Exemple #1
0
        /// <summary>
        /// In Nim a valid move is defined as removing from 1 to all tokens from 1 row,
        /// this methods verifies that the difference between the first parameter
        /// and the second constitutes a valid move.
        /// </summary>
        /// <param name="currentState">The current state of the game board</param>
        /// <param name="proposedState">The state which an AI or Player's move will result in</param>
        /// <returns>If the move the AI or Player is making is valid</returns>
        public static bool IsMoveValid(BoardState currentState, BoardState proposedState)
        {
            if (currentState.RowCounts[0] > proposedState.RowCounts[0] &&
                proposedState.RowCounts[0] >= 0)
            {
                if (currentState.RowCounts[1] == proposedState.RowCounts[1] &&
                    currentState.RowCounts[2] == proposedState.RowCounts[2]) return true;
            }

            if (currentState.RowCounts[1] > proposedState.RowCounts[1] &&
                proposedState.RowCounts[1] >= 0)
            {
                if (currentState.RowCounts[0] == proposedState.RowCounts[0] &&
                    currentState.RowCounts[2] == proposedState.RowCounts[2]) return true;
            }

            if (currentState.RowCounts[2] > proposedState.RowCounts[2] &&
                proposedState.RowCounts[2] >= 0)
            {
                if (currentState.RowCounts[0] == proposedState.RowCounts[0] &&
                    currentState.RowCounts[1] == proposedState.RowCounts[1]) return true;
            }

            return false;
        }
Exemple #2
0
        public void RunPlayerVersusAIGame()
        {
            GameState = new BoardState();
            MoveList.Clear();

            Random randomGen = new Random();

            //Randomly choose the AI to take first turn.
            if (randomGen.Next(2) % 2 == 0)
            {
                GameState = NimAI_1.TakeTurn(GameState);
                MoveList.Add(GameState);

                Console.WriteLine();
                GameState.PrintBoard();
                Console.WriteLine("After AI Turn. Any Key To Continue");

                Console.ReadLine();
            }

            do
            {
                Console.Clear();
                GameState.PrintBoard();

                GameState = UserConsoleInput.GetPlayerTurnInput(GameState);
                MoveList.Add(GameState);
                Console.WriteLine();
                Console.WriteLine("After Player Turn.");
                GameState.PrintBoard();

                if (GameState.TotalLeft <= 0)
                {
                    GameOver("AI_1");
                    break;
                }

                GameState = NimAI_1.TakeTurn(GameState);
                MoveList.Add(GameState);
                Console.WriteLine();
                Console.WriteLine("After AI Turn");
                GameState.PrintBoard();

                if (GameState.TotalLeft <= 0)
                {
                    GameOver("Player");

                    break;
                }

                Console.WriteLine("Press Any Key To Continue. ");
                Console.ReadLine();
            }
            while (Playing);

            NimLogic.WeightBoardStates(ref MoveList);

            NimAI_1.IntegrateIntoCatalog(MoveList);
            Console.ReadLine();
        }
Exemple #3
0
 public BoardState(BoardState b)
 {
     this.RowCounts = new int[3];
     for (int r = 0; r < RowCounts.Length; r++)
         this.RowCounts[r] = b.RowCounts[r];
     this.StateValue = b.StateValue;
     this.Frequency = b.Frequency;
 }
Exemple #4
0
 /// <summary>
 /// Used to determine all possible moves based upon the current BoardState
 /// </summary>
 /// <param name="currentState">Current Game's BoardState</param>
 /// <param name="weightedStateList">List to look for possible moves from</param>
 /// <returns>Each valid move from the provided list</returns>
 public static IEnumerable<BoardState> GetAllValidMoves(BoardState currentState, List<BoardState> weightedStateList)
 {
     foreach (var bs in weightedStateList)
     {
         if (IsMoveValid(currentState, bs))
             yield return bs;
     }
 }
