Expanding on my previous post, I am still writing Towers of Hanoi. After having a wonderful solution explained of how to draw the rings on the pegs, I still have one question that I have been fiddling with for quite awhile now.
Here is my PegClass:
namespace Towers_Of_Hanoi
{
class PegClass
{
private int pegheight;
private int y = 3;
int[] rings = new int[0];
public PegClass()
{
//this is the default constructor
}
public PegClass(int height)
{
pegheight = height;
}
// other user defined functions
public void AddRing(int size)
{
Array.Resize (ref rings, rings.Length + 2);
rings[rings.Length - 1] = size;
}
public void DrawPeg(int x, int numberOfRings = 0)
{
for (int i = pegheight; i >= 1; i--)
{
string halfRing = new string (' ', i);
if (numberOfRings > 0)
{
if (i <= numberOfRings)
halfRing = new string ('-', numberOfRings - i + 1);
}
Console.SetCursorPosition(x - halfRing.Length * 2 + i + (halfRing.Contains("-") ? (-i + halfRing.Length) : 0), y);
Console.WriteLine(halfRing + "|" + halfRing);
y++;
}
if (x < 7) {
x = 7;
}
Console.SetCursorPosition (x - 7, y); //print the base of the peg
Console.WriteLine("----------------");
}
}
}
And here is my main method.
namespace Tower_of_hanoi
{
class Program
{
static void Main(string[] args)
{
PegClass myPeg = new PegClass(8);
PegClass myPeg2 = new PegClass(8);
PegClass myPeg3 = new PegClass(8);
DrawBoard(myPeg, myPeg2, myPeg3);
Console.WriteLine ("\t\t\nWelcome to kTowers!");
while (true)
{
string input = "\nWhat peg do you want to move to commander?";
Console.WriteLine (input);
if (input == "2")
{
myPeg.DrawPeg (2);
}
Console.ReadLine ();
}
}
public static void DrawBoard(PegClass peg1,PegClass peg2,PegClass peg3)
{
Console.Clear();
peg1.DrawPeg(20,1);
peg2.DrawPeg(40,2);
peg3.DrawPeg(60,4);
}
}
}
This is the current output:
| | |
| | |
| | |
| | |
| | -|-
| | --|--
| -|- ---|---
-|- --|-- ----|----
---------------- ---------------- ----------------
My question remains, how does one move the '-' characters from peg to peg when asked for a prompt. I've tried tweaking it for hours and still couldn't figure it out.
Thank you in advance, youmeoutside
Rules. Only one disk can be moved among the towers at any given time. Only the "top" disk can be removed. No large disk can sit over a small disk.
The full Tower of Hanoi solution then consists of moving n disks from the source peg A to the target peg C, using B as the spare peg. This approach can be given a rigorous mathematical proof with mathematical induction and is often used as an example of recursion when teaching programming.
In this formula, S is the number of steps, and N is the number of discs. So, if the tower had five discs, the formula would be 25-1, which is 31. Therefore, solving the puzzle would take a minimum of 31 steps. If it had four discs, it would require only 15 steps – and for three discs, only 7.
You have manifested the rings as just "how many rings are on this peg" but that won't be enough.
For instance, if you have 8 rings you will represent one ring with width 1, one with width 2, one with 3, etc. up to one with 8.
In your image you have 3 rings with width of 1 (the top one on each peg), 2 with width 2 (the second ring on the two pegs that have multiple rings), and so on. This is incorrect and the reason for why your code does this is that it have no notion of "how wide should this particular ring be", instead it draws the top ring with width 1, the one below it with width 2, etc.
Instead here is a very simple set of objects to represent the rings and pegs and the operation to move from one to the other:
public void MoveRing(Peg fromPeg, Peg toPeg)
{
toPeg.Push(fromPeg.Pop());
}
public class Peg : Stack<Ring>
{
}
public struct Ring
{
public int Width { get; }
public Ring(int width) { Width = width; }
}
To create 3 pegs and stack 8 rings on the first peg you could use this code:
const int pegCount = 3;
const int ringCount = 8;
var pegs = Enumerable.Range(1, pegCount).Select(_ => new Peg()).ToList();
foreach (var ring in Enumerable.Range(1, ringCount).Select(width => new Ring(ringCount + 1 - width)))
pegs[0].Push(ring);
To draw them I took the liberty of fleshing out a LINQPad program that draws them to demonstrate but you could easily adapt this to the console code you have now:
void Main()
{
const int pegCount = 3;
const int ringCount = 8;
var pegs = Enumerable.Range(1, pegCount).Select(_ => new Peg()).ToList();
foreach (var ring in Enumerable.Range(1, ringCount).Select(width => new Ring(ringCount + 1 - width)))
pegs[0].Push(ring);
DrawPegs(pegs);
MoveRing(pegs[0], pegs[1]);
DrawPegs(pegs);
}
public void MoveRing(Peg fromPeg, Peg toPeg)
{
toPeg.Push(fromPeg.Pop());
}
public class Peg : Stack<Ring>
{
}
public struct Ring
{
public int Width { get; }
public Ring(int width) { Width = width; }
}
public void DrawPegs(IEnumerable<Peg> pegs)
{
var bitmaps = pegs.Select(peg => DrawPeg(peg));
Util.HorizontalRun(true, bitmaps).Dump();
}
public Bitmap DrawPeg(Peg peg)
{
const int width = 200;
const int height = 300;
const int pegWidth = 6;
const int ringHeight = 20;
const int ringWidthFactor = 10;
const int ringGapHeight = 3;
var result = new Bitmap(width, height);
using (var g = Graphics.FromImage(result))
{
g.Clear(Color.White);
g.FillRectangle(Brushes.Black, width / 2 - pegWidth/2, 0, pegWidth, height);
int y = height;
foreach (var ring in peg.Reverse())
{
y -= ringHeight;
g.FillRectangle(Brushes.Blue, width / 2 - ring.Width * ringWidthFactor, y, 2 * ring.Width * ringWidthFactor, ringHeight);
y -= ringGapHeight;
}
}
return result;
}
The output:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With