2016-01-08 24 views
9

扩大我以前的职位,我仍然在写河内塔。在解释了如何在钉上画环之后,我仍然有一个问题,现在我已经摆弄了很长一段时间了。河内塔:从钉挂环到挂钩

这里是我的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

+1

欢迎堆栈溢出!请在下次发布问题时,能否正确缩进?它不仅可以帮助人们阅读和理解你的代码,它还可以让你阅读并理解你的代码。 – Rob

+1

为了更好地理解您的问题,您是否想要在控制台的原始输出上移动挂钩?或者你想在每次输入后重新绘制一个新的挂钩系统? – Ruskin

+1

您必须创建戒指作为单独的对象。正如它现在显示你有三个相同宽度的戒指,这不是河内的塔,这是不同的。所以钉的高度是由多少个环给出的,但你需要将环实例化为具有宽度的具体物体。 –

回答

3

您已经体现了环统称为“多环是如何在这个挂钩”,但还不够。

例如,如果你有8个环你将代表一个环具有宽度1,一个具有宽度为2,一个具有3等,至多一个与8.

在图像你有3个环带宽度为1(每个钉上的最高一个),宽度为2(两个钉上有多个环的第二个环),依此类推。这是不正确的,并且你的代码为什么这样做的原因是它没有“这个特定环应该多宽”的概念,而是它绘制了宽度为1的顶环,宽度为2的顶环,等等。

相反这里是一个非常简单的设置对象来表示环和PEG和操作从一个移动到另一个:

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个钉和您可以在第一PEG堆叠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; 
} 

输出:

pegs and rings

+0

这是一个非常好的解决方案。我鼓励你花时间帮助我理解这一点。但是,如何使这不使用任何IEnumerables?除此之外,没有其他办法可以做到吗? – youmeoutside

+0

如果你总是有3个挂钩,那么只需要将挂钩作为一个集合的方法具体地采用挂钩,比如'Peg a,Peg b,Peg c'(尽管可能有更好的名字)。 –