【问题标题】:Towers of Hanoi: Moving Rings from Peg to Peg河内塔:从 Peg 到 Peg 的移动环
【发布时间】:2016-01-08 04:42:51
【问题描述】:

扩展我之前的帖子,我仍在写河内塔。在解释了如何在钉子上画戒指的绝妙解决方案之后,我仍然有一个问题我已经摆弄了很长一段时间了。

这是我的 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("----------------");
        }
    }
}

这是我的主要方法。

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);
        }
    }
}

这是当前的输出:

                |                   |                   |        
                |                   |                   |       
                |                   |                   |      
                |                   |                   |     
                |                   |                  -|-
                |                   |                 --|--
                |                  -|-               ---|---
               -|-                --|--             ----|----
         ----------------    ----------------    ----------------

我的问题仍然存在,当被要求提示时,如何将“-”字符从一个钉子移到另一个钉子。我已经尝试调整它几个小时,但仍然无法弄清楚。

提前谢谢你,youmeoutside

【问题讨论】:

  • 欢迎堆栈溢出!请,下次您发布问题时,您可以正确缩进吗?它不仅可以帮助人们阅读和理解您的代码,还可以让您和其他阅读代码的人更整洁。
  • 为了更好地理解您的问题,您要移动控制台原始输出上的钉子吗?或者您想在每次输入后重新绘制一个新的挂钩系统?
  • 您必须将环创建为单独的对象。正如它现在显示的那样,您有 3 个宽度相同的环,这不是河内的塔,这是不同的东西。因此,钉子的“高度”取决于你有多少个环,但你需要将环实例化为具有宽度的具体对象。
  • @Rob,对于给 Rob 带来的轻微不便,我们深表歉意,感谢您的帮助。
  • @Ruskin,我希望能够移动控制台原始输出上的钉子。因此,例如,第一个钉子有 3 个环,那么您必须将这些环相应地移动到其他钉子上。

标签: c# .net windows console


【解决方案1】:

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

例如,如果您有 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; }
}

要创建 3 个钉子并在第一个钉子上堆叠 8 个环,您可以使用以下代码:

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);

为了绘制它们,我冒昧地充实了一个 LINQPad 程序来绘制它们以进行演示,但您可以轻松地将其调整为您现在拥有的控制台代码:

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;
}

输出:

【讨论】:

  • 这是一个非常好的解决方案。我赞赏你花时间帮助我理解这一点。但是如何不使用任何 IEnumerables 呢?除此以外没有别的办法吗?
  • 如果你总是有 3 个 pegs,只需让将 pegs 作为集合的方法专门使用 pegs,例如 Peg a, Peg b, Peg c(尽管可能有更好的名称)。
猜你喜欢
  • 2012-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
相关资源
最近更新 更多