moveBoard.CS

mail@pastecode.io avatar
unknown
csharp
7 months ago
11 kB
9
Indexable
Never
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

  
}