Check Old Play Winner

Asked

Viewed 4,816 times

21

The algorithm teacher asked us to write a code to make a simple old game in Java. And I already have everything ready only I’m not very happy with the solution I found to validate who won the game.

I did a series of if and elseifs to check each condition in which a player can win the game. And all right, that covers what the professor asked for, only I don’t think that’s the smartest way to write an algorithm. I was thinking about using embedded repeats (go inside for) but I can’t find a way where I can apply this to the algorithm, or maybe a lot of thinking I can’t think anymore.

I also thought of creating a matrix with all possible possibilities:

   final int[][][] condicoesVencer = {
    //COLUNAS
    {{ 0, 0 }, { 1, 0 }, { 2, 0 }},
    {{ 0, 1 }, { 1, 1 }, { 2, 1 }},
    {{ 0, 2 }, { 1, 2 }, { 2, 2 }},

    //LINHAS
    {{ 0, 0 }, { 0, 1 }, { 0, 2 }},
    {{ 1, 0 }, { 1, 1 }, { 1, 2 }},
    {{ 2, 0 }, { 2, 1 }, { 2, 2 }},

    //DIAGONAIS
    {{ 0, 0 }, { 1, 1 }, { 2, 2 }},
    {{ 2, 0 }, { 1, 1 }, { 0, 2 }}
};

condicoesVencer holds all possible winning combinations, vector positions char tabuleiro[][] = new char[3][3] where X or O can win. But I couldn’t find a way to go through the two vectors in order to check on the vector board each condition in the vector condicoesVencer and now I don’t know what to do.

How do I replace the lot of ifs I did with something 'smart'? Please, if you have an answer, send the code and explain.

EDIT: Here’s the method I created, with all ifs:

public boolean haGanhador(){
    //Checa X verticalmente
    if(tabuleiro[0][0] == 'X' && tabuleiro[1][0] == 'X' && tabuleiro [2][0] == 'X'){
        System.out.println("'X' VENCEU");
        return true;
    }
     else if(tabuleiro[0][1] == 'X' && tabuleiro[1][1] == 'X' && tabuleiro[2][1] == 'X'){
        System.out.println("'X' VENCEU");
        return true;
     }
     else if(tabuleiro[0][2] == 'X' && tabuleiro[1][2] == 'X' && tabuleiro[2][2] == 'X'){
        System.out.println("'X' VENCEU");
        return true;
    }



     //Checa X horizontalmente
     else if(tabuleiro[0][0] == 'X' && tabuleiro[0][1] == 'X' && tabuleiro[0][2] == 'X'){
    System.out.println("'X' VENCEU");
    return true;
    }
    else if(tabuleiro[1][0] == 'X' && tabuleiro[1][1] == 'X' && tabuleiro[1][2] == 'X'){
    System.out.println("'X' VENCEU");
    return true;
    } 
    else if(tabuleiro[2][0] == 'X' && tabuleiro[2][1] == 'X' && tabuleiro[2][2] == 'X'){
    System.out.println("'X' VENCEU");
    return true;
    }
    //Checa X diagonalmente
    else if(tabuleiro[0][0] == 'X' && tabuleiro[1][1] == 'X' && tabuleiro[2][2] == 'X'){
    System.out.println("'X' VENCEU");
    return true;
    }
    else if(tabuleiro[0][2] == 'X' && tabuleiro[1][1] == 'X' && tabuleiro[2][0] == 'X'){
    System.out.println("'X' VENCEU");
    return true;
    }
    //Checa O verticalmente
    if(tabuleiro[0][0] == 'O' && tabuleiro[1][0] == 'O' && tabuleiro [2][0] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }
    else if(tabuleiro[0][1] == 'O' && tabuleiro[1][1] == 'O' && tabuleiro[2][1] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }
    else if(tabuleiro[0][2] == 'O' && tabuleiro[1][2] == 'O' && tabuleiro[2][2] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }

    //Checa O horizontalmente
    if(tabuleiro[0][0] == 'O' && tabuleiro[0][1] == 'O' && tabuleiro[0][2] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }
    else if(tabuleiro[1][0] == 'O' && tabuleiro[1][1] == 'O' && tabuleiro[1][2] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }
    else if(tabuleiro[2][0] == 'O' && tabuleiro[2][1] == 'O' && tabuleiro[2][2] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }

    //Checa O diagonalmente
    if(tabuleiro[0][0] == 'O' && tabuleiro[1][1] == 'O' && tabuleiro[2][2] == 'O'){
    System.out.println("'O' VENCEU");
    return true;
    }
    else if(tabuleiro[0][2] == 'O' && tabuleiro[1][1] == 'O' && tabuleiro[2][0] == 'O'){
    System.out.println("'O' VENCEU");
    return true; 
    }

    return false;
}
  • 1

    How about posting your code even with lots of Ifs? Can help people interested in helping.

  • I just posted

  • Related: http://answall.com/q/61351/73

