Пример #1
0
        /// <summary>
        /// Asks the game engine next (valid) move given a game position
        /// The board assumes following standard move notation:
        ///                             v
        ///             A B C D E F G H I
        ///            [0 1 2 3 4 5 6 7 8]    (first index)
        ///       1[0]
        ///       2[1]
        ///       3[2]        w K
        ///       4[3]        K w
        ///       5[4]
        ///       6[5]
        ///      >7[6]                  x
        ///
        ///   {Column;Line}
        ///  E.g.:  'w' on D3 in game notation will map to {3,2}, and 'x' on I7  to {8,6}
        /// </summary>
        /// <param name="game">a 2D board with integer values: 0 for white 1 for black and -1 for empty tiles. First index for the column, second index for the line</param>
        /// <param name="level">an integer value to set the level of the IA, 5 normally</param>
        /// <param name="whiteTurn">true if white players turn, false otherwise</param>
        /// <returns>The column and line indices. Will return {-1,-1} as PASS if no possible move </returns>
        public Tuple <int, int> GetNextMove(int[,] game, int level, bool whiteTurn)
        {
            int[,] gameState = new int[9, 7];
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 7; j++)
                {
                    gameState[i, j] = game[i, j];
                }
            }

            BoardIA logic = new BoardIA
            {
                GameBoard  = gameState,
                PlayerTurn = whiteTurn ? Player.White : Player.Black
            };

            List <IntPosition> possibleMoves = logic.GetAllPossibleMoves();

            if (possibleMoves.Count == 0)
            {
                return(new Tuple <int, int>(-1, -1));
            }

            var nextMove = AlphaBeta(logic, level, int.MinValue, true);     // Always minimum value (int.MinValue) and we maximize (true), whatever the color...

            return(new Tuple <int, int>(nextMove.Item2.Column, nextMove.Item2.Row));
        }
Пример #2
0
        /// <summary>
        /// Implementation of negamax algorithm with alpha beta pruning. A node is represented by a game board.
        /// </summary>
        /// <param name="nodeBoard">A particular game state</param>
        /// <param name="depth">The maximum tree depth</param>
        /// <param name="parentValue">The parent node value</param>
        /// <param name="maximizingPlayer">Whether node is a maximizimer or minimizer. True if maximizer. </param>
        /// <returns>A tuple containing the value as it's first item and the position corresponding to the best
        /// predicted play as it's second item. </returns>
        private Tuple <int, IntPosition> AlphaBeta(BoardIA nodeBoard, int depth, int parentValue, bool maximizingPlayer)
        {
            if (depth == 0 || nodeBoard.IsTerminal())
            {
                var heuristicValue = nodeBoard.GetHeuristicValue();
                return(new Tuple <int, IntPosition>(heuristicValue, new IntPosition(-1, -1)));
            }
            else
            {
                int         bestValue = maximizingPlayer ? -int.MaxValue : int.MaxValue;
                IntPosition bestMove  = new IntPosition(-1, -1);

                var childPositions = nodeBoard.GetAllPossibleMoves();
                foreach (var child in childPositions)
                {
                    var childValue = AlphaBeta(PosToBoard(child, nodeBoard), depth - 1, bestValue, !maximizingPlayer);
                    int minOrMax   = maximizingPlayer ? 1 : -1;
                    if (childValue.Item1 * minOrMax > bestValue * minOrMax)
                    {
                        bestValue = childValue.Item1;
                        bestMove  = child;
                        if (bestValue * minOrMax > parentValue * minOrMax)
                        {
                            break;
                        }
                    }
                }
                return(new Tuple <int, IntPosition>(bestValue, bestMove));
            }
        }
Пример #3
0
        /// <summary>
        /// Creates an AIBoard class given the position of a move to play
        /// and the board where the move has to be played.
        /// </summary>
        /// <param name="position">The position of the pawn to play on the board</param>
        /// <param name="sourceBoard">The board where the move takes place</param>
        /// <returns>A new AIBoard with the updated game state</returns>
        private BoardIA PosToBoard(IntPosition position, BoardIA sourceBoard)
        {
            int[,] gameState = new int[9, 7];
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 7; j++)
                {
                    gameState[i, j] = sourceBoard.GameBoard[i, j];
                }
            }

            BoardIA newBoard = new BoardIA
            {
                GameBoard  = gameState,
                PlayerTurn = sourceBoard.PlayerTurn
            };

            newBoard.PlayMove(position.Column, position.Row, sourceBoard.PlayerTurn == Player.White);
            newBoard.SwitchPlayer();
            return(newBoard);
        }