2016-01-08 11 views
9

私の前のポストでは、私はまだタワーズオブハノイを書いています。素晴らしい解決策を説明した後、どのようにリングをペグに描くかについて、私はまだしばらくの間、手をつけていたという疑問が1つあります。ハノイの塔:ペグからペグへのリングの移動

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

そして、ここに私の主な方法です。

は、ここに私のPegClassです。

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

これは、現在の出力です:

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

私の質問は1つが移動しないか、残っている - プロンプトのために求められたとき、PEGとペグから文字「」を。私は数時間それを調整しようとしたが、まだそれを理解することができませんでした。

はただ「どのように多くのリング、このペグの上にある」しかし、それは十分ではないとして、あなたがリングを明らかにしている、事前にyoumeoutside

+1

は、スタックオーバーフローへようこそ!次回に質問を投稿するときは、正しくインデントしてください。人々があなたのコードを読んで理解するのを助けるだけでなく、それを読んだ人や他の誰もがそれをより穏やかにするでしょう。 – Rob

+1

あなたの質問をもっとよく理解するために、コンソールの元の出力にペグを移動したいですか?あるいは、入力ごとに新しいペグシステムを再描画したいですか? – Ruskin

+1

リングを個別のオブジェクトとして作成する必要があります。今度は同じ幅の3つのリングがありますが、これはハノイの塔ではありません。これは別のものです。だから、ペグの「高さ」はあなたが持っているリングの数によって与えられますが、幅を持つ具体的なオブジェクトとしてリングをインスタンス化する必要があります。 –

答えて

3

、ありがとうございました。あなたは8つのリングを持っている場合

たとえば、あなたがあなたのイメージ8.

で1まで、幅が2で幅1、1と3、などと一つに一つの環を表します、あなたは3個の環とを持っています幅1(各ペグの上の1つ)、幅2の2つ(複数のリングを持つ2つのペグの2番目のリング)などがあります。これは間違っていて、なぜコードがこれを行うのかという理由は、「この特定のリングがどれだけ広いか」という概念がなく、幅1のトップリング、幅2の下のトップリングなどを描画します。

3つのペグとスタック、あなたは可能性が最初にペグの8つのリングを作成するには

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

:代わりに、ここで

は、一方から他方へ移動するためにリングとペグとの動作を表現するオブジェクトの非常にシンプルなセットですこのコードを使用してください:

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つのペグを持っていたら、コレクションとしてのペグを取るメソッドを、ペグa、ペグb、ペグcのように具体的にペグを取るようにしてください。 –

関連する問題