moveBoard.CS
unknown
csharp
2 years ago
11 kB
14
Indexable
using UnityEngine; using System.Collections; using System.Collections.Generic; using static GameBoard; // // This class is created as a "scratch pad" for the AI. Before deciding its next move, the AI will make a copy of the current board on to // its move board. This class has functions to determine the possible moves, based on one move on the board, and it can evaluate each move (to use with minimax) // // SEARCH For TODO s for hints on where you complete you code... public class moveBoard { #region Properties public GameBoard.PLAYERS_ID MaximizingPlayer // Keeps track of which player is maximizing (i.e. AI) { get { return maximizingPlayer; } set { maximizingPlayer = value; } } public Move Root // the root node of the game tree (very first move, depth = 0 for top of tree, the PossibleMoves for the root node will contain all possible moves for an empty game board). { get { return rootMove; } set { rootMove = value; } } #endregion #region Private Data Members private const int NO_SCORE = 0; //TODO: Determine the values for the evaluate function private const int WIN_SCORE = 1000; private const int LOSE_SCORE = -1000; private const int TIE_SCORE = 0; private Move rootMove; private GameBoard.PLAYERS_ID maximizingPlayer; // This is the AI player private bool isMoveGameFinished; #endregion #region Public Members public Move[,] gameMoveBoard; //Constructor for the moveBoard public moveBoard() { rootMove = new Move(-1, -1); gameMoveBoard = new Move[GameBoard.MAX_ROWS, GameBoard.MAX_COLUMNS]; InitMoveBoard(); } // Adds the "nextMove" for "nextMovePlayer" to the move board. TODO: use this in the minimax function to test a move on the board public void makeMove( Move nextMove, GameBoard.PLAYERS_ID nextMovePlayer ) { // Add move to our scratch pad game board. AddMovetoGameMoveBoard(nextMove,nextMovePlayer); nextMove.SetOccupied(nextMovePlayer); // After the nextMove is made then create a list of children with the remaining possible moves. AddPossibleMovesForNextMove(nextMove); } // Clears the "nextMove" from the gameMoveBoard. TODO: use this in the minimax function to remove the move from the board so another move can be tested. public void RemoveMoveFromGameMoveBoard(Move nextMove) { //clear the board with the move by the currentplayer gameMoveBoard[nextMove.Row, nextMove.Column].ClearOccupied(); } //Initializes the move board ( this is the scratch pad for the AI ) public void InitMoveBoard() { rootMove.ClearChildrenList(); isMoveGameFinished = false; maximizingPlayer = GameBoard.PLAYERS_ID.PLAYER_NONE; for (int i = 0; i < GameBoard.MAX_ROWS; i++) { for(int j = 0; j < GameBoard.MAX_COLUMNS; j++) { gameMoveBoard[i,j] = new Move(i,j); //Inits move for scratch pad gameMoveBoard gameMoveBoard[i,j].Score = 0; } } } // Copies the actual game board to the scratch pad (gameMoveBoard) so AI can look ahead. public void SetCurrentGameBoardToMoveBoard(GameBoard.PLAYERS_ID initPlayer) { for (int i = 0; i < GameBoard.MAX_ROWS; i++) { for(int j = 0; j < GameBoard.MAX_COLUMNS; j++) { gameMoveBoard[i,j].Occupied = GameBoard.gameBoard[i,j].Occupied; gameMoveBoard[i,j].PlayerID = GameBoard.gameBoard[i,j].PlayerID; } } // Set up the root node to match the current game board. MaximizingPlayer = initPlayer; rootMove.PlayerID = initPlayer; rootMove.Score = NO_SCORE; AddPossibleMovesForNextMove(rootMove); } public int EvalBoardForAI() { int boardScore = TIE_SCORE; // // TODO: Complete this function with your OWN code. // Determine if there is a win, loss or tie and return appropriate score // If not a win loss or tie, evaluate the board based on your OWN strategy (how do you play the game?) // and return score accordingly // if (CheckForWinner(PLAYERS_ID.PLAYER_ONE)) { boardScore = LOSE_SCORE; } if(CheckForWinner(PLAYERS_ID.PLAYER_TWO)) { boardScore = WIN_SCORE; } return boardScore; } public bool IsGameOver() { isMoveGameFinished = false; // CheckForWinner(PLAYERS_ID.PLAYER_ONE); // CheckForWinner(PLAYERS_ID.PLAYER_TWO); //TODO: Determing when the game is over on the AI board (scratch board) gameMoveBoard, will need for MiniMax function in gameboard.cs // Will need to use functions that check if there is a win, loss or tie (see TODO CHECK functions at end of file), if there is a win/loss or tie return true if(CheckForWinner(PLAYERS_ID.PLAYER_ONE)) { isMoveGameFinished = true; } else if (CheckForWinner(PLAYERS_ID.PLAYER_TWO)) { isMoveGameFinished = true; } if(isMoveGameFinished == false) { isMoveGameFinished = CheckForTie(); } return isMoveGameFinished; } public bool CheckForTie() { bool gameTied = true; //Assumes that there is not a win on the board (assumes other function checks for win). //If there is not a win or loss on the board and the there are no unoccupied spots then there is a tie. for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (!gameMoveBoard[i,j].Occupied) { gameTied = false; } } } return gameTied; } public bool CheckForWinner(PLAYERS_ID IDtoPASS) { bool rowsWin = false; bool columnsWin = false; bool diagonalWin = false; int count = 0; if (WinConditions(rowsWin, columnsWin, diagonalWin) == false) { for (int r = 0; r < MAX_ROWS; r++) { count = 0; for (int c = 0; c < MAX_COLUMNS; c++) { PLAYERS_ID playerTurnID = gameMoveBoard[r, c].PlayerID; if (playerTurnID == IDtoPASS) { count++; } if (count == CONNECT_NUM) { rowsWin = true; break; } } if (rowsWin == true) { break; } } } //Check Rows if(WinConditions(rowsWin, columnsWin, diagonalWin) == false) { { for (int c = 0; c < MAX_COLUMNS; c++) { count = 0; for (int r = 0; r < MAX_ROWS; r++) { PLAYERS_ID playerTurnID = gameMoveBoard[r,c].PlayerID; if(playerTurnID == IDtoPASS) { count++; if (count == CONNECT_NUM){ columnsWin = true; break;} } } if (count == CONNECT_NUM) { break; } } } } //Check Columns if(WinConditions(rowsWin, columnsWin,diagonalWin) == false) { count = 0; for (int r = 0; r < MAX_ROWS; r++) { for (int c = 0;c < MAX_COLUMNS; c++) { PLAYERS_ID playerTurnID = gameMoveBoard[c, r].PlayerID; if(playerTurnID == IDtoPASS && r == c) { count++; if (count == CONNECT_NUM) { diagonalWin = true; break; } } } if (diagonalWin == true) { break; } } count = 0; for (int r = MAX_ROWS - 1; r > 0; r--) { count = 0; for (int c = 0; c < MAX_COLUMNS; c++) { PLAYERS_ID playerTurnID = gameMoveBoard[c, r].PlayerID; if (playerTurnID == IDtoPASS) { count++; if (count == CONNECT_NUM) { diagonalWin = true; break; } } if (diagonalWin == true) { break; } } } } //Check Diagonals if(rowsWin || columnsWin || diagonalWin) { return true; } else { return false; } } public bool WinConditions(bool rowsWin, bool columnsWin, bool diagonalWin) { if (rowsWin == true || columnsWin == true || diagonalWin == true) { return true; } else { return false; } } //Check if any win has occurred. #endregion #region Private Functions // Goes through the entire board and sets all the possible moves for "nextMove". private void AddPossibleMovesForNextMove(Move nextMove) { for (int i = 0; i < GameBoard.MAX_ROWS; i++) { for (int j = 0; j < GameBoard.MAX_COLUMNS; j++) { if (!gameMoveBoard[i, j].Occupied) { Move posMove = new Move(); gameMoveBoard[i, j].Copy(posMove); nextMove.PossibleMoves.Add(posMove); } } } } // Directly sets the nextMovePlayer to the nextMove position on the gameMoveBoard. private void AddMovetoGameMoveBoard(Move nextMove, GameBoard.PLAYERS_ID nextMovePlayer) { // Update the board with the move by the currentplayer. gameMoveBoard[nextMove.Row, nextMove.Column].SetOccupied(nextMovePlayer); } #endregion }
Editor is loading...