コード例 #1
0
 /// <summary>
 /// Constructor for a Game Move
 /// </summary>
 /// <param name="movePiece">The moving piece</param>
 /// <param name="destination">The destination position of the moving piece</param>
 public GameMove(CheckersPiece movePiece, Vector2 destination)
 {
     this.movePiece      = movePiece;
     capturedPieces      = new List <CheckersPiece>();
     destinationPosition = new Vector2(destination.X, destination.Y);
     originalPosition    = new Vector2(movePiece.position.X, movePiece.position.Y);
 }
コード例 #2
0
 /// <summary>
 /// This function is for handling any checker piece actions.
 /// Function take a checkers piece as parameter, and set it as the active game piece.
 /// Function will also make the piece determine all its possible moves.
 /// </summary>
 /// <param name="activePiece">A piece to do an action on</param>
 public void doGamePieceAction(CheckersPiece activePiece)
 {
     if (activePiece.getCaptureStatus() == false && activePiece.getColor() == turnColor)
     {
         activeGamePiece = activePiece;
         activePiece.determineMoves(gameBoard, this);
     }
 }
コード例 #3
0
 /// <summary>
 /// Copy constructor for a game move.
 /// This constructor is used for creating temporary game states.
 /// </summary>
 /// <param name="move">The move to copy</param>
 public GameMove(GameMove move)
 {
     movePiece      = move.movePiece;
     capturedPieces = new List <CheckersPiece>();
     foreach (CheckersPiece piece in move.capturedPieces)
     {
         capturedPieces.Add(new CheckersPiece(piece));
     }
     destinationPosition = new Vector2(move.destinationPosition.X, move.destinationPosition.Y);
     originalPosition    = new Vector2(move.originalPosition.X, move.originalPosition.Y);
 }
コード例 #4
0
ファイル: CheckersPiece.cs プロジェクト: whuang02/AICheckers
 /// <summary>
 /// Copy constructor for a checkers piece.
 /// This constructor is used mainly for creating new temporary states for running the alpha-beta
 /// </summary>
 /// <param name="piece">The piece to copy</param>
 public CheckersPiece(CheckersPiece piece)
 {
     position      = new Vector2(piece.position.X, piece.position.Y);
     color         = piece.color;
     isCaptured    = piece.isCaptured;
     destination   = new Vector2(piece.destination.X, piece.destination.Y);
     possibleMoves = new List <GameMove>();
     foreach (GameMove move in piece.possibleMoves)
     {
         possibleMoves.Add(new GameMove(move));
     }
 }
コード例 #5
0
        /// <summary>
        /// Constructor for a state.
        /// A new game state is initialized by passing in the color the player is playing as.
        /// </summary>
        /// <param name="playerClr">The color for the player</param>
        public CheckersGameState(PieceColor playerClr)
        {
            gameBoard       = new CheckersBoard();
            whiteGamePieces = new List <CheckersPiece>();
            blackGamePieces = new List <CheckersPiece>();
            turnColor       = PieceColor.None;
            winner          = PieceColor.None;
            jumpExists      = false;

            //If a player color is passed in, the blow will initialize all the white and black pieces.
            if (playerClr != PieceColor.None)
            {
                Vector2 blackPosition;
                Vector2 whitePosition;
                for (int index = 0; index < MAX_PIECES; index++)
                {
                    //calculate the position for the black piece and the white piece
                    if (index < 3)
                    {
                        blackPosition = new Vector2(index * 2f, 5 - (index / 3));
                        whitePosition = new Vector2(index * 2f + 1, index / 3);
                    }
                    else
                    {
                        blackPosition = new Vector2((index * 2f + 1) - 6, 5 - (index / 3));
                        whitePosition = new Vector2((index * 2f) - 6, index / 3);
                    }

                    //Create the pieces with the calculated positions and add them the the list
                    CheckersPiece blackPiece = new CheckersPiece(new Vector2(blackPosition.X, blackPosition.Y), PieceColor.Black);
                    CheckersPiece whitePiece = new CheckersPiece(new Vector2(whitePosition.X, whitePosition.Y), PieceColor.White);
                    blackGamePieces.Add(blackPiece);
                    whiteGamePieces.Add(whitePiece);

                    //Set the tiles to be occupied
                    gameBoard.getTileAt(blackPosition).occupy(PieceColor.Black);
                    gameBoard.getTileAt(whitePosition).occupy(PieceColor.White);
                }
                //Set the player and ai colors
                if (playerClr == PieceColor.Black)
                {
                    playerColor = PieceColor.Black;
                    aiColor     = PieceColor.White;
                }
                else
                {
                    playerColor = PieceColor.White;
                    aiColor     = PieceColor.Black;
                }
            }
        }
