C# 河内的塔:从一个木桩到另一个木桩移动圆环

C# 河内的塔:从一个木桩到另一个木桩移动圆环,c#,.net,windows,console,C#,.net,Windows,Console,在我上一篇文章的基础上,我仍在写《河内之塔》。在解释了如何在钉子上画环的奇妙解决方案之后,我仍然有一个问题,我已经摆弄了很长一段时间了 这是我的课: namespace Towers_Of_Hanoi { class PegClass { private int pegheight; private int y = 3; int[] rings = new int[0]; public 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("----------------");
        }
    }
}
这是电流输出:

                |                   |                   |        
                |                   |                   |       
                |                   |                   |      
                |                   |                   |     
                |                   |                  -|-
                |                   |                 --|--
                |                  -|-               ---|---
               -|-                --|--             ----|----
         ----------------    ----------------    ----------------
我的问题仍然是,当要求提示时,如何将“-”字符从一个peg移动到另一个peg。我已经试着调整了好几个小时,但仍然没有弄明白


提前谢谢你,youmeoutside

你已经将戒指显示为“这个钉子上有多少个戒指”,但这还不够

例如,如果您有8个环,您将表示一个宽度为1的环,一个宽度为2的环,一个宽度为3的环,等等,最多表示一个宽度为8的环

在您的图像中,您有3个宽度为1的环(每个销钉上的顶部一个),2个宽度为2的环(两个销钉上有多个环的第二个环),依此类推。这是不正确的,您的代码之所以这样做,是因为它不知道“这个特定的环应该有多宽”,而是绘制了宽度为1的顶环,宽度为2的下环,等等

相反,这里有一组非常简单的对象来表示环和销钉,以及从一个移动到另一个的操作:

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; }
}
为了绘制它们,我冒昧地充实了一个绘制它们的程序以进行演示,但您可以很容易地将其改编为您现在拥有的控制台代码:

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;
}
void Main()
{
常数int pegCount=3;
const int ringCount=8;
var pegs=Enumerable.Range(1,pegCount)。选择(=>new Peg()).ToList();
foreach(枚举范围(1,ringCount)中的var环。选择(宽度=>new环(ringCount+1-width)))
销钉[0]。推(环);
牵引栓;
移动(销钉[0],销钉[1]);
牵引栓;
}
公共空间移动(Peg fromPeg,Peg toPeg)
{
toPeg.Push(fromPeg.Pop());
}
公共类Peg:Stack
{
}
公共结构环
{
公共整数宽度{get;}
公共环(整数宽度){width=width;}
}
公用空心吊杆(IEnumerable吊杆)
{
var bitmap=pegs.Select(peg=>DrawPeg(peg));
Util.HorizontalRun(true,位图).Dump();
}
公共位图挂起(挂起)
{
常数int宽度=200;
const int height=300;
常数int pegWidth=6;
常数int环高=20;
常数int环宽因子=10;
常数int ringGapHeight=3;
var结果=新位图(宽度、高度);
使用(var g=Graphics.FromImage(结果))
{
g、 清晰(颜色:白色);
g、 FillRectangle(画笔.黑色,宽度/2-pegWidth/2,0,pegWidth,高度);
int y=高度;
foreach(peg.Reverse()中的var环)
{
y-=环高;
g、 FillRectangle(画笔。蓝色,宽度/2-环。宽度*环宽度因子,y,2*环。宽度*环宽度因子,环高度);
y-=环隙光;
}
}
返回结果;
}
输出:


欢迎使用堆栈溢出!请,下次你发布问题时,你能正确缩进它吗?它不仅可以帮助人们阅读和理解您的代码,还可以让您和其他阅读您的代码的人更整洁。为了更好地理解您的问题,是否要移动控制台原始输出上的标记?或者你想在每次输入后重新绘制一个新的peg系统吗?你必须创建环作为单独的对象。正如它所显示的,现在你有3个相同宽度的环,这不是河内的塔,这是不同的东西。因此,木钉的“高度”由其上有多少个环来表示,但您需要将这些环实例化为具有宽度的具体对象。@Rob,很抱歉给您带来了一些不便Rob,感谢您的帮助。@Ruskin,我希望能够移动控制台原始输出上的木钉。例如,第一个销钉有3个环,然后你必须相应地移动环到其他销钉上。这是一个很好的解决方案。我为你花时间帮助我理解这一点而鼓掌。但是,如果不使用任何IEnumerables,该怎么做呢?没有其他方法可以做到这一点吗?如果你总是要有3个Peg,那么只需让将Peg作为集合的方法专门使用Peg,比如
Peg a、Peg b、Peg c
(可能有更好的名称)。
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);
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;
}