0

There's a game with 9 colored squared. A random one of those colors is displayed on the screen, in one of those 9 colors (e.g: 'orange' in green). The user scores a point when they tap the colored square which corresponds with the word, ignoring the color of the word (e.g if 'orange' in any color and orange square is tapped, one point is added to score). All these color strings are stored in an array (colorString[]). When the score reaches 10, I introduce new values to the colorString array in the onClick method of each button. The values are ciphered versions of each color string. The issue is, even when the right color boxed is tapped for the ciphered value, the score goes no higher than 10. The newer array values are not working. All is explained in the code below:

int score = 0;
Random colStr = new Random();
int decider = colStr.nextInt(9);

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game3);



final Button loseStarter3;

    loseStarter3 = (Button) findViewById(R.id.Starter3);
    loseStarter3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            infoG3.setVisibility(View.GONE);
            loseStarter3.setVisibility(View.GONE);
            final TextView word = (TextView) findViewById(R.id.word);
            word.setVisibility(View.VISIBLE);
            greenButton.setVisibility(View.VISIBLE);
            purpleButton.setVisibility(View.VISIBLE);
            blueButton.setVisibility(View.VISIBLE);
            blackButton.setVisibility(View.VISIBLE);
            redButton.setVisibility(View.VISIBLE);
            whiteButton.setVisibility(View.VISIBLE);
            brownButton.setVisibility(View.VISIBLE);
            orangeButton.setVisibility(View.VISIBLE);
            yellowButton.setVisibility(View.VISIBLE);

                final String[] colorString = new String[9];
                colorString[0] = "yellow";
                colorString[1] = "red";
                colorString[2] = "green";
                colorString[3] = "black";
                colorString[4] = "white";
                colorString[5] = "purple";
                colorString[6] = "blue";
                colorString[7] = "brown";
                colorString[8] = "orange";
                word.setText(colorString[decider]);

                int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                word.setTextColor(randomAndroidColor);

                yellowButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (word.getText() == colorString[0] || word.getText() == colorString[9] || word.getText() == colorString[10] || word.getText() == colorString[11]) {
                            score++;
                        }
                        Random colStr = new Random();
                        if (score<=9) {
                            int decider = colStr.nextInt(9);
                            final String[] colorString = new String[9];
                            colorString[0] = "yellow";
                            colorString[1] = "red";
                            colorString[2] = "green";
                            colorString[3] = "black";
                            colorString[4] = "white";
                            colorString[5] = "purple";
                            colorString[6] = "blue";
                            colorString[7] = "brown";
                            colorString[8] = "orange";
                            word.setText(colorString[decider]);
                        }
                        if (score>9) {
                            int decider = colStr.nextInt(27)+9;
                            final String[] colorString = new String[36];
                            colorString[0] = "yellow";
                            colorString[1] = "red";
                            colorString[2] = "green";
                            colorString[3] = "black";
                            colorString[4] = "white";
                            colorString[5] = "purple";
                            colorString[6] = "blue";
                            colorString[7] = "brown";
                            colorString[8] = "orange";
                            colorString[9] = "weyoll";
                            colorString[10] = "loyelw";
                            colorString[11] = "oelwyl";
                            colorString[12] = "erd";
                            colorString[13] = "der";
                            colorString[14] = "edr";
                            colorString[15] = "enrge";
                            colorString[16] = "regne";
                            colorString[17] = "nerge";
                            colorString[18] = "lcbka";
                            colorString[19] = "alkcb";
                            colorString[20] = "cbakl";
                            colorString[21] = "ihewt";
                            colorString[22] = "thewi";
                            colorString[23] = "ewthi";
                            colorString[24] = "relppu";
                            colorString[25] = "ulrpep";
                            colorString[26] = "leprpu";
                            colorString[27] = "ebul";
                            colorString[28] = "lbeu";
                            colorString[29] = "ulbe";
                            colorString[30] = "rbwno";
                            colorString[31] = "wobnr";
                            colorString[32] = "onwrb";
                            colorString[33] = "agonre";
                            colorString[34] = "negrao";
                            colorString[35] = "greaon";
                            word.setText(colorString[decider]);
                        }

                        int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                        int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                        word.setTextColor(randomAndroidColor);
                    }
                });

                redButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (word.getText() == colorString[1]) {
                            score++;
                        }
                        Random colStr = new Random();
                        if (score<=9) {
                            int decider = colStr.nextInt(9);
                            final String[] colorString = new String[9];
                            colorString[0] = "yellow";
                            colorString[1] = "red";
                            colorString[2] = "green";
                            colorString[3] = "black";
                            colorString[4] = "white";
                            colorString[5] = "purple";
                            colorString[6] = "blue";
                            colorString[7] = "brown";
                            colorString[8] = "orange";
                            word.setText(colorString[decider]);
                        }
                        if (score>9) {
                            int decider = colStr.nextInt(27) + 9;
                            final String[] colorString = new String[36];
                            colorString[0] = "yellow";
                            colorString[1] = "red";
                            colorString[2] = "green";
                            colorString[3] = "black";
                            colorString[4] = "white";
                            colorString[5] = "purple";
                            colorString[6] = "blue";
                            colorString[7] = "brown";
                            colorString[8] = "orange";
                            colorString[9] = "weyoll";
                            colorString[10] = "loyelw";
                            colorString[11] = "oelwyl";
                            colorString[12] = "erd";
                            colorString[13] = "der";
                            colorString[14] = "edr";
                            colorString[15] = "enrge";
                            colorString[16] = "regne";
                            colorString[17] = "nerge";
                            colorString[18] = "lcbka";
                            colorString[19] = "alkcb";
                            colorString[20] = "cbakl";
                            colorString[21] = "ihewt";
                            colorString[22] = "thewi";
                            colorString[23] = "ewthi";
                            colorString[24] = "relppu";
                            colorString[25] = "ulrpep";
                            colorString[26] = "leprpu";
                            colorString[27] = "ebul";
                            colorString[28] = "lbeu";
                            colorString[29] = "ulbe";
                            colorString[30] = "rbwno";
                            colorString[31] = "wobnr";
                            colorString[32] = "onwrb";
                            colorString[33] = "agonre";
                            colorString[34] = "negrao";
                            colorString[35] = "greaon";
                            word.setText(colorString[decider]);
                        }

                        int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                        int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                        word.setTextColor(randomAndroidColor);
                    }
                });

                greenButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (word.getText() == colorString[2]) {
                            score++;
                        }
                        Random colStr = new Random();
                        if (score<=9) {
                            int decider = colStr.nextInt(9);
                            final String[] colorString = new String[9];
                            colorString[0] = "yellow";
                            colorString[1] = "red";
                            colorString[2] = "green";
                            colorString[3] = "black";
                            colorString[4] = "white";
                            colorString[5] = "purple";
                            colorString[6] = "blue";
                            colorString[7] = "brown";
                            colorString[8] = "orange";
                            word.setText(colorString[decider]);
                        }
                        if (score>9) {
                            int decider = colStr.nextInt(27) + 9;
                            final String[] colorString = new String[36];
                            colorString[0] = "yellow";
                            colorString[1] = "red";
                            colorString[2] = "green";
                            colorString[3] = "black";
                            colorString[4] = "white";
                            colorString[5] = "purple";
                            colorString[6] = "blue";
                            colorString[7] = "brown";
                            colorString[8] = "orange";
                            colorString[9] = "weyoll";
                            colorString[10] = "loyelw";
                            colorString[11] = "oelwyl";
                            colorString[12] = "erd";
                            colorString[13] = "der";
                            colorString[14] = "edr";
                            colorString[15] = "enrge";
                            colorString[16] = "regne";
                            colorString[17] = "nerge";
                            colorString[18] = "lcbka";
                            colorString[19] = "alkcb";
                            colorString[20] = "cbakl";
                            colorString[21] = "ihewt";
                            colorString[22] = "thewi";
                            colorString[23] = "ewthi";
                            colorString[24] = "relppu";
                            colorString[25] = "ulrpep";
                            colorString[26] = "leprpu";
                            colorString[27] = "ebul";
                            colorString[28] = "lbeu";
                            colorString[29] = "ulbe";
                            colorString[30] = "rbwno";
                            colorString[31] = "wobnr";
                            colorString[32] = "onwrb";
                            colorString[33] = "agonre";
                            colorString[34] = "negrao";
                            colorString[35] = "greaon";
                            word.setText(colorString[decider]);
                        }

                        int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                        int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                        word.setTextColor(randomAndroidColor);
                    }
                });

                /*etc... for other buttons, same contents but different color name*/

