Добавленно TUI
This commit is contained in:
@@ -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<Move> moves)
|
||||
{
|
||||
foreach (Move move in moves)
|
||||
public static void ExecuteMove(HanoiTowers towers, Move move)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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("Сделать ход вручную", () =>
|
||||
{
|
||||
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<Move> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,7 @@ namespace su.divan2000.PLandDS_HanoiTowers
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
HanoiTowers towers = new HanoiTowers(8);
|
||||
Console.WriteLine(towers);
|
||||
|
||||
List<HanoiUtils.Move> moves = HanoiUtils.MoveN(towers, towers.Size, HanoiTowers.TowerName.A, HanoiTowers.TowerName.C, HanoiTowers.TowerName.B);
|
||||
HanoiUtils.ExecuteMoves(towers, moves);
|
||||
HanoiUtils.RunTUI();
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
45
TUI/InputHelper.cs
Normal file
45
TUI/InputHelper.cs
Normal file
@@ -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("Введите 'да' или 'нет'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
109
TUI/Menu.cs
Normal file
109
TUI/Menu.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// TUI menu;
|
||||
/// </summary>
|
||||
internal class Menu
|
||||
{
|
||||
private List<Option> options;
|
||||
private int selected;
|
||||
private string title;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor of menu;
|
||||
/// </summary>
|
||||
/// <param name="title">Title of menu</param>
|
||||
public Menu(string title)
|
||||
{
|
||||
this.title = title;
|
||||
this.options = new List<Option> { };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add option to menu;
|
||||
/// </summary>
|
||||
/// <param name="name">Name of option</param>
|
||||
/// <param name="action">Action, runs if option selected</param>
|
||||
public void AddOption(string name, Action action)
|
||||
{
|
||||
this.options.Add(new Option(name, action));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set title of menu;
|
||||
/// </summary>
|
||||
/// <param name="title">New title of menu</param>
|
||||
public void SetTitle(string title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run menu;
|
||||
/// Console will be clean!;
|
||||
/// </summary>
|
||||
public void RunMenu()
|
||||
{
|
||||
selected = 0;
|
||||
this.PrintMenu();
|
||||
ConsoleKeyInfo keyinfo;
|
||||
do
|
||||
{
|
||||
keyinfo = Console.ReadKey();
|
||||
|
||||
if (keyinfo.Key == ConsoleKey.DownArrow)
|
||||
{
|
||||
if (selected + 1 < options.Count)
|
||||
{
|
||||
selected++;
|
||||
this.PrintMenu();
|
||||
}
|
||||
}
|
||||
if (keyinfo.Key == ConsoleKey.UpArrow)
|
||||
{
|
||||
if (selected > 0)
|
||||
{
|
||||
selected--;
|
||||
this.PrintMenu();
|
||||
}
|
||||
}
|
||||
if (keyinfo.Key == ConsoleKey.Enter)
|
||||
{
|
||||
Console.Clear();
|
||||
options[selected].Action.Invoke();
|
||||
}
|
||||
} while (keyinfo.Key != ConsoleKey.Enter);
|
||||
}
|
||||
private void PrintMenu()
|
||||
{
|
||||
Console.Clear();
|
||||
Console.WriteLine(title);
|
||||
int optionIndex = 0;
|
||||
foreach (Option option in options)
|
||||
{
|
||||
string pointer = optionIndex == selected ? " ->" : " ";
|
||||
Console.WriteLine($"{pointer}{option.Name}");
|
||||
optionIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
private struct Option
|
||||
{
|
||||
public string Name { get; }
|
||||
public Action Action { get; }
|
||||
|
||||
public Option(string name, Action action)
|
||||
{
|
||||
Name = name;
|
||||
Action = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user