Maisy
Maisy

Reputation: 23

Why does this only work with a return statement here?

I just started to teach myself java with no prior programming experience and I just completed the functional programming course in Udacity. While making a Tic Tac Toe game as the final project, I am required to program a function that checks for a winner or tie. The game is represented as a 2d array and everything else is already given; my only job is code the checkGameWinner function. I've completed the code and gotten it to work; but in the interest of fully understanding Java, I want to ask the following:

    public String checkGameWinner(char [][]grid){
    String result = "None";
    //Student code goes here ...

    if(grid[1][1]=='x' && grid[1][0]=='x'&& grid[1][2]=='x'){     
        result = "X wins";                                       
    }
    else if(grid[1][1]=='x' && grid[0][1]=='x'&& grid[2][1]=='x'){
        result = "X wins";
    }
    else if(grid[1][1]=='x' && grid[0][0]=='x' && grid[2][2]=='x'){
        result = "X wins";
    }
    else if(grid[1][1]=='x' && grid[0][2]=='x' && grid[2][0]=='x'){
        result = "X wins";
    }
    else if(grid[0][0]=='x' && grid[1][0]=='x' && grid[2][0]=='x'){
        result = "X wins";
    }
    else if(grid[2][0]=='x' && grid[2][1]=='x' && grid[2][2]=='x'){
        result = "X wins";
    }
    else if(grid[0][2]=='x' && grid[1][2]=='x' && grid[2][2]=='x'){
        result = "X wins";
    }
    else if(grid[0][0]=='x' && grid[0][1]=='x' && grid[0][2]=='x'){
        result = "X wins";
    }

    else if(grid[1][1]=='o' && grid[1][0]=='o'&& grid[1][2]=='o'){ 
        result = "O wins";                                       
    }
    else if(grid[1][1]=='o' && grid[0][1]=='o'&& grid[2][1]=='o'){
        result = "O wins";
    }
    else if(grid[1][1]=='o' && grid[0][0]=='o' && grid[2][2]=='o'){
        result = "O wins";
    }
    else if(grid[1][1]=='o' && grid[0][2]=='o' && grid[2][0]=='o'){
        result = "O wins";
    }
    else if(grid[0][0]=='o' && grid[1][0]=='o' && grid[2][0]=='o'){
        result = "O wins";
    }
    else if(grid[2][0]=='o' && grid[2][1]=='o' && grid[2][2]=='o'){
        result = "O wins";
    }
    else if(grid[0][2]=='o' && grid[1][2]=='o' && grid[2][2]=='o'){
        result = "O wins";
    }
    else if(grid[0][0]=='o' && grid[0][1]=='o' && grid[0][2]=='o'){
        result = "O wins";
    }

    else {
        for (int i = 0; i < 3; i++) {       
            for (int j = 0; j < 3; j++) {    
                if (grid[i][j] == '-') {
                    result = "None";
                    return result;        
                } else {
                    result = "Tie";
                }
            }
        }
    }




    return result;
}

My logic was that I would first check for all of the 16 different winning combinations, then check if any of the cells in the array were empty using a for loop(which if they were the function returns "None" and the game proceeds). Finally, if there are no winning combinations and no empty spaces, the game is a tie and I left that as the last statement. I found that in order for the above code to work as intended, I needed to include an additional return statement immediately after the if statement in the double for loop(the one checking for empty spaces). If this return was not added, the game would end and be declared a Tie at incorrect moments, even when empty spaces were available. My question is why is this return necessary? If the boolean value of the if statement under the for loop is true(i.e. there are ANY empty spaces), then shouldn't the variable "result" be updated as "none" and the following else statement skipped, therefore exiting the for loop, and then going to the final return at the end of the code?. I've read that generally you don't want more than one return in any one function, but I'm not sure how true this is. I hope this was understandable and if anyone has any insight or help they can give this beginning programmer would be very appreciative. Thank you. P.S. Empty spaces are represented by the '-' character.

Upvotes: 2

Views: 359

Answers (3)

johngeffert
johngeffert

Reputation: 11

Working on the same udacity course I had a very similar experience trying to figure out where to place the final 'if' statement evaluating for a tie in order for the program to step through the function correctly; and I ran into the same issue of it not working if I didn't also have the very last 'return' statement in there. Thanks for all the discussion on ending the for loops better. I finally came up with this method for evaluating for a tie.

public String checkGameWinner(char[][] grid) {
    String result = "None";
    char[] letter = {'x', 'o'};
    String[] otherResults = {"X Wins", "O Wins", "Tie"};
    int isTie = 0;

    //checks for win on both diagonals
    for (int i = 0; i < letter.length; i++) {
        if (grid[0][0] == letter[i] && grid[1][1] == letter[i] && grid[2][2] == letter[i]) {
            return otherResults[i];
        }
        if (grid[0][2] == letter[i] && grid[1][1] == letter[i] && grid[2][0] == letter[i]) {
            return otherResults[i];
        }
        for (int j = 0; j < grid.length; j++) {
            //Checks for win on rows
            if (grid[0][j] == letter[i] && grid[1][j] == letter[i] && grid[2][j] == letter[i]) {
                return otherResults[i];
            }
            //Checks for win on columns
            if (grid[j][0] == letter[i] && grid[j][1] == letter[i] && grid[j][2] == letter[i]) {
                return otherResults[i];
            }
        }
    }
    // checks for tie or draw
    for (int i = 0; i < grid.length; i++) {
        for (int j = 0; j < grid.length; j++) {
            if (grid[i][j] == 'x' || grid[i][j] == 'o') {
                isTie = isTie + 1;
            }
        }
    }
    if (isTie == 9){
        return otherResults [2];
    }
    return result;
}

Upvotes: 1

minigeek
minigeek

Reputation: 3166

By looking at your code,you want to stop when you get the result none and then you return.

If you want only one return statement so as to return result immediately after you find "None" Use the break statement to cut the loop.

Old code

for (int i = 0; i < 3; i++) { 
      for (int j = 0; j < 3; j++) { 
            if (grid[i][j] == '-') { 
                result = "None";
                return result; 
            } 
           else { 
                result = "Tie"; 
           } 
      } 
  } 
 return result;

New code (corrected)

  result = "Tie";
  outeerloop:
  for (int i = 0; i < 3; i++) { 
      for (int j = 0; j < 3; j++) { 
            if (grid[i][j] == '-') { 
                result = "None";
                break outerloop;
            }
      } 
  } 
 return result;

Now whatever will be stored in result will be returned.earlier even if you get result none and without return statement in if statement it used to iterate again and change the value to tie.

Upvotes: 0

D.B.
D.B.

Reputation: 4713

Consider the situation where your double for loop finds a "blank" space before it reaches the end of the 2D array.

Without the return if it encounters a non-blank space after this blank space it will declare a tie unless it encounters another blank space and then the process repeats - if another non-blank is found the result changes, etc until the end of the array is reached.

In other words the loops do not stop unless their condition for continuing results in a value of false or you have a break or return inside the loop. Having the return in there breaks out of not just the loops but the entire method once it encounters a blank space.

Upvotes: 1

Related Questions