<html>
<head>
<title>ComputerMove.java</title>
</head>
<body bgcolor=#ffffff>
<pre>
/*
** ComputerMove is an object that selects a move for the
** the computer based on memory.  The way this works is
** by letting the computer choose the first available move
** starting from position 1 thourgh 9.  As the game progesses
** the computer will be told of losses caused by the
** unintelligent choises.  The game that lead to a loss is
** therefore saved in memory, and it is avoided afterwards.
**
** There is this one problem though.  The computer might at
** a point run out of possible end choices that would make
** it avoid a loss.  That's when it memorises earlier steps
** that make it come to a end-losing-choices. (I hope I made
** sense!)
*/
import java.lang.Math;
class ComputerMove
{

    //TttString currentBoard = new TttString();
        // This is the last board containing the computer's
        // last move (that might lead it to a loss
    TttString lastBoard = new TttString();
    //GameStatus currentGame = new GameStatus();
        // This is an array of all possible bad moves.  I am
        // sure of my calculations, but I think this is
        // correct.  The number of all combinations of
        // X's and O's are 512.  There are 2^(9-1) (256) possible
        // combinations of X's, and 256 combinations of O's.
        // Add them together and you would get 1024 possible
        // moves. Why (9-1), because there is always aleast on X
        // or O on the board.  Ahh!  I don't want to explain
        // too much.  Just think about it.
    TttString badMoves[] = new TttString[512];
        // Number of bad moves in memory
    int nBadMoves = 0;
        // The board is symetrical about the middle, and
        // is the same if rotated by 90 degrees.  Therefore
        // I am taking into account all possible moves including
        // those moves that are similar.
    int similarBoards[][] = {{1, 2, 3, 4, 5, 6, 7, 8, 9},
                             {3, 6, 9, 2, 5, 8, 1, 4, 7},
                             {9, 8, 7, 6, 5, 4, 3, 2, 1},
                             {7, 4, 1, 8, 5, 2, 9, 6, 3},
                             {3, 2, 1, 6, 5, 4, 9, 8, 7},
                             {1, 4, 7, 2, 5, 8, 3, 6, 9},
                             {7, 8, 9, 4, 5, 6, 1, 2, 3},
                             {9, 6, 3, 8, 5, 2, 7, 4, 1}};

    int nSimilarBoards = 8;
        // How many moves are available on the board. These
        // are the empty locations.
    private int availableMoves[] = new int[9];


    //===============================================================
    //  This is brain of the computer. The computer selects a move
    //  if the move didn't lead to a loss the last time it was
    //  played.  If there were more than one choice then it selects
    //  any one of them.
    //===============================================================
    public void MakeMove(TttString board)
    {
        int nAvailable;
        int move;
        boolean moveNotMade = true;
        TttString tempBoard = new TttString();

            // locate all available moves (empty locations).
        nAvailable = GetAvailableMoves(board);
        move = 0;
        while (moveNotMade)
        {
            tempBoard.tttString = board.tttString;
                // make a move in our test board
            tempBoard.SetTttString(availableMoves[move], board.O);
                // check to see if it's a bad move
            if (!BadMove(tempBoard))
            {
                    // if it's not a bad move then keep it.
                moveNotMade = false;
            }
            else
            {
                    // advance to the next location
                move++;
                    // if we are out of good moves then
                if (nAvailable == move)
                {
                        // consider the computer a loser,
                        // and make any move. The computer
                        // memporizes.
                    moveNotMade = false;
                    Lost();
                }
            }
        }
            // Since we made a choice move then, save the board
            // for later uses.
        board.tttString = tempBoard.tttString;
        lastBoard.tttString = board.tttString;
    }

    //===============================================================
    // Find all the positions that are not accupied
    //===============================================================
    private int GetAvailableMoves(TttString b)
    {
        int i;
        int nAvailable = 0;

        for (i = 0; i < 9; i++)
        {
            if (b.GetXO(i + 1) == b.EMPTY)
            {
                availableMoves[nAvailable++] = i + 1;
            }
        }

        return(nAvailable);

    }

    //===============================================================
    // The computer lost and needs to save the move that made it
    // loose.
    //===============================================================
    public void Lost()
    {
            // if the move that made us loose exists in
            // memory then don't save it.
        if (!BadMove(lastBoard))
        {
                // Assign a new TttString
            badMoves[nBadMoves] = new TttString();
            badMoves[nBadMoves++].tttString = lastBoard.tttString;
        }
    }

    //===============================================================
    // Check to see if a move is bad or not.  Compare the given
    // move with those in memory, and with all similar moves.
    //===============================================================
    private boolean BadMove(TttString testBoard)
    {
        int i, j, k;
        TttString equivalentBoard = new TttString();

        for (k = 0; k < nBadMoves; k++)
        {
                // make the different combinations of boards
                // that have similar apperances
            for (i = 0; i < nSimilarBoards; i++)
            {
                equivalentBoard.ClearTttString();
                for (j = 0; j < 9; j++)
                {
                    equivalentBoard.SetTttString(similarBoards[i][j], badMoves[k].GetXO(j + 1));
                }
                if (testBoard.tttString == equivalentBoard.tttString)
                {
                    return(true);
                }
            }
        }
        return(false);
    }

}
</pre>
</body>
</html>