コード例 #6
0
 /// <summary>
 /// Copy constructor to make a new copy of this current state
 /// This constructor is used to create temporary states in the ai.
 /// </summary>
 /// <param name="gameState">The state to be copied</param>
 public CheckersGameState(CheckersGameState gameState)
 {
     whiteGamePieces = new List <CheckersPiece>();
     blackGamePieces = new List <CheckersPiece>();
     moveablePieces  = new List <CheckersPiece>();
     gameBoard       = new CheckersBoard(gameState.gameBoard);
     foreach (CheckersPiece piece in gameState.blackGamePieces)
     {
         CheckersPiece newPiece = new CheckersPiece(piece);
         //find the active game piece
         if (gameState.activeGamePiece != null && newPiece.position == gameState.activeGamePiece.position)
         {
             activeGamePiece = newPiece;
         }
         blackGamePieces.Add(newPiece);
     }
     foreach (CheckersPiece piece in gameState.whiteGamePieces)
     {
         CheckersPiece newPiece = new CheckersPiece(piece);
         //find the active game piece
         if (gameState.activeGamePiece != null && newPiece.position == gameState.activeGamePiece.position)
         {
             activeGamePiece = newPiece;
         }
         whiteGamePieces.Add(newPiece);
     }
     foreach (CheckersPiece piece in gameState.moveablePieces)
     {
         CheckersPiece newPiece = new CheckersPiece(piece);
         moveablePieces.Add(newPiece);
     }
     playerColor    = gameState.playerColor;
     aiColor        = gameState.aiColor;
     turnColor      = gameState.turnColor;
     jumpExists     = gameState.jumpExists;
     winner         = gameState.winner;
     numTurnsPassed = gameState.numTurnsPassed;
 }
コード例 #7
0
ファイル: CheckersGame.cs プロジェクト: whuang02/AICheckers
        /// <summary>
        /// Function that is called whenever it is the turn of the AI to do its move
        /// </summary>
        public void doAiMove()
        {
            if (didAiMove == false)
            {
                bool onlyOneMove = false;
                //Check if theres only 1 moveable piece
                if (currentState.moveablePieces.Count == 1)
                {
                    //If there only 1 moveable piece and only 1 available action, set best move to that move
                    if (currentState.moveablePieces.First().getPossibleMoves().Count == 1)
                    {
                        bestMove    = currentState.moveablePieces.First().getPossibleMoves().First();
                        onlyOneMove = true;
                        Console.WriteLine("Only one move was available - Alpha-beta wasn't required"
                                          + "\n--------------------------------------------------------");
                    }
                }
                //If there is more than one move run algorithm
                if (onlyOneMove == false)
                {
                    int bestMoveValue = AlphaBetaSearch(new CheckersGameState(currentState));

                    //if the algorithm determines that the AI will win or lose regardless of which move,
                    //then make the ai do the first possible move it can
                    if (bestMoveValue == MIN_INT || bestMoveValue == MAX_INT)
                    {
                        bestMove = currentState.moveablePieces.First().getPossibleMoves()[0];
                    }
                    //if algorithm took 50 or more seconds to run, it has reach time cutoff
                    if ((endTime - startTime).TotalSeconds >= 55)
                    {
                        Console.Write("Tree reached time cutoff of 55 seconds"
                                      + "\n--Max Depth: " + maxDepth
                                      + "\n--Cut Off Depth: " + (cutoff + iterativeDepth));

                        //Reached time cutoff - reduce the cutoff by 1/4
                        float actualCutoff = 0.75f * (cutoff + iterativeDepth);
                        iterativeDepth = (((int)actualCutoff - cutoff) > 0) ? (int)actualCutoff - cutoff : 0;
                    }
                    //Else if maxDepth is equal to the cutoff depth, that means the tree reached cutoff level
                    else if (maxDepth == cutoff + iterativeDepth)
                    {
                        Console.Write("Tree reached cut off"
                                      + "\n--Cut Off Depth: " + (cutoff + iterativeDepth));

                        //Since alpha-beta was able to finish in reasonable time (< 50s)
                        // and the cutoff was reached, increased by 1 + (1/4)number of turns passed
                        iterativeDepth = 1 + (int)(currentState.numTurnsPassed * 0.25);
                    }
                    //else the tree completed before reaching cutoff
                    else
                    {
                        Console.Write("Tree completed before reaching cut off"
                                      + "\n--Max Depth: " + maxDepth
                                      + "\n--Cut Off Depth: " + (cutoff + iterativeDepth));
                    }
                    Console.WriteLine("\n--Nodes Generated: " + nodes
                                      + "\n--# times pruning occured in MAX-VALUE: " + maxPruned
                                      + "\n--# times pruning occured in MIN-VALUE: " + minPruned
                                      + "\nFound Move in: " + (endTime - startTime).TotalSeconds
                                      + "seconds\n--------------------------------------------------------");

                    //AI is completed sleep the thread
                    Thread.Sleep(1000);
                }

                //Do the actual move
                CheckersPiece movePiece = bestMove.movePiece;
                currentState.doGamePieceAction(currentState.getPiece(movePiece.getColor(), movePiece.position));
                //Set now to when the delay for the AI to actually do the move to now
                didAiMove   = true;
                aiMoveStart = DateTime.Now;
            }
            else
            {
                //If the delay for an AI to do the move has been reached do the move
                if ((DateTime.Now - aiMoveStart).TotalSeconds > aiTimeDelay)
                {
                    if (currentState.doTileAction(currentState.gameBoard.getTileAt(bestMove.destinationPosition)) == true)
                    {
                        currentState.activeGamePiece.Update(currentState);
                        didAiMove = false;
                    }
                }
            }
        }
