рефактор HanoyTowers, добавление решателя
This commit is contained in:
109
HanoiTowers.cs
109
HanoiTowers.cs
@@ -1,82 +1,113 @@
|
||||
namespace su.divan2000.PLandDS_hanoi
|
||||
namespace su.divan2000.PLandDS_HanoiTowers
|
||||
{
|
||||
class HanoiTowers
|
||||
{
|
||||
private int[] tower_A;
|
||||
private int[] tower_B;
|
||||
private int[] tower_C;
|
||||
|
||||
private int[][] towers;
|
||||
private int size;
|
||||
|
||||
public enum TowerName { A, B, C }
|
||||
public int Size { get { return size; } }
|
||||
|
||||
public HanoiTowers(int size)
|
||||
{
|
||||
this.size = size;
|
||||
tower_A = new int[size];
|
||||
tower_B = new int[size];
|
||||
tower_C = new int[size];
|
||||
towers = new int[3][];
|
||||
towers[0] = new int[size];
|
||||
towers[1] = new int[size];
|
||||
towers[2] = new int[size];
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
tower_A[i] = size - i;
|
||||
towers[0][i] = size - i;
|
||||
}
|
||||
}
|
||||
|
||||
public string toString()
|
||||
public override string ToString()
|
||||
{
|
||||
int charsPerTower = size.ToString().Length;
|
||||
string result = "";
|
||||
for (int i = size - 1; i >= 0; i--)
|
||||
{
|
||||
result += tower_A[i].ToString().PadLeft(charsPerTower).Replace("0", "|") + " ";
|
||||
result += tower_B[i].ToString().PadLeft(charsPerTower).Replace("0", "|") + " ";
|
||||
result += tower_C[i].ToString().PadLeft(charsPerTower).Replace("0", "|") + "\n";
|
||||
result += towers[0][i].ToString().PadLeft(charsPerTower).Replace("0", "|") + " ";
|
||||
result += towers[1][i].ToString().PadLeft(charsPerTower).Replace("0", "|") + " ";
|
||||
result += towers[2][i].ToString().PadLeft(charsPerTower).Replace("0", "|") + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void move(int from, int to)
|
||||
public void move(TowerName from, TowerName to)
|
||||
{
|
||||
int[] sourceTower = getTower(from);
|
||||
int[] targetTower = getTower(to);
|
||||
if (from == to) return;
|
||||
|
||||
int[] sourceTower = towers[(int)from];
|
||||
int[] targetTower = towers[(int)to];
|
||||
int sourceTopIndex = getTopIndex(sourceTower);
|
||||
int targetTopIndex = getTopIndex(targetTower);
|
||||
|
||||
if (sourceTopIndex == -1)
|
||||
{
|
||||
throw new InvalidOperationException("No disk to move");
|
||||
}
|
||||
|
||||
if (targetTopIndex != -1 && sourceTower[sourceTopIndex] > targetTower[targetTopIndex])
|
||||
{
|
||||
if (sourceTopIndex < 0)
|
||||
throw new InvalidOperationException("Source tower is empty");
|
||||
if (targetTopIndex >= size)
|
||||
throw new InvalidOperationException("Target tower is full");
|
||||
if (targetTopIndex > 0 && sourceTower[sourceTopIndex] > targetTower[targetTopIndex])
|
||||
throw new InvalidOperationException("Cannot place larger disk on smaller one");
|
||||
}
|
||||
|
||||
|
||||
targetTower[targetTopIndex + 1] = sourceTower[sourceTopIndex];
|
||||
sourceTower[sourceTopIndex] = 0;
|
||||
}
|
||||
|
||||
private int[] getTower(int index)
|
||||
public int getTopIndex(int[] tower)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return tower_A;
|
||||
case 1: return tower_B;
|
||||
case 2: return tower_C;
|
||||
default: throw new ArgumentException("Invalid tower index");
|
||||
}
|
||||
}
|
||||
|
||||
private int getTopIndex(int[] tower)
|
||||
{
|
||||
for (int i = size - 1; i >= 0; i--)
|
||||
for (int i = size-1; i >= 0; i--)
|
||||
{
|
||||
if (tower[i] != 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // Tower is full
|
||||
return -1; // Tower is empty
|
||||
}
|
||||
}
|
||||
|
||||
static class HanoiUtils
|
||||
{
|
||||
public struct Move
|
||||
{
|
||||
public HanoiTowers.TowerName From;
|
||||
public HanoiTowers.TowerName To;
|
||||
|
||||
public Move(HanoiTowers.TowerName from, HanoiTowers.TowerName to)
|
||||
{
|
||||
From = from;
|
||||
To = to;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Move> MoveN(HanoiTowers towers, int n, HanoiTowers.TowerName from, HanoiTowers.TowerName to, HanoiTowers.TowerName aux)
|
||||
{
|
||||
List<Move> moves = new List<Move>();
|
||||
if (n == 1)
|
||||
{
|
||||
moves.Add(new Move(from, to));
|
||||
}
|
||||
else
|
||||
{
|
||||
moves.AddRange(MoveN(towers, n - 1, from, aux, to));
|
||||
moves.Add(new Move(from, to));
|
||||
moves.AddRange(MoveN(towers, n - 1, aux, to, from));
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
public static void ExecuteMoves(HanoiTowers towers, List<Move> moves)
|
||||
{
|
||||
foreach (Move move in moves)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user