4 answers

11


Since you prefer a few IFs, I made a solution using a IF and a FORonly.

Solution:

public class JogoVelha {

    public static String obtemVencedor(String[] tabuleiro) {

        if ((tabuleiro == null) || (tabuleiro.length != 9)) {
            throw new IllegalArgumentException
                ("Um tabuleiro deve ser um array de 9 posições.");
        }
        Integer[][] padroesVitoria = {
                    {0, 1, 2},
                    {0, 4, 8},
                    {0, 3, 6},
                    {1, 4, 7},
                    {2, 5, 8},
                    {2, 4, 6},
                    {3, 4, 5},
                    {6, 7, 8}};

        for (Integer[] padraoVitoria: padroesVitoria) {

            boolean haVencedor = tabuleiro[padraoVitoria[0]] != null 
                && tabuleiro[padraoVitoria[0]].equals(tabuleiro[padraoVitoria[1]]) 
                && tabuleiro[padraoVitoria[0]].equals(tabuleiro[padraoVitoria[2]]);

            if (haVencedor) {
                String vencedor = tabuleiro[padraoVitoria[0]];
                return vencedor;
            }
        }
        return null;
    }
}

Testing:

@Test
public void jovadorXVence() {

    String[] tabuleiro = {
            "X", "O", null, 
            "O", "O", null,
            "X", "X", "X"} ;

    String vencedor = JogoVelha.obtemVencedor(tabuleiro);

    assertEquals("X", vencedor);
}

@Test
public void naoHaVencedor() {

    String[] tabuleiro = {
            "X", "O", null, 
            "O", "O", null, 
            "X", null, "X"} ;

    String vencedor = JogoVelha.obtemVencedor(tabuleiro);

    assertNull(vencedor);
}

My approach was as follows:

  • I realized that the board has nine positions. Your visualization would be something like this:

    0 | 1 | 2
    ---------
    3 | 4 | 5
    ---------
    6 | 7 | 8
    
  • Then the filled or partially filled board is represented by a 9-position array.

  • Then I visualized an example of finished game. It would be the following:

    X | O | -
    ---------
    O | O | -
    ---------
    X | X | X
    
  • Viewing this completed game within my array, I have identified the winning patterns (which positions within the array, when occupied by the same player, signal a win):

    0 1 2
    0 4 8
    0 3 6
    1 4 7
    2 5 8
    2 4 6
    3 4 5
    6 7 8
    
  • And then I wrote an algorithm to process the array representing a board, searching within it for the winning patterns.

After every move, obtemVencedor can be invoked to identify if there is already a winner. If there is no winner, we can check if there are still positions available on the board (if there are non-null elements in the array) to see if the game ended tied.

  • He already had his homework done :)

  • kkkk okay. It’s just that the teacher specifically asked to create an array 3 by 3. That’s why I made a char tabuleiro[][] = new char[3][3] , I also thought it would be more 'intelligent' to do with an array of 9 positions but he asked this way. I liked the way you solved, quite interesting this line of reasoning.

  • It’s true, @Jorgeb!

  • @Davidduque Well, if the teacher wanted to use multidimensional array, in this algorithm he has it, the winning patterns.

