-3

Given that

  • A board is possible if it could occur in a Tic-Tac-Toe game
  • An empty board counts as a valid solution
  • The board cannot be "finished" (i.e., neither side can have three pieces in a row)
  • If two boards differ only by reflection or rotation, they are counted as the same position

How many such positions exist and how can I get an list of them. I tried this:

import java.util.ArrayList;
import java.util.Arrays;

public class Second {
static ArrayList<int[]> arr = new ArrayList<int[]>();
static int[] board = new int[9];

public static void main(String[] args) {
    for(int i = 0; i < 19683; ++i){
        int c = i;
        for (int j = 0; j < 9; ++j){
            board[j] = c%3;
            c /= 3;
        }  

        //Check for Xs and Os
        int diff = 0;
        for(int x : board){
            if(x==1){
                diff++;
            }else if(x==2){
                diff--;
            }
        }
        if(diff==0 || diff==1){
            add(board);
        }
    }   
    System.out.println(arr.size());
}

public static void add(int[] board){
    //If the board is won by either side
    if(isCompleted(board)){return;}

    //Get all possible arrangements
    int[] board1 = {board[6],board[7],board[8],   board[3],board[4],board[5],   board[0],board[1],board[2]};
    int[] board2 = {board[2],board[1],board[0],   board[5],board[4],board[3],   board[8],board[7],board[6]};
    int[] board3 = {board[8],board[5],board[2],   board[7],board[4],board[1],   board[6],board[3],board[0]};
    int[] board4 = {board[0],board[3],board[6],   board[1],board[4],board[7],   board[2],board[5],board[8]};
    int[] board5 = {board[2],board[5],board[8],   board[1],board[4],board[7],   board[0],board[3],board[6]};
    int[] board6 = {board[8],board[7],board[6],   board[5],board[4],board[3],   board[2],board[1],board[0]};
    int[] board7 = {board[6],board[3],board[0],   board[7],board[4],board[1],   board[8],board[5],board[2]};

    int[][] boards = {board1, board2, board3, board4, board5, board6, board7};

    //Find the smallest of the 8 possible arrangements
    int[] smallestBoard = board;
    for(int k=0; k<7; k++){
        if(isGreater(boards[k], smallestBoard)){
            smallestBoard = boards[k];
        }
    }

    for(int[] x : arr){
        if(Arrays.equals(x, smallestBoard)){
            return;
        }
    }
    arr.add(smallestBoard);     
}

public static boolean isCompleted(int[] board){
    int piece = 1;

    if(isAll(piece, new int[]{board[0], board[1], board[2]})){return true;}
    if(isAll(piece, new int[]{board[3], board[4], board[5]})){return true;}
    if(isAll(piece, new int[]{board[6], board[7], board[8]})){return true;}
    if(isAll(piece, new int[]{board[0], board[3], board[6]})){return true;}
    if(isAll(piece, new int[]{board[1], board[4], board[7]})){return true;}
    if(isAll(piece, new int[]{board[2], board[5], board[8]})){return true;}
    if(isAll(piece, new int[]{board[0], board[4], board[8]})){return true;}
    if(isAll(piece, new int[]{board[2], board[4], board[6]})){return true;}

    piece = 2;

    if(isAll(piece, new int[]{board[0], board[1], board[2]})){return true;}
    if(isAll(piece, new int[]{board[3], board[4], board[5]})){return true;}
    if(isAll(piece, new int[]{board[6], board[7], board[8]})){return true;}
    if(isAll(piece, new int[]{board[0], board[3], board[6]})){return true;}
    if(isAll(piece, new int[]{board[1], board[4], board[7]})){return true;}
    if(isAll(piece, new int[]{board[2], board[5], board[8]})){return true;}
    if(isAll(piece, new int[]{board[0], board[4], board[8]})){return true;}
    if(isAll(piece, new int[]{board[2], board[4], board[6]})){return true;}

    return false;
}

public static boolean isGreater(int[] first, int[] second){
    for(int j=0; j<9; j++){
        if(first[j]>second[j]){return true;}
        if(second[j]>first[j]){return false;}
    }
    return true;
}

public static boolean isAll(int value, int[] arr){
    for(int x : arr){
        if(x != value){
            return false;
        }
    }
    return true;
}

}

This gives a result of 628 possible positions. However, Michal Forišek's answer to a Quora question gives the answer of 630 positions, including three which I don't have. My program also outputs [2, 2, 2, 2, 2, 2, 2, 2, 2] as a valid positions, which it can't be.

  • 4
    https://stackoverflow.com/questions/7466429/generate-a-list-of-all-unique-tic-tac-toe-boards?rq=1 ? –  Dec 29 '16 at 16:40
  • I have seen this; I'm not sure what's wrong with my code, though. @RC. – QuestionCactus Dec 29 '16 at 16:46
  • I wonder if you look at the problem as printing out all the base 3 numbers between 0 and 19683. Where 0 corresponds empty square 1 is an O and 2 is a X. – Red Cricket Dec 29 '16 at 16:48
  • Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation. [Minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) applies here. We cannot effectively help you until you post your MCVE code and accurately describe the problem. – Prune Dec 29 '16 at 17:03
  • @Prune I posted my code. – QuestionCactus Dec 29 '16 at 17:10
  • When you materially change a question, you should retire the original one (by accepting an answer or removing the question) and post the alteration as a new question. In this case, you've changed the question so much that the "duplicate" claims no longer apply as well, due to the symmetry considerations. – Prune Dec 29 '16 at 17:28
  • When I run your code, I get only the **628**, no boards output. When I add a line to print boards, I do not get the all-2's board. I do get at least two completed games, which are contrary to your question. Please retire this properly and open a new question with the customary documentation. – Prune Dec 29 '16 at 18:27

1 Answers1

0

The basic problem is that you never backtrack. You start with an empty board and make a linear-script set of nine moves, filling the board. There are no more possible moves, so the algorithm terminates, leaving arr holding only those nine positions, the squares occupied in order.

To get proper coverage, make board a dynamic variable, rather than a static attribute of the class. Pass it as a parameter to playThrough, so that each instance has its own copy. This isn't a space problem: your call stack has a max depth of 10.

Handling the board dynamically will let the run-time stack manage your backtracking (since each instance maintains its own partial-game state).

I do hope that you're braced for the volume of solutions; 9! isn't large by some standards, but your array of 9! integer arrays of size 9 is something to consider.

Prune
  • 76,765
  • 14
  • 60
  • 81
  • Sorry, I have since changed the question. However, referring to my old question, I _did_ pass board as a parameter to playThrough. – QuestionCactus Dec 29 '16 at 17:14
  • You passed board, but you maintained it as a static attribute; that killed your backtracking. – Prune Dec 29 '16 at 17:16
  • Oh . . . what does static mean? I get an error, "Cannot make static reference to non-static field _board_" – QuestionCactus Dec 29 '16 at 17:18
  • "Here, let me search that for you ..." https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html – Prune Dec 29 '16 at 17:26
  • I know how to use Google. I still don't understand how this relates to my program. If I change it so that there are no static variables, it still does not work. – QuestionCactus Dec 29 '16 at 17:42