A simple game of Tic-Tac-Toe.
Example #1
0
        public GameForm()
        {
            InitializeComponent();
            _randomPlayer = new RandomPlayer();
            _optimalPlayer = new OptimalPlayer(SquareTypes.O);
            _neatPlayer = new NeatPlayer(null, SquareTypes.O);
            _aiSquareType = SquareTypes.O;
            _humanSquareType = SquareTypes.X;
            _game = new TicTacToeGame();

            // Set the AI to the random player by default.
            _ai = _randomPlayer;

            // Experiment classes encapsulate much of the nuts and bolts of setting up a NEAT search.
            _experiment = new TicTacToeExperiment();
            _hyperNeatExperiment = new TicTacToeHyperNeatExperiment();

            // Load config XML for the NEAT experiment.
            XmlDocument xmlConfig = new XmlDocument();
            xmlConfig.Load("tictactoe.config.xml");
            _experiment.Initialize("TicTacToe", xmlConfig.DocumentElement);

            // Load config XML for the HyperNEAT experiment.
            xmlConfig = new XmlDocument();
            xmlConfig.Load("hyperneat.config.xml");
            _hyperNeatExperiment.Initialize("TicTacToe", xmlConfig.DocumentElement);
        }
        /// <summary>
        /// A helper method for competing two players against each other.
        /// </summary>
        /// <param name="xPlayer">The player to act first.</param>
        /// <param name="oPlayer">The player to act second.</param>
        /// <returns>
        /// The square type of the winner, or SquareTypes.N if the game
        /// was a draw.
        /// </returns>
        public static SquareTypes PlayGameToEnd(IPlayer xPlayer, IPlayer oPlayer)
        {
            TicTacToeGame game = new TicTacToeGame();
            SquareTypes winner = SquareTypes.N;

            // Play until we have a winner or the game board is full.
            for (int moveNum = 0; moveNum < 9 && winner == SquareTypes.N; moveNum++)
            {
                IPlayer curPlayer;
                SquareTypes curSquareType;

                // Determine if it's X's or O's turn to act.
                if (moveNum % 2 == 0)
                {
                    curPlayer = xPlayer;
                    curSquareType = SquareTypes.X;
                }
                else
                {
                    curPlayer = oPlayer;
                    curSquareType = SquareTypes.O;
                }
                
                // Get the next move from the current player.
                var move = curPlayer.GetMove(game.Board);

                // Check to make sure the player's move is legal.
                Debug.Assert(game.IsEmpty(move.X, move.Y), "Player tried to make an illegal move!");

                // Set the board to the player's move.
                game.Board[move.X, move.Y] = curSquareType;

                // Start checking if we have a winner once xPlayer has made
                // at least 3 moves.
                if(moveNum > 3)
                    winner = game.GetWinner();
            }

            // Return the square type of the winner, or SquareTypes.N if it was a draw.
            return winner;
        }
        public Move GetMove(SquareTypes[,] board)
        {
            TicTacToeGame.GetWinner(board);
            int moveNum = 0;

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[i, j] != SquareTypes.N)
                    {
                        moveNum++;
                    }
                }
            }

            //first move is always a corner
            if (moveNum == 0)
            {
                return(new Move(0, 0));
            }

            //second move should be the center if free, else a corner
            if (moveNum == 1)
            {
                if (board[1, 1] == SquareTypes.N)
                {
                    return(new Move(1, 1));
                }

                return(new Move(0, 0));
            }

            //make a winning move if possible
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[i, j] != SquareTypes.N)
                    {
                        continue;
                    }

                    board[i, j] = SquareType;
                    var winner = TicTacToeGame.GetWinner(board);
                    board[i, j] = SquareTypes.N;
                    if (winner == SquareType)
                    {
                        return(new Move(i, j));
                    }
                }
            }

            //if we can't win, check if there are any moves that we have to make
            //to prevent ourselves from losing
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[i, j] != SquareTypes.N)
                    {
                        continue;
                    }

                    //set the move to the opponent's type
                    board[i, j] = SquareType == SquareTypes.X ? SquareTypes.O : SquareTypes.X;
                    var winner = TicTacToeGame.GetWinner(board);
                    board[i, j] = SquareTypes.N;

                    //if the opponent will win by moving here, move here to block them
                    if (winner != SquareTypes.N)
                    {
                        return(new Move(i, j));
                    }
                }
            }

            //if we're here, that means we have made at least 1 move already and can't win
            //nor lose in 1 move, so just make the optimal play which would be to a free
            //corner that isn't blocked
            Move move = null;
            int  max  = -1;

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[i, j] != SquareTypes.N)
                    {
                        continue;
                    }

                    board[i, j] = SquareType;
                    int count = 0;
                    for (int m = 0; m < 3; m++)
                    {
                        for (int n = 0; n < 3; n++)
                        {
                            if (board[m, n] != SquareTypes.N)
                            {
                                continue;
                            }

                            board[m, n] = SquareType;
                            var winner = TicTacToeGame.GetWinner(board);
                            board[m, n] = SquareTypes.N;
                            if (winner == SquareType)
                            {
                                count++;
                            }
                        }
                    }
                    board[i, j] = SquareTypes.N;
                    if (count > max)
                    {
                        move = new Move(i, j);
                        max  = count;
                    }
                }
            }

            return(move);
        }