9

You can wear bows for to check at the end of each round (from the third round) the winner, I would do as follows:

1. Fora do for verifica diagonais são iguais
2. Verifica se linha i todas as colunas são iguais
3. Verifica se coluna i todas as linhas são iguais

coding would look something like this:

public boolean fimDoJogo(){
  if((matriDoJogo[0][0] == matriDoJogo[1][1] && matriDoJogo[1][1] == matriDoJogo[2][2]) || 
     (matriDoJogo[0][2] == matriDoJogo[1][1] && matriDoJogo[1][1] == matriDoJogo[2][0])){
    System.out.println("Venceu o jogador que escolheu o "+matriDoJogo[1][1]);
    return true;
  }
  for(int i = 0; i < 3; i++){
    if(matriDoJogo[i][0] == matriDoJogo[i][1] && matriDoJogo[i][1] == matriDoJogo[i][2]){
      System.out.println("Venceu o jogador que escolheu o "+matriDoJogo[i][1]);
      return true;
    }
    if(matriDoJogo[0][i] == matriDoJogo[1][i] && matriDoJogo[1][i] == matriDoJogo[2][i]){
      System.out.println("Venceu o jogador que escolheu o "+matriDoJogo[1][i]);
      return true;
    }
  }
  return false;
}

It would still be possible to change the return of the method, to return which player symbol won.

  • How could I get what symbol that satisfied the winning condition?

  • 1

    You’d change the headline to char (could be string too, but it’s more indicator char) and, instead of having the system.out and Return true, you would have had return matriDoJogo[x][y], where x and y are the indices according to the conditionals. In this case, it would be the one being added to the System.out string.

7

Use bit maps (bitmaps).

Your 'board' can be expressed in a sequence of bits, thus:

Posições
2 | 1 | 0
5 | 4 | 3
8 | 7 | 6

Is equivalent to:

Posição 876543210
Bit     000000000

The following condition of victory

Posições
X |   |  
  | X |  
  |   | X

It can then be expressed as follows:

001 010 100 = Decimal 84

To check if the player has reached this condition, turn the positions occupied by him into a binary map as well.

Posições
A | B |  
  | A | A 
B | B | A

Apenas jogador A
A |   |  
  | A | A 
  |   | A

Bit map:

001 011 100 = Decimal 92

Do an operation now AND between the two:

001 010 100 AND
001 011 100 = 
001 010 100   Decimal 84

If the result of operation AND is equal to the winning condition value, the player has won.

Create an array of all possible win conditions:

Integer[] mapasVitoria = 
    {
    0b100100100, //Todas as posições da Coluna 1
    0b010010010, //Todas as posições da Coluna 2
    0b001001001, //Todas as posições da Coluna 3

    0b111000000, //Todas as posições da Linha 1
    0b000111000, //Todas as posições da Linha 2
    0b000000111, //Todas as posições da Linha 3

    0b100010001, //Diagonal Topo esquerdo -> Fundo direito
    0b001010100  //Diagonal Topo direito -> Fundo esquerdo
    };

and compare each player’s bit map to each throw.

  • Nice to use bit map. The logic is the same as mine using String array and Integer array, right?

  • 1

    @Correct Caffé, in practice is the same evaluation process - perhaps a little more economical at the point of iterations needed to determine a winner (only one cycle, only one AND operation per item, and so on.) So you took a +1. =)

1

Look at the simplest way I think you can solve this problem is all with this code:

possibilidades = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{6,4,8}}

for (p: possibilidades)
    if(tabuleiro[p[0]] == (tabuleiro[p[1]] == (tabuleiro[p[0]] && tabuleiro[p[0]] != null )
        System.out.println("Venceu");

whereas:

1 - You initialized a 9 position vector with null value (board)

2 - every time a move occurs you validate if you won

The possibilities is the map of valid moves, all positions of a possibility must be equal (X/O) and different from null which is the initial value of the map.

I hope I’ve helped!

  • 2

    This solution is almost the same as mine. With the difference that leaves unanswered the question: who won?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.