/* * 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(); } }
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); }
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); }