Example #1
0
        /*
         * Algorithm Source: https://www.geeksforgeeks.org/combinatorial-game-theory-set-2-game-nim/
         *
         * Based on the number of stones -  calculate the nim sum (aka binary sum ignoring the carries)
         *
         *  If the Nim Sum does not equal zero - find a way to make it zero:
         *      Check the XOR between each value and the nim sum
         *      If this value is less than the value in the pile - reduce the pile to this number
         *
         *      Example: piles = {3, 4, 5}
         *      nim sum = 3 ^ 4 ^ 5 = 2
         *
         *      3 ^ 2 = 1  <---- Since 1 < 3, we want to reduce this pile to 1 (remove 2 stones from pile 1)
         *      4 ^ 2 = 6
         *      5 ^ 2 = 7
         *
         *      Why? Because 1 ^ 4 ^ 5 = 0 and ending your turn with a nim sum of 0 is a winning position
         *
         *  However, if the nim sum starts at zero - its been mathematically proven that you will lose.
         *  Therefore, make a random move and hope your opponent makes a mistake
         */
        public static void MakeOptimalMove()
        {
            int nimSum = CalculateNimSum();

            int[] remainingStones = { Heaps.Heap1, Heaps.Heap2, Heaps.Heap3 };

            if (nimSum != 0)
            {
                for (int i = 0; i < remainingStones.Length; i++)
                {
                    if ((remainingStones[i] ^ nimSum) < remainingStones[i])
                    {
                        int amountToRemove = remainingStones[i] - (remainingStones[i] ^ nimSum);
                        Render.ClearLine();
                        Console.WriteLine($"Computer removed {amountToRemove} stones from pile {i + 1}");
                        Heaps.UpdateNumberOfStones(amountToRemove, i);
                        break;
                    }
                }
            }
            else
            {
                MakeRandomMove();
            }
        }
Example #2
0
        public static void MakeRandomMove()
        {
            int  randomAmountToRemove = -1; //Start at invalid amount & heap
            int  heapToRemoveFrom     = -1;
            bool isValidMove          = false;

            while (!isValidMove) //Make sure move is valid before updating board
            {
                randomAmountToRemove = rnd.Next(1, Game.MAX_STONES);
                heapToRemoveFrom     = rnd.Next(0, 3);
                isValidMove          = Game.CheckIfValidMove(randomAmountToRemove, heapToRemoveFrom);
            }
            Render.ClearLine();
            Console.WriteLine($"Computer removed {randomAmountToRemove} stones from pile {heapToRemoveFrom + 1}");
            Heaps.UpdateNumberOfStones(randomAmountToRemove, heapToRemoveFrom);
        }
Example #3
0
        public static int CURSOR_LEFT = 6; //user input the cursor will move & write the message without disrupting the game

        public static void Turn()
        {
            bool validMove      = false;
            bool validNumber    = false;
            int  amountToRemove = 0;

            while (!validNumber || !validMove) //User must enter an integer that is a valid move
            {
                SelectedHeap = GetSelectedHeap();
                AskForUserInput();
                validNumber = int.TryParse(Console.ReadLine(), out amountToRemove); //Check if user gave an integer value
                validMove   = Game.CheckIfValidMove(amountToRemove, SelectedHeap);  //Check if that integer value is a valid move
                if (!validNumber)
                {
                    amountToRemove = AskForValidNumber();
                }                                                           //Lines22-23: error messages for invalid input
                else if (!validMove)
                {
                    amountToRemove = AskForValidMove(amountToRemove);
                }
            }
            Heaps.UpdateNumberOfStones(amountToRemove, SelectedHeap);
        }