コード例 #8
0
ファイル: CheckersGame.cs プロジェクト: whuang02/AICheckers
        /// <summary>
        /// Function that handles all drawings in the game
        /// This function is called everytime after an update
        /// </summary>
        /// <param name="spriteBatch">Spritebatch initialized by main</param>
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Begin();
            //Draw the board
            currentState.gameBoard.Draw(spriteBatch, checkerGameBoardTexture);

            //Draw all white pieces
            foreach (CheckersPiece piece in currentState.whiteGamePieces)
            {
                if (piece.getCaptureStatus() == false)
                {
                    piece.Draw(spriteBatch, whitePieceTexture);
                }
            }
            //Draw all black pieces
            foreach (CheckersPiece piece in currentState.blackGamePieces)
            {
                if (piece.getCaptureStatus() == false)
                {
                    piece.Draw(spriteBatch, blackPieceTexture);
                }
            }
            //Draw the active game piece marking
            CheckersPiece active = currentState.activeGamePiece;

            if (active != null)
            {
                if (active.getColor() == PieceColor.White)
                {
                    currentState.activeGamePiece.Draw(spriteBatch, activePieceTexture2, true);
                }
                else
                {
                    currentState.activeGamePiece.Draw(spriteBatch, activePieceTexture, true);
                }
            }
            //Draw any marked tiles
            BoardTile[,] tiles = currentState.gameBoard.getTiles();
            for (int x = 0; x < CheckersBoard.MAX_HORIZONTAL_TILES; x++)
            {
                for (int y = 0; y < CheckersBoard.MAX_VERTICAL_TILES; y++)
                {
                    if (tiles[x, y].getStatus() == TileStatus.MOVE)
                    {
                        tiles[x, y].Draw(spriteBatch, moveTileTexture);
                    }
                    else if (tiles[x, y].getStatus() == TileStatus.JUMP)
                    {
                        tiles[x, y].Draw(spriteBatch, jumpTileTexture);
                    }
                }
            }
            //Draw the text and buttons for the UI
            spriteBatch.DrawString(textFont, "Select a color to start a new game", new Vector2(10, 610), Color.Bisque);
            spriteBatch.Draw(blackButtonTexture, blackButton, Color.White);
            spriteBatch.Draw(whiteButtonTexture, whiteButton, Color.White);
            //Below displays the player's turn, or the winner if there exists
            if (currentState.winner == PieceColor.None && currentState.turnColor != PieceColor.None)
            {
                String message = currentState.turnColor + " turn";
                spriteBatch.DrawString(font, message, new Vector2(400, 630), Color.Bisque);
            }
            else
            {
                if (currentState.winner == PieceColor.Black)
                {
                    String message = "Black Wins!";
                    spriteBatch.DrawString(font, message, new Vector2(385, 630), Color.Red);
                }
                if (currentState.winner == PieceColor.White)
                {
                    String message = "White Wins!";
                    spriteBatch.DrawString(font, message, new Vector2(385, 630), Color.Blue);
                }
            }
            spriteBatch.End();
        }