I AM AWARE THAT I HAVE ONLY USED || OTHER ARRAY VALUES FOR YELLOW, THIS IS JUST AN EXAMPLE. I have also tried using individual if statements below the colorString[0] one to add scores when == to the other values, and else if. Neither worked, they just crashed the app. I've also tried different button, not that is should make a difference. I tried changing the order of where the if statement is, only to fail again. I've spent a while trying to resolve this, but have unfortunately not been able to resolve this.

Would appreciate it if someone could provide me with a fix, to ensure these other array values are accepted. If there is something I haven't made clear, all is shown in the code I have posted. Many thanks in advance.

UPDATED CODE:

final String[] colorString1 = new String[9];
                colorString1[0] = "yellow";
                colorString1[1] = "red";
                colorString1[2] = "green";
                colorString1[3] = "black";
                colorString1[4] = "white";
                colorString1[5] = "purple";
                colorString1[6] = "blue";
                colorString1[7] = "brown";
                colorString1[8] = "orange";
                word.setText(colorString1[decider]);

            final String[] colorString2 = new String[36];

                int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                word.setTextColor(randomAndroidColor);

                yellowButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (word.getText().equals(colorString1[0])) {
                            score++;
                        }
                        if (word.getText().equals(colorString2[9])) {
                            score++;
                        }
                        if (word.getText().equals(colorString2[10])) {
                            score++;
                        }
                        if (word.getText().equals(colorString2[11])) {
                            score++;
                        }
                        Random colStr = new Random();
                        if (score<=9) {
                            int decider = colStr.nextInt(9);
                            final String[] colorString1 = new String[9];
                            colorString1[0] = "yellow";
                            colorString1[1] = "red";
                            colorString1[2] = "green";
                            colorString1[3] = "black";
                            colorString1[4] = "white";
                            colorString1[5] = "purple";
                            colorString1[6] = "blue";
                            colorString1[7] = "brown";
                            colorString1[8] = "orange";
                            word.setText(colorString1[decider]);
                        }
                        if (score>9) {
                            int decider = colStr.nextInt(27)+9;
                            final String[] colorString2 = new String[36];
                            colorString2[0] = "yellow";
                            colorString2[1] = "red";
                            colorString2[2] = "green";
                            colorString2[3] = "black";
                            colorString2[4] = "white";
                            colorString2[5] = "purple";
                            colorString2[6] = "blue";
                            colorString2[7] = "brown";
                            colorString2[8] = "orange";
                            colorString2[9] = "weyoll";
                            colorString2[10] = "loyelw";
                            colorString2[11] = "oelwyl";
                            colorString2[12] = "erd";
                            colorString2[13] = "der";
                            colorString2[14] = "edr";
                            colorString2[15] = "enrge";
                            colorString2[16] = "regne";
                            colorString2[17] = "nerge";
                            colorString2[18] = "lcbka";
                            colorString2[19] = "alkcb";
                            colorString2[20] = "cbakl";
                            colorString2[21] = "ihewt";
                            colorString2[22] = "thewi";
                            colorString2[23] = "ewthi";
                            colorString2[24] = "relppu";
                            colorString2[25] = "ulrpep";
                            colorString2[26] = "leprpu";
                            colorString2[27] = "ebul";
                            colorString2[28] = "lbeu";
                            colorString2[29] = "ulbe";
                            colorString2[30] = "rbwno";
                            colorString2[31] = "wobnr";
                            colorString2[32] = "onwrb";
                            colorString2[33] = "agonre";
                            colorString2[34] = "negrao";
                            colorString2[35] = "greaon";
                            word.setText(colorString2[decider]);
                        }

                        int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                        int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                        word.setTextColor(randomAndroidColor);
                    }
                });

                redButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (word.getText() == colorString1[1]) {
                            score++;
                        }
                        Random colStr = new Random();
                        if (score<=9) {
                            int decider = colStr.nextInt(9);
                            final String[] colorString1 = new String[9];
                            colorString1[0] = "yellow";
                            colorString1[1] = "red";
                            colorString1[2] = "green";
                            colorString1[3] = "black";
                            colorString1[4] = "white";
                            colorString1[5] = "purple";
                            colorString1[6] = "blue";
                            colorString1[7] = "brown";
                            colorString1[8] = "orange";
                            word.setText(colorString1[decider]);
                        }
                        if (score>9) {
                            int decider = colStr.nextInt(27)+9;
                            final String[] colorString2 = new String[36];
                            colorString2[0] = "yellow";
                            colorString2[1] = "red";
                            colorString2[2] = "green";
                            colorString2[3] = "black";
                            colorString2[4] = "white";
                            colorString2[5] = "purple";
                            colorString2[6] = "blue";
                            colorString2[7] = "brown";
                            colorString2[8] = "orange";
                            colorString2[9] = "weyoll";
                            colorString2[10] = "loyelw";
                            colorString2[11] = "oelwyl";
                            colorString2[12] = "erd";
                            colorString2[13] = "der";
                            colorString2[14] = "edr";
                            colorString2[15] = "enrge";
                            colorString2[16] = "regne";
                            colorString2[17] = "nerge";
                            colorString2[18] = "lcbka";
                            colorString2[19] = "alkcb";
                            colorString2[20] = "cbakl";
                            colorString2[21] = "ihewt";
                            colorString2[22] = "thewi";
                            colorString2[23] = "ewthi";
                            colorString2[24] = "relppu";
                            colorString2[25] = "ulrpep";
                            colorString2[26] = "leprpu";
                            colorString2[27] = "ebul";
                            colorString2[28] = "lbeu";
                            colorString2[29] = "ulbe";
                            colorString2[30] = "rbwno";
                            colorString2[31] = "wobnr";
                            colorString2[32] = "onwrb";
                            colorString2[33] = "agonre";
                            colorString2[34] = "negrao";
                            colorString2[35] = "greaon";
                            word.setText(colorString2[decider]);
                        }

                        int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                        int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                        word.setTextColor(randomAndroidColor);
                    }
                });

                greenButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (word.getText() == colorString1[2]) {
                            score++;
                        }
                        Random colStr = new Random();
                        if (score<=9) {
                            int decider = colStr.nextInt(9);
                            final String[] colorString1 = new String[9];
                            colorString1[0] = "yellow";
                            colorString1[1] = "red";
                            colorString1[2] = "green";
                            colorString1[3] = "black";
                            colorString1[4] = "white";
                            colorString1[5] = "purple";
                            colorString1[6] = "blue";
                            colorString1[7] = "brown";
                            colorString1[8] = "orange";
                            word.setText(colorString1[decider]);
                        }
                        if (score>9) {
                            int decider = colStr.nextInt(27)+9;
                            final String[] colorString2 = new String[36];
                            colorString2[0] = "yellow";
                            colorString2[1] = "red";
                            colorString2[2] = "green";
                            colorString2[3] = "black";
                            colorString2[4] = "white";
                            colorString2[5] = "purple";
                            colorString2[6] = "blue";
                            colorString2[7] = "brown";
                            colorString2[8] = "orange";
                            colorString2[9] = "weyoll";
                            colorString2[10] = "loyelw";
                            colorString2[11] = "oelwyl";
                            colorString2[12] = "erd";
                            colorString2[13] = "der";
                            colorString2[14] = "edr";
                            colorString2[15] = "enrge";
                            colorString2[16] = "regne";
                            colorString2[17] = "nerge";
                            colorString2[18] = "lcbka";
                            colorString2[19] = "alkcb";
                            colorString2[20] = "cbakl";
                            colorString2[21] = "ihewt";
                            colorString2[22] = "thewi";
                            colorString2[23] = "ewthi";
                            colorString2[24] = "relppu";
                            colorString2[25] = "ulrpep";
                            colorString2[26] = "leprpu";
                            colorString2[27] = "ebul";
                            colorString2[28] = "lbeu";
                            colorString2[29] = "ulbe";
                            colorString2[30] = "rbwno";
                            colorString2[31] = "wobnr";
                            colorString2[32] = "onwrb";
                            colorString2[33] = "agonre";
                            colorString2[34] = "negrao";
                            colorString2[35] = "greaon";
                            word.setText(colorString2[decider]);
                        }

                        int[] androidColors = getResources().getIntArray(R.array.androidcolors);
                        int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
                        word.setTextColor(randomAndroidColor);
                    }
                });