Exemple #5
0
        public static BoardState EmptyBoardState()
        {
            BoardState emptyBoard = new BoardState();
            emptyBoard.RowCounts[0] = 0;
            emptyBoard.RowCounts[1] = 0;
            emptyBoard.RowCounts[2] = 0;
            emptyBoard.StateValue = -1000;

            return emptyBoard;
        }
        /// <summary>
        /// Runs the logic for an AI to make a move. Iterates through all valid moves and returns the highest weighted possible move.
        /// </summary>
        /// <param name="currentState">Current Game's BoardState</param>
        /// <returns>The AI's chosen move, guaranteed to be a valid move.</returns>
        public BoardState TakeTurn(BoardState currentState)
        {
            BoardState moveToMake = BoardState.EmptyBoardState();

            Random random = new Random();
            foreach(var b in NimLogic.GetAllValidMoves(currentState, BoardStateCatalog))
            {
                if (b.StateValue > moveToMake.StateValue)
                    moveToMake = new BoardState(b);
                else if (b.StateValue == moveToMake.StateValue)
                    if(random.Next(2) == 0) moveToMake = new BoardState(b);
            }

            return moveToMake;
        }
Exemple #7
0
 /// <summary>
 /// Used to provide a list of all possible BoardStates.
 /// </summary>
 /// <returns></returns>
 public static IEnumerable<BoardState> EveryPossibleBoardState()
 {
     for (int rowA = 0; rowA <= 3; rowA++)
     {
         for (int rowB = 0; rowB <= 5; rowB++)
         {
             for (int rowC = 0; rowC <= 7; rowC++)
             {
                 BoardState b = new BoardState();
                 b.Frequency = 0;
                 b.StateValue = 0;
                 b.RowCounts[0] = rowA;
                 b.RowCounts[1] = rowB;
                 b.RowCounts[2] = rowC;
                 yield return b;
             }
         }
     }
 }
Exemple #8
0
        public void RunAIVersusAIGame()
        {
            GameState = new BoardState();
            MoveList.Clear();

            Random randomGen = new Random();

            if (randomGen.Next(2) % 2 == 0)
            {
                GameState = NimAI_2.TakeTurn(GameState);
                MoveList.Add(GameState);
            }

            do
            {
                GameState = NimAI_1.TakeTurn(GameState);
                MoveList.Add(GameState);

                if (GameState.TotalLeft <= 0)
                {
                    GameOver("AI_2");
                    break;
                }

                GameState = NimAI_2.TakeTurn(GameState);
                MoveList.Add(GameState);

                if (GameState.TotalLeft <= 0)
                {
                    GameOver("AI_1");
                    break;
                }
            }
            while (Playing);

            NimLogic.WeightBoardStates(ref MoveList);

            NimAI_1.IntegrateIntoCatalog(MoveList);
            NimAI_2.IntegrateIntoCatalog(MoveList);
        }
        /// <summary>
        /// Runs through the logic required to create a new BoardState based upon
        /// the currentState and user input. First queries the user for which row using
        /// ForceConsoleIntegerInput and checks that the row has more than 0 tokens.
        /// Then asks for how many tokens to remove using ForceConsoleIntegerInput.
        /// </summary>
        /// <param name="currentState">Current game's BoardState</param>
        /// <returns>A BoardState created from the currentState and UserInput</returns>
        public static BoardState GetPlayerTurnInput(BoardState currentState)
        {
            BoardState newState = new BoardState(currentState);

            do
            {
                int row = 0;
                bool validChoice = false;

                do
                {
                    row = ForceConsoleIntegerInput("Choose a Row(1-3): ", "Invalid Input.", 1, 3);
                    validChoice = newState.RowCounts[row - 1] > 0;
                }
                while (!validChoice);

                newState.RowCounts[row - 1] -= ForceConsoleIntegerInput("Choose an amount(1-" + currentState.RowCounts[row - 1] + "): ",
                        "Invalid Input.", 1, currentState.RowCounts[row - 1]);
            }
            while (!NimLogic.IsMoveValid(currentState, newState));

            return newState;
        }
Exemple #10
0
 public void ApplyNewData(BoardState state)
 {
     float totalValue = (float)Frequency * StateValue;
     totalValue += state.StateValue;
     Frequency++;
     StateValue = totalValue / Frequency;
 }
Exemple #11
0
        public bool Equals(BoardState board)
        {
            if (board.RowCounts.Length != this.RowCounts.Length) return false;

            for(int r = 0; r < RowCounts.Length; r++)
                if(board.RowCounts[r] != this.RowCounts[r]) return false;

            return true;
        }