diff --git a/HanoiTowers.cs b/HanoiTowers.cs index 2ac723d..a3d44c0 100644 --- a/HanoiTowers.cs +++ b/HanoiTowers.cs @@ -1,3 +1,6 @@ +using System; +using su.divan2000.UtilsTUI; + namespace su.divan2000.PLandDS_HanoiTowers { class HanoiTowers @@ -48,7 +51,7 @@ namespace su.divan2000.PLandDS_HanoiTowers throw new InvalidOperationException("Source tower is empty"); if (targetTopIndex >= size) throw new InvalidOperationException("Target tower is full"); - if (targetTopIndex > 0 && sourceTower[sourceTopIndex] > targetTower[targetTopIndex]) + if (targetTopIndex >= 0 && sourceTower[sourceTopIndex] > targetTower[targetTopIndex]) throw new InvalidOperationException("Cannot place larger disk on smaller one"); targetTower[targetTopIndex + 1] = sourceTower[sourceTopIndex]; @@ -66,6 +69,21 @@ namespace su.divan2000.PLandDS_HanoiTowers } return -1; // Tower is empty } + + public bool isSolved() + { + return towers[0].All(disk => disk == 0) && towers[1].All(disk => disk == 0) && towers[2].All(disk => disk != 0); + } + + public void reset() + { + for (int i = 0; i < size; i++) + { + towers[0][i] = size - i; + towers[1][i] = 0; + towers[2][i] = 0; + } + } } static class HanoiUtils @@ -98,16 +116,68 @@ namespace su.divan2000.PLandDS_HanoiTowers return moves; } - public static void ExecuteMoves(HanoiTowers towers, List moves) + public static void ExecuteMove(HanoiTowers towers, Move move) { - foreach (Move move in moves) + towers.move(move.From, move.To); + } + + public static int RunTUI() + { + bool running; + int n = InputHelper.AskInt("Введите количество дисков в ханойской башне: "); + HanoiTowers towers = new HanoiTowers(n); + + HanoiTowers.TowerName selectedTower = HanoiTowers.TowerName.A; + Menu manualInput = new Menu("Выберите башню:\n"+towers); + manualInput.AddOption("Башня A", () => selectedTower = HanoiTowers.TowerName.A); + manualInput.AddOption("Башня B", () => selectedTower = HanoiTowers.TowerName.B); + manualInput.AddOption("Башня C", () => selectedTower = HanoiTowers.TowerName.C); + + Menu menu = new Menu("Выберите действие:\n"+towers); + menu.AddOption("Сделать ход вручную", () => { - towers.move(move.From, move.To); - Console.Clear(); - Console.WriteLine($"Move from {move.From} to {move.To}"); - Console.WriteLine(towers); - System.Threading.Thread.Sleep(1000); + manualInput.SetTitle("Выберите башню, с которой хотите переместить диск:\n" + towers); + manualInput.RunMenu(); + HanoiTowers.TowerName from = selectedTower; + manualInput.SetTitle("Перемещение с башни " + from + "\nВыберите башню, на которую хотите переместить диск:\n" + towers); + manualInput.RunMenu(); + HanoiTowers.TowerName to = selectedTower; + try + { + towers.move(from, to); + } catch (InvalidOperationException ex) + { + Console.WriteLine("Невозможно переместить диск: " + ex.Message); + } + }); + menu.AddOption("Сбросить башню", () => + { + towers.reset(); + }); + menu.AddOption("Решить башню автоматически", () => + { + List moves = MoveN(towers, towers.Size, HanoiTowers.TowerName.A, HanoiTowers.TowerName.C, HanoiTowers.TowerName.B); + towers.reset(); + foreach (Move move in moves) { + ExecuteMove(towers, move); + Console.Clear(); + Console.WriteLine("Решение башни:\n" + towers); + System.Threading.Thread.Sleep(500); // Пауза для визуализации + } + }); + menu.AddOption("Выход", () => + { + running = false; + }); + + for (running = true; running;) + { + menu.SetTitle("Выберите действие:\n" + towers); + menu.RunMenu(); + running = !towers.isSolved(); } + + return 0; } } } \ No newline at end of file diff --git a/Program.cs b/Program.cs index 6cd851d..0eb3676 100644 --- a/Program.cs +++ b/Program.cs @@ -6,11 +6,7 @@ namespace su.divan2000.PLandDS_HanoiTowers { static void Main() { - HanoiTowers towers = new HanoiTowers(8); - Console.WriteLine(towers); - - List moves = HanoiUtils.MoveN(towers, towers.Size, HanoiTowers.TowerName.A, HanoiTowers.TowerName.C, HanoiTowers.TowerName.B); - HanoiUtils.ExecuteMoves(towers, moves); + HanoiUtils.RunTUI(); Environment.Exit(0); } diff --git a/TUI/InputHelper.cs b/TUI/InputHelper.cs new file mode 100644 index 0000000..6941f08 --- /dev/null +++ b/TUI/InputHelper.cs @@ -0,0 +1,45 @@ +using System; + +namespace su.divan2000.UtilsTUI +{ + public static class InputHelper + { + public static double AskDouble(string prompt) + { + double val; + while (true) + { + Console.Write(prompt); + if (double.TryParse(Console.ReadLine(), out val)) + return val; + + Console.WriteLine("Некорректный ввод. Введите число в формате 1.0, 2.5 и т.д."); + } + } + + public static int AskInt(string prompt) + { + int val; + while (true) + { + Console.Write(prompt); + if (int.TryParse(Console.ReadLine(), out val)) + return val; + + Console.WriteLine("Некорректный ввод. Введите целое число."); + } + } + + public static bool AskYesNo(string prompt) + { + while (true) + { + Console.Write(prompt); + string? s = Console.ReadLine()?.Trim().ToLower(); + if (s == "да") return true; + if (s == "нет") return false; + Console.WriteLine("Введите 'да' или 'нет'."); + } + } + } +} diff --git a/TUI/Menu.cs b/TUI/Menu.cs new file mode 100644 index 0000000..51790cd --- /dev/null +++ b/TUI/Menu.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace su.divan2000.UtilsTUI +{ + /// + /// TUI menu; + /// + internal class Menu + { + private List