views:

86

answers:

5

I am trying to make a really simple Tic-Tac-Toe game. I have stored values of "X" and "O" in a 0-8 ArrayList (3x3 square, essentially). I can do the following for each instance of a winning situation:

if ((newBoard().get(0)).equals("X") &&
    (newBoard().get(1)).equals("X") && 
    (newBoard().get(2)).equals("X")){
System.out.println("Player-X has won!");
return true;

However, this is going to take a TON of code! I thought about creating new ArrayLists that contain the situations in which "X" has won (3-in-roe) and then copy and paste, replace "X" with "O", then compare these with the current ArrayList board that the user is 'interacting with.' That's all good, but I don't know how to compare them. I looked at the API, but I couldn't find anything that could do what I want, which is to compare to ArrayLists, but only for the specified indexes.

Anything pertaining to making this situation a bit smaller, code-wise, will be greatly appreciated. Thanks!

A: 

Checkout this code golf to see various algorithms to check if and which player has one a TicTacToe game:

http://stackoverflow.com/questions/2245801/code-golf-tic-tac-toe

Roflcoptr
Particularly the [Java solution](http://stackoverflow.com/questions/2245801/code-golf-tic-tac-toe/2565507#2565507).
jball
+5  A: 

Well, one option is not to think of all the winning boards, but all the winning required locations. For example:

private static final int[][] LINES_OF_THREE = {
  { 0, 1, 2 }, // Horizontals
  { 3, 4, 5 },
  { 6, 7, 8 },
  { 0, 3, 6 }, // Verticals
  { 1, 4, 7 },
  { 2, 5, 8 },
  { 0, 4, 8 }, // Diagonals
  { 6, 4, 2 }
};

Then something like:

for (int[] line : LINES_OF_THREE) {
  boolean won = true;
  for (int place : line) {
    // player = "O" or "X"
    if (!newBoard.get(place).equals(player)) { 
      won = false;
      break;
    }
  }
  if (won) {
    // Yippee!
  }
}
Jon Skeet
You're confusing your C# and Java with the hybrid "for (int place IN line)" syntax :p
Luke Hutteman
@Luke: Whoops, yes. Fixing...
Jon Skeet
A: 

The point is not that rows, columns, and diaganols are equal to X and O, but that they are all equal to each other whether they be X or O so instead of your line use:

if ((newBoard().get(0)).equals(newBoard().get(1)).equals(newBoard().get(2))){
    System.out.println("Player-" + newBoard().get(0)  +" has won!");
return true;

It means the same thing, but works for X and O. The next step is to make a function that just compares three location indexes:

private boolean checkForWin(int x, int y, int z){
     return newBoard().get(x).equals(newBoard().get(y)).equals(newBoard().get(z)); 
}

You can then just keep passing that function all possible winning location indexes.

Adam
A: 

Sun released a TicTacToe app which uses bitwise operation to store the game state and calculate calculate wins.

http://java.sun.com/products/jfc/tsc/articles/tictactoe/src/TicTacToe.java

Each player has their own board state and using the bitwise operations the game tells which spaces are free.

Much like Jon's answer, the win conditions are checked vs an array of win locations. Requiring only one for loop, instead of two.

If you have the time to review this, it is a fantastic solution to TicTacToe

Sean
A: 

There are only 3 real winning conditions in tic tac toe. The rows, the columns and the diagonals

Here with a square array [3,3] (adapt as needed) and then you use iterate through the columns and the rows. Then you just have two diagonals to check.

I found this to be the far easiest way to do it.

boolean HasWon(PLAYER p)
{
    for (int i = 0; i < 3; i++)
    {
        // Columns
        if (board[i, 0] == p)
            if (board[i,1] == p && board[i,2] == p)
                return true;
        // Rows
        if (board[0, i] == p)
            if (board[1, i] == p && board[2, i] == p)
                return true;
    }
    //Check diagonals
    if (board[0,0] == p && board[1,1] == p && board[2,2] == p) return true;
    if (board[2,0] == p && board[1,1] == p && board[0,2] == p) return true;
    return false;
}
Christian Kjær