コード例 #9
0
ファイル: CheckersPiece.cs プロジェクト: whuang02/AICheckers
        /// <summary>
        /// Function that will recursively find all the jump sequences possible by this piece
        /// </summary>
        /// <param name="tilePosition">The position of the tile to check jumps from</param>
        /// <param name="gameBoard">The gameboard</param>
        /// <param name="gameState">The current gamestate</param>
        /// <returns>A list of possible jumps</returns>
        public List <GameMove> getJumps(Vector2 tilePosition, CheckersBoard gameBoard, CheckersGameState gameState)
        {
            List <GameMove> jumps = new List <GameMove>();
            //Get all the possible tiles that could result with a jump
            BoardTile topLeftTile         = gameBoard.getTileAt((int)tilePosition.X - 1, (int)tilePosition.Y - 1);
            BoardTile topRightTile        = gameBoard.getTileAt((int)tilePosition.X + 1, (int)tilePosition.Y - 1);
            BoardTile bottomLeftTile      = gameBoard.getTileAt((int)tilePosition.X - 1, (int)tilePosition.Y + 1);
            BoardTile bottomRightTile     = gameBoard.getTileAt((int)tilePosition.X + 1, (int)tilePosition.Y + 1);
            BoardTile topLeftJumpTile     = gameBoard.getTileAt((int)tilePosition.X - 2, (int)tilePosition.Y - 2);
            BoardTile topRightJumpTile    = gameBoard.getTileAt((int)tilePosition.X + 2, (int)tilePosition.Y - 2);
            BoardTile bottomLeftJumpTile  = gameBoard.getTileAt((int)tilePosition.X - 2, (int)tilePosition.Y + 2);
            BoardTile bottomRightJumpTile = gameBoard.getTileAt((int)tilePosition.X + 2, (int)tilePosition.Y + 2);

            //Set the enemy color
            PieceColor enemyColor;

            if (this.color == PieceColor.Black)
            {
                enemyColor = PieceColor.White;
            }
            else
            {
                enemyColor = PieceColor.Black;
            }

            //The below four if-elses will basically determine if there was a piece of the enemy color was jumped over
            //by moving to a tile 2 diagonal tiles away. If there was a jump, it will mark the piece that it just jumped over
            //and then recursively look for any other following jumps from that tile.
            if (topLeftTile != null && topLeftTile.getOccupiedStatus() == enemyColor)
            {
                //Get the piece that was jumped over
                CheckersPiece adjacentPiece = gameState.getPiece(enemyColor, topLeftTile.position);
                if (topLeftJumpTile != null && topLeftJumpTile.getOccupiedStatus() == PieceColor.None && adjacentPiece.justJumpedOver == false)
                {
                    //mark the piece as jumped over
                    adjacentPiece.justJumpedOver = true;
                    //Find any jumps from the new tile position
                    List <GameMove> sequenceJumps = getJumps(topLeftJumpTile.position, gameBoard, gameState);

                    //If there was no following jump then add the jump to the list of jump
                    if (sequenceJumps.Count == 0)
                    {
                        GameMove newJump = (new GameMove(this, topLeftJumpTile.position));
                        newJump.capturedPieces.Add(adjacentPiece);
                        jumps.Add(newJump);
                    }
                    //Else for each following jump, add the piece the first jump captured to the list of captured pieces
                    else
                    {
                        foreach (GameMove jump in sequenceJumps)
                        {
                            //GameMove newJump = (new GameMove(this, jump.destinationPosition));
                            //jump.capturedPieces = jump.capturedPieces;
                            jump.capturedPieces.Add(adjacentPiece);
                            jumps.Add(jump);
                        }
                    }
                }
            }
            if (topRightTile != null && topRightTile.getOccupiedStatus() == enemyColor)
            {
                CheckersPiece adjacentPiece = gameState.getPiece(enemyColor, topRightTile.position);
                if (topRightJumpTile != null && topRightJumpTile.getOccupiedStatus() == PieceColor.None && adjacentPiece.justJumpedOver == false)
                {
                    //get any jumps from that tile
                    adjacentPiece.justJumpedOver = true;
                    List <GameMove> sequenceJumps = getJumps(topRightJumpTile.position, gameBoard, gameState);

                    if (sequenceJumps.Count == 0)
                    {
                        GameMove newJump = (new GameMove(this, topRightJumpTile.position));
                        newJump.capturedPieces.Add(adjacentPiece);
                        jumps.Add(newJump);
                    }
                    else
                    {
                        foreach (GameMove jump in sequenceJumps)
                        {
                            GameMove newJump = (new GameMove(this, jump.destinationPosition));
                            newJump.capturedPieces = jump.capturedPieces;
                            newJump.capturedPieces.Add(adjacentPiece);
                            jumps.Add(newJump);
                        }
                    }
                }
            }
            if (bottomLeftTile != null && bottomLeftTile.getOccupiedStatus() == enemyColor)
            {
                CheckersPiece adjacentPiece = gameState.getPiece(enemyColor, bottomLeftTile.position);
                if (bottomLeftJumpTile != null && bottomLeftJumpTile.getOccupiedStatus() == PieceColor.None && adjacentPiece.justJumpedOver == false)
                {
                    //get any jumps from that tile
                    adjacentPiece.justJumpedOver = true;
                    List <GameMove> sequenceJumps = getJumps(bottomLeftJumpTile.position, gameBoard, gameState);

                    if (sequenceJumps.Count == 0)
                    {
                        GameMove newJump = (new GameMove(this, bottomLeftJumpTile.position));
                        newJump.capturedPieces.Add(adjacentPiece);
                        jumps.Add(newJump);
                    }
                    else
                    {
                        foreach (GameMove jump in sequenceJumps)
                        {
                            GameMove newJump = (new GameMove(this, jump.destinationPosition));
                            newJump.capturedPieces = jump.capturedPieces;
                            newJump.capturedPieces.Add(adjacentPiece);
                            jumps.Add(newJump);
                        }
                    }
                }
            }
            if (bottomRightTile != null && bottomRightTile.getOccupiedStatus() == enemyColor)
            {
                CheckersPiece adjacentPiece = gameState.getPiece(enemyColor, bottomRightTile.position);
                if (bottomRightJumpTile != null && bottomRightJumpTile.getOccupiedStatus() == PieceColor.None && adjacentPiece.justJumpedOver == false)
                {
                    //get any jumps from that tile
                    adjacentPiece.justJumpedOver = true;
                    List <GameMove> sequenceJumps = getJumps(bottomRightJumpTile.position, gameBoard, gameState);

                    if (sequenceJumps.Count == 0)
                    {
                        GameMove newJump = (new GameMove(this, bottomRightJumpTile.position));
                        newJump.capturedPieces.Add(adjacentPiece);
                        jumps.Add(newJump);
                    }
                    else
                    {
                        foreach (GameMove jump in sequenceJumps)
                        {
                            GameMove newJump = (new GameMove(this, jump.destinationPosition));
                            newJump.capturedPieces = jump.capturedPieces;
                            newJump.capturedPieces.Add(adjacentPiece);
                            jumps.Add(newJump);
                        }
                    }
                }
            }

            return(jumps);
        }
コード例 #10
0
ファイル: CheckersPiece.cs プロジェクト: whuang02/AICheckers
 /// <summary>
 /// Function to capture a checkerpiece given the piece, and its tile position
 /// </summary>
 /// <param name="piece">The piece to be captured</param>
 /// <param name="tile">The tile the piece is on</param>
 public void Capture(CheckersPiece piece, BoardTile tile)
 {
     tile.unOccupy();
     piece.isCaptured = true;
 }