public static void IterativeAutoSolve(Towers poles, int discs, Queue <MoveRecord> moveLog, int pTower1, int pTower2, int pTower3) { MoveRecord tempMoveRecord; string userInput; bool done = false; if (discs % 2 == 0) { int temp = pTower3; pTower3 = pTower2; pTower2 = temp; } do { for (int i = 1; i <= poles.MinimumPossibleMoves; i++) { if (i % 3 == 1) { tempMoveRecord = MoveBetweenPoles(poles, pTower1, pTower3); moveLog.Enqueue(tempMoveRecord); TowerUtilities.DisplayTowers(poles); Console.WriteLine($"\nMove {poles.NumberOfMoves}. Successfully moved disc from pole {pTower1} to pole {pTower3}."); } else if (i % 3 == 2) { tempMoveRecord = MoveBetweenPoles(poles, pTower1, pTower2); moveLog.Enqueue(tempMoveRecord); TowerUtilities.DisplayTowers(poles); Console.WriteLine($"\nMove {poles.NumberOfMoves}. Successfully moved disc from pole {pTower1} to pole {pTower3}."); } else if (i % 3 == 0) { tempMoveRecord = MoveBetweenPoles(poles, pTower2, pTower3); moveLog.Enqueue(tempMoveRecord); TowerUtilities.DisplayTowers(poles); Console.WriteLine($"\nMove {poles.NumberOfMoves}. Successfully moved disc from pole {pTower1} to pole {pTower3}."); } Console.WriteLine("\nPress Enter to move to the next step or \"X\" to quit."); userInput = Console.ReadKey().Key.ToString().ToUpper(); if (userInput.ToUpper() == "X") { done = true; break; } } done = true; } while (!done); }
static void Main(string[] args) { bool playGame = true; bool notValidEntry = true; string userInput; int numberOfDiscs; Towers poles; // Source tower int sourceTower = 0; // Destination tower int destinationTower = 0; int auxTower = 2; // Move Log Queue <MoveRecord> moveLog = new Queue <MoveRecord>(); // Temp Move Record MoveRecord tempMoveRecord; const string CtrlZ = "Z"; const string CtrlY = "Y"; Stack <MoveRecord> undoLog = new Stack <MoveRecord>(); Stack <MoveRecord> redoLog = new Stack <MoveRecord>(); while (playGame) { Console.WriteLine("How many discs in your tower (default is 5, max is 9)"); userInput = Console.ReadLine().ToUpper(); if (userInput == "X") { Console.WriteLine("Bye!"); break; } numberOfDiscs = Convert.ToInt32(userInput); poles = new Towers(numberOfDiscs); Console.Clear(); TowerUtilities.DisplayTowers(poles); Console.WriteLine(); Console.WriteLine("Options:"); Console.WriteLine("- M - Solve the puzzle manually"); Console.WriteLine("- A - Auto-solve Recursively"); Console.WriteLine("- S - Auto-solve Iteratively"); Console.WriteLine(); Console.Write("Choose an approach: "); userInput = Console.ReadLine().ToUpper(); if (userInput.ToUpper() == "A") { Console.WriteLine(); Console.WriteLine("Enter to watch closely!"); userInput = Console.ReadLine().ToUpper(); if (userInput != null) { sourceTower = 1; destinationTower = 3; RecursiveAutoSolve(poles.NumberOfDiscs, sourceTower, destinationTower, auxTower, moveLog, 1); Console.WriteLine($"Recursion Call Finished"); foreach (var moveRecord in moveLog) { sourceTower = moveRecord.From; destinationTower = moveRecord.To; tempMoveRecord = poles.Move(sourceTower, destinationTower); TowerUtilities.DisplayTowers(poles); Console.WriteLine($"Move {poles.NumberOfMoves} completed. Successfully moved disc {moveRecord.Disc} from tower {moveRecord.From} to tower {moveRecord.To}."); System.Threading.Thread.Sleep(250); //Console.ReadLine(); } Console.WriteLine($"Number of moves: {poles.NumberOfMoves}"); } } else if (userInput.ToUpper() == "S") { Console.WriteLine(); Console.WriteLine("Enter to watch closely!"); userInput = Console.ReadLine(); if (userInput != null) { sourceTower = 1; destinationTower = 3; IterativeAutoSolve(poles, numberOfDiscs, moveLog, sourceTower, auxTower, destinationTower); } } else { do { //First Question- Source tower do { // If block logic to determine if redoLog has entry. If log has entry, display redo message if (redoLog.Count == 0) { Console.WriteLine("Enter 'from' tower number 1,2 or 3, Z to undo"); } else { Console.WriteLine("Enter 'from' tower number 1,2 or 3, Z to undo or Y to redo"); } userInput = Console.ReadLine().ToUpper(); if (userInput == "X") { playGame = false; break; } else { //Check for ctrl keys, if none, convert to int if (userInput == CtrlZ || userInput == CtrlY) { Console.WriteLine("UNDO / REDO MOVE Requested"); notValidEntry = false; } else { sourceTower = Convert.ToInt32(userInput); if (sourceTower < 1 || sourceTower > 3) { Console.WriteLine("Invalid Tower Number"); } else { notValidEntry = false; } } } } while (notValidEntry); //Second question - Destination tower //Wrap 2nd question in If check for ctrl key if (userInput != CtrlZ && userInput != CtrlY) { notValidEntry = true; do { if (redoLog.Count == 0) { Console.WriteLine("Enter 'to' tower number 1,2 or 3, Ctr Z to undo"); } else { Console.WriteLine("Enter 'to' tower number 1,2 or 3, Ctrl Z to undo or Ctrl Y to redo"); } userInput = Console.ReadLine().ToUpper(); if (userInput == "X") { playGame = false; break; } else { if (userInput == CtrlZ || userInput == CtrlY) { //Console.WriteLine("UNDO / REDO MOVE Requested"); notValidEntry = false; } else { destinationTower = Convert.ToInt32(userInput); if (destinationTower < 1 || destinationTower > 3) { Console.WriteLine("Invalid Tower Number"); } else { notValidEntry = false; } } } } while (notValidEntry); } // Switch Case check to to see if Undo or Redo Request was entered else default regular move switch (userInput.ToUpper()) { case CtrlZ: Console.WriteLine($"undoLog BEFORE POP Count = {undoLog.Count}"); // Pop undoLog tempMoveRecord = undoLog.Pop(); sourceTower = tempMoveRecord.From; destinationTower = tempMoveRecord.To; // Move record redoLog redoLog.Push(tempMoveRecord); Console.WriteLine($"source = {sourceTower}, destination = {destinationTower}"); Console.WriteLine($"undoLog After POP Count = {undoLog.Count}"); // Call the Move but reverse values of sourceTower and destinationTower tempMoveRecord = poles.Move(destinationTower, sourceTower); break; case CtrlY: Console.WriteLine($"redoLog BEFORE POP Count = {redoLog.Count}"); // Pop redoLog tempMoveRecord = redoLog.Pop(); sourceTower = tempMoveRecord.From; destinationTower = tempMoveRecord.To; // Move record to undoLog undoLog.Push(tempMoveRecord); Console.WriteLine($"source = {sourceTower}, destination = {destinationTower}"); Console.WriteLine($"redoLog AFTER POP Count = {redoLog.Count}"); // Call the Move tempMoveRecord = poles.Move(sourceTower, destinationTower); break; default: // Set temp Move Record to the Move method tempMoveRecord = poles.Move(sourceTower, destinationTower); // Record Move into undoLog Console.WriteLine($"source = {sourceTower}, destination = {destinationTower}"); undoLog.Push(tempMoveRecord); // Clear redoLog Records redoLog.Clear(); break; } // Record Move Record into log moveLog.Enqueue(tempMoveRecord); // Display Code TowerUtilities.DisplayTowers(poles); Console.WriteLine($"Move {poles.NumberOfMoves} complete. Sucessfully moved tower {sourceTower} to tower {destinationTower}."); // Display stats Console.WriteLine($"Number of moves is {poles.NumberOfMoves}"); // Determine if they won if (poles.IsComplete == true) { if (poles.MinimumPossibleMoves == poles.NumberOfMoves) { Console.WriteLine($"Your number of moves is minimum number of move of {poles.MinimumPossibleMoves}."); } playGame = false; } } while (playGame); } // Ask if they want to see number of moves Console.WriteLine(); Console.WriteLine("Do you want to see the number of moves? 'Y' for yes."); userInput = Console.ReadLine().ToUpper(); if (userInput == "Y") { // Loop thru queue to and display all items foreach (var moveRecord in moveLog) { Console.WriteLine($"{moveRecord.MoveNumber}. Disc {moveRecord.Disc} moved from tower {moveRecord.From} to tower {moveRecord.To}."); } // Loop thru queue to remove while (moveLog.Count != 0) { //Console.WriteLine($"{moveRecord.MoveNumber}. Disc {moveRecord.Disc} moved from tower {moveRecord.From} to tower {moveRecord.To}."); moveLog.Dequeue(); } } // Ask if they want to play again Console.WriteLine(); Console.WriteLine("Do you want to play again? 'Y' for yes."); userInput = Console.ReadLine().ToUpper(); if (userInput == "Y") { //Clear all undoLog and redoLog and moveLog undoLog.Clear(); redoLog.Clear(); moveLog.Clear(); playGame = true; Console.Clear(); } else { Console.WriteLine("Nice day!"); break; } } }