/* same for other colored buttons */
H3ll0
  • 259
  • 1
  • 3
  • 16
  • Beside the Answer of Zarki to use the correct comparison for strings. From the above code and usage of `final String[] colorString` I'd assume that after `score>9` the text is selected from the `final String[] colorString = new String[36];` in the `if` block. But the check of `word` is done against the outer scopes `final String[] colorString = new String[9];`. Since this is just example code, it's not clear if this is an issue in your real code. – makadev Oct 31 '16 at 22:50
  • @makadev This is my real code, I meant the use of the 'or' symbols were an example of one of my attempted solutions. Can you please specify my issue is and how to resolve it? I have tried putting if statements in various positions, as mentioned, with no success. What is it you believe I must do? I will try Zarki's suggestions when I access my project later today, though what confuses me is that when using == the points add just fine for a score up to 10. Last I remembered, using = for strings game me an error. I'll check again for sure, your response is greatly appreciated. – H3ll0 Nov 01 '16 at 10:55
  • I'll add another answer since it may get a bit longer. – makadev Nov 01 '16 at 13:18

2 Answers2

1

When you compare your Strings you do it with "==" (which means you are comparing the references of 2 objects), you should use "equals" methods to check that both values are equals.

Zarki
  • 76
  • 7
0

If I strip down your code and change final String[] colorString declarations into colorString1, colorString2, colorString3, ... it looks like this:

...
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    loseStarter3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ...
            final String[] colorString1 = new String[9];
            ...
            yellowButton.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     if (word.getText().equals(colorString1[0]) ... ) {
                         score++;
                     }
                     Random colStr = new Random();
                     if (score<=9) {
                         final String[] colorString2 = new String[9];
                         ...
                     }
                     if (score>9) {
                         final String[] colorString3 = new String[36];
                         ...
                     }

So if yellowButton is clicked - with checks according to Zarki - it will check with word.getText().equals(colorString1[0]) which will never check on colorString3 with 36 entries.

There are multiple ways to solve this.

  • make colorString a member variable of the most outer class which is probably the activity in your case, it won't need to be final and can be set with string array (fast solution)
  • a good idea in general is to pull out all the duplicated array initializations into a separate class, it could have switchX methods to switch between 9 and 36 names like

    public class ColorField {
       private String[] colorString = new String[36];
       private int length = 9;
       public ColorField() {
         // init colorString
       }
    
       public void switchTo9() {
         this.length = 9;
       }
    
       public void switchTo36() {
         this.length = 36;
       }
    
       public int getLength() {
         return this.length;
       }
    
       public String getField(int idx) {
         // sanity checks omitted
         return colorString[idx];
       }
    
       // more stuff
    }
    

UPDATE:

Ok, your update is another possibility. Now you can remove the inner colorString since you have them in the outer closure already - that may not help against bugs, but it shortens code and makes it more readable. Notice how colorString1 is useless too, you could remove it completely and only use colorString2.

Anyway, I added some comments on what happens now in the code and some changes for the decider - removed the inner declaration too - and word setting.

// declare "colorString2"
final String[] colorString2 = new String[36];
// initialize with values
colorString2[0] = "yellow";
colorString2[1] = "red";
colorString2[2] = "green";
colorString2[3] = "black";
colorString2[4] = "white";
colorString2[5] = "purple";
colorString2[6] = "blue";
colorString2[7] = "brown";
colorString2[8] = "orange";
colorString2[9] = "weyoll";
colorString2[10] = "loyelw";
colorString2[11] = "oelwyl";
colorString2[12] = "erd";
colorString2[13] = "der";
colorString2[14] = "edr";
colorString2[15] = "enrge";
colorString2[16] = "regne";
colorString2[17] = "nerge";
colorString2[18] = "lcbka";
colorString2[19] = "alkcb";
colorString2[20] = "cbakl";
colorString2[21] = "ihewt";
colorString2[22] = "thewi";
colorString2[23] = "ewthi";
colorString2[24] = "relppu";
colorString2[25] = "ulrpep";
colorString2[26] = "leprpu";
colorString2[27] = "ebul";
colorString2[28] = "lbeu";
colorString2[29] = "ulbe";
colorString2[30] = "rbwno";
colorString2[31] = "wobnr";
colorString2[32] = "onwrb";
colorString2[33] = "agonre";
colorString2[34] = "negrao";
colorString2[35] = "greaon";

// select first color string to be used for as word
word.setText(colorString2[decider]);
// select first visual color to be used for word
int[] androidColors =getResources().getIntArray(R.array.androidcolors);
int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
word.setTextColor(randomAndroidColor);

// create click listener for yellow button
yellowButton.setOnClickListener(new View.OnClickListener() {
    @Override
        public void onClick(View v) {
            // on click, check if word color is matching
            // this buttons color and increase score
            if (word.getText().equals(colorString2[0])) {
                score++;
            }
            if (word.getText().equals(colorString2[9])) {
                score++;
            }
            if (word.getText().equals(colorString2[10])) {
                score++;
            }
            if (word.getText().equals(colorString2[11])) {
                score++;
            }
            // select new color string with difficulty level
            // depending on score
            Random colStr = new Random();
            if (score<=9) {
                decider = colStr.nextInt(9);
            }
            if (score>9) {
                decider = colStr.nextInt(27)+9;
            }
            word.setText(colorString2[decider]);
            // set new visual color
            int[] androidColors = getResources().getIntArray(R.array.androidcolors);
            int randomAndroidColor = androidColors[new Random().nextInt(androidColors.length)];
            word.setTextColor(randomAndroidColor);
        }
    });

/* same for other colored buttons */

IN DEPTH EXPLANATION:

For the beginning, since I don't know on which knowledge level you are, I'll clear up some Words - very short and only in Java context - with references so you can find much more information if needed.

(Variable) Declaration: A variable declaration introduces a variable with its name, type and other attributes - not to be mixed up with definition and use:

// Declaration: declares variable colorString of type String[]
String[] colorString;
// Definition: define/set/assign the "content" of variable colorString
colorString = new String[36];
// Use: access the "content" of variable colorString
if (word.equals(colorString[6]) { }

NOTE: final means that the variable can only be defined once so - the first definition is called initalization and so on:

final String[] colorString = new String[36];
// now this should be an error
colorString = new String[9];

Scope: I can't say it any less complex as this sentence from English Wikipedia:

The scope of a variable describes where in a program's text the variable may be used ...

In the above example of Declaration, Definition and Use this all happens in the same Scope. Scopes can be nested which means that you can define/use variables from multiple scopes like:

// SCOPE0 - contains "Sample" and all classes/interfaces... available
class Sample {
     // SCOPE1 - contains all from SCOPE0 and "Variable1" and "something"
     private Integer Variable1 = 0;
     function void something() {
         // now here it gets special, a variable is only visible after
         // declaration so java basically has a new local scope for each declaration
         // SCOPE2 - contains all from SCOPE1 and some specials like `this`
         Integer Variable2 = 1;
         // SCOPE3 - contains all from SCOPE1 and "Variable2"
         if(Variable1.equals(Variable2)) {
            // SCOPE4 - contains all from SCOPE3 
            Integer Variable3 = 2;
            // SCOPE5 - contains all from SCOPE4 and "Variable3" 

            // END OF SCOPE5 and SCOPE4
         }
         // now this will give an error because "Variable3" is not visible anymore
         Variable2 = Variable3;
         // END OF SCOPE3 and SCOPE2
     }
}

Scopes are tied to static binding. The compiler can statically - meaning on compilation - collect all information needed to know which name at which position in code means which variable, method, class and so on.

The differences in the scopes are defined by the language or static binding mechanism. For example in SCOPE1 all members declared in that class are visible. Whereas in SCOPE3 the declaration creates a new scope and the variable is only visible within this scope.

As you see a variable is in general declared only in one Scope but defined/used in the same and nested Scopes. Now it gets more funny when a Programming language allows to override a name in nested scopes:

class Sample {
     private Integer Variable1 = 0;
     function void something() {
         // Local variable gets the same name as the member "Variable1"
         Integer Variable1 = 1;
         // now we need to use "this.Variable1" to access the "outer"
         // scopes "Variable1" because the name "Variable1" is bound to
         // the local variable "Variable1"
         if(Variable1.equals(this.Variable1)) {
            // Local - meaning in the method body - Scope overrides are not allowed so this gives an error 
            Integer Variable1 = 2;
         }
     }
}

Closure: Be warned.. the wiki article is a bit "overcomplexified" and the first 2 sentences mix in scopes, binding, "first-class functions", variable captures and so on..

Lets reduce that and say a closure is a part of the program which has a dynamic execution context - meaning a context with variables and some more that is created on runtime.

Java local Classes (Closure):

Java local classes - or anonymous classes - are an example of closures in java. Still, nested scopes work much the same, it just gets ugly when you think about how every execution of the local class definition basically "creates a new class" which binds to the same names - the "captured variables".

Lets check out your original code and apply that knowledge of declarations, scopes and stuff and give them scopes names.

// Outer Scope of Activity: SCOPE_MAIN
...
@Override
protected void onCreate(Bundle savedInstanceState) {
    // Local Scope of onCreate Method: SCOPE_OUTER_MLOCAL
    ...
    loseStarter3.setOnClickListener(new View.OnClickListener() {
        // Outer Closure
        // anonymous class/closure with closures Scope: SCOPE_OUTER_CLOSURE
        @Override
        public void onClick(View v) {
            // Local Scope of onClick Method: SCOPE_OUTER_CLOSURE_MLOCAL
            ...
            final String[] colorString = new String[9];
            ...
            yellowButton.setOnClickListener(new View.OnClickListener() {
                 // Inner Closure
                 // Scope: SCOPE_INNER_CLOSURE
                 @Override
                 public void onClick(View v) {
                     // Local Scope: SCOPE_INNER_CLOSURE_MLOCAL
                     // NOTICE that colorString is the USE of colorString DECLARED in SCOPE_OUTER_CLOSURE_MLOCAL
                     if (word.getText().equals(colorString[0]) ... ) {
                         score++;
                     }
                     Random colStr = new Random();
                     if (score<=9) {
                         // Scope introduced with declaration: SCOPE_INNER_CLOSURE_MLOCAL_SUB1
                         final String[] colorString = new String[9];
                         ...
                         // This actually select the string from SCOPE_INNER_CLOSURE_MLOCAL_SUB1
                         word.setText(colorString[decider]);
                         // End of SCOPE_INNER_CLOSURE_MLOCAL_SUB1
                         // the here declared colorString does not exist anymore after this is executed
                     }
                     if (score>9) {
                         // Scope introduced with declaration: SCOPE_INNER_CLOSURE_MLOCAL_SUB2
                         final String[] colorString = new String[36];
                         ...
                         word.setText(colorString[decider]);
                     }

Maybe now it makes more sense what I wrote before. The check word.getText().equals(colorString[0]) in onClick of yellowButtons click listener checks against colorString from SCOPE_OUTER_CLOSURE_MLOCAL Scope which is always the same with only 9 entries.

When score goes up to 9, the string for word is selected from colorString in SCOPE_INNER_CLOSURE_MLOCAL_SUB2 but that array ceases to exist after the scope is left.

What you probably tried to do is to replace colorString from SCOPE_OUTER_CLOSURE_MLOCAL but that does not work that way for once because of final and second because you just declared a new variable in SCOPE_INNER_CLOSURE_MLOCAL_SUB1 or SCOPE_INNER_CLOSURE_MLOCAL_SUB2 which stops to exist after the word was set.

The updated code which only uses 1/2 variable(s) and initialization for colorString does not have these problems because it only uses the variables declared in SCOPE_OUTER_CLOSURE_MLOCAL so it simply eliminated the problem of setting colorString within the second closure.


Now, why did == work sporadically instead of equals and why should you use equals instead of ==?

This goes even farther and involves string constant pool and what string objects are actually flying around. == is a reference/address comparison, meaning it checks if the left parameter is stored at the same address than the right parameter which in turn means it checks if both are the same object.

It may work in your case because of implicit interning but it can break as fast - and very hard to debug - when something creates and passes back a copy without your knowledge like f.e. some third party code. For example I wouldn't trust in word.setText and word.getText to take and return the same string objects.

The rule of thumb is those: use equals if you compare content, use == if you compare primitives/references and you actually know what references are flying around. Because equals is simple, but == can really produce headaches especially if you don't have control over all these references.

Hope that helps a bit.

Community
  • 1
  • 1
makadev
  • 1,034
  • 15
  • 26
  • Please see my updated code. As far as I'm aware, I followed both yours and Zarki's advice but still have the same issue. Only difference is, the app doesn't crash whenever yellow is tapped now. The points do not go up after 10, like before. Please correct me on anything I have done wrong here, thank you. – H3ll0 Nov 01 '16 at 19:35
  • @H3ll0 see my update, I've shortened the code a bit to make it better readable. In your update you forgot to initialize the outer `colorString2` which is used for the checks, so it was much like the problem before: colors selected in the inner but checked with the outer which was not initialized for the checks. – makadev Nov 02 '16 at 10:02
  • Removed the repeated initiations and initialized it out of the buttons, seemed to do the trick. Works flawlessly now, thank you. What I want to know, is what exactly was my flaw? What was it that caused my program to fail? I haven't tested it after its success, but would going back to == make it fail again? Was it simply creating two colorString variables that did it. If so, why? Would greatly appreciate an explantation, thank you. – H3ll0 Nov 02 '16 at 21:07
  • @H3ll0 The initial Code had both problems with the `==` comparison and inner `colorString` re-declaration. Your update should work with correct `colorString2` initialization and `equals` but not with `==`. The last update which only has the outer `colorString2` - and maybe `colorString1` - gets the `word` string from the **same** `colorString` array which it compares to later. So `==` **may** work because `word.getText()` and the checked string from array **may** be the same objects - those have same address. But the `==` check can easily break so better use `equals` for content comparision. – makadev Nov 03 '16 at 06:05
  • @H3ll0 For the *why simply creating two variables* removes the problem: Well that may be a longer explanation but I'll try to add some example to visualize it. – makadev Nov 03 '16 at 06:19
  • Are you saying that declaring colorString and initializing it again in each button also contributed to my issue? I don't believe it made it a difference when I first tested this with success yesterday. I thought it was just extra unnecessary code, as you suggested. I'll test that later today and get back to you, but yes it's successful now with the guidance you provided. And I still don't understand why two different colorString variables are needed. It appears that declaring and initializing the same array (but one with more values) has solved my issue, as well as the .equals(). – H3ll0 Nov 03 '16 at 08:20
  • @H3ll0 so, I've added some in depth explanation under *IN DEPTH EXPLANATION:* about what actually goes on and produces the problem. Read it few times and sleep about it. – makadev Nov 03 '16 at 11:10
  • I'll get to reading that sometime, and will ensure to have sweet dreams about it indeed. Many thanks for your effort, appreciate it. – H3ll0 Nov 03 '16 at 17:09