2016-01-08 18 views
9

Espansione sul mio post precedente, sto ancora scrivendo Towers of Hanoi. Dopo aver trovato una soluzione meravigliosa su come disegnare gli anelli sui pioli, ho ancora una domanda con cui mi sto divertendo da un po 'ora.Towers of Hanoi: Moving Rings da Peg a Peg

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

E qui è il mio metodo principale.

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

Questa è la corrente di uscita:

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

La mia domanda rimane, come si fa a spostare il '-' caratteri da piolo a piolo quando gli viene chiesto per un prompt. Ho provato a modificarlo per ore e ancora non riuscivo a capirlo.

Grazie in anticipo, youmeoutside

+1

Benvenuti a overflow dello stack! Per favore, la prossima volta che posti una domanda, puoi indentarla correttamente? Non solo aiuterà le persone a leggere e comprendere il tuo codice, ma renderà anche più ordinato per te e chiunque altro lo leggerà. – Rob

+1

Per capire meglio la tua domanda, vuoi spostare i pioli sull'output originale della Console? O vuoi ridisegnare un nuovo sistema di pegging dopo ogni input? – Ruskin

+1

È necessario creare gli anelli come oggetti separati. Come mostra ora hai 3 anelli con la stessa larghezza, non sono torri di hanoi, è qualcosa di diverso. Quindi "l'altezza" di un piolo è data da quanti anelli hai su di esso ma devi istanziare gli anelli come oggetti concreti che hanno una larghezza. –

risposta

3

Hai manifestato gli anelli come solo "quanti anelli sono su questo peg", ma che non saranno sufficienti.

Per esempio, se si dispone di 8 anelli si rappresentare un anello con larghezza di 1, una con larghezza di 2, uno con 3, ecc fino a quella con 8.

nell'immagine si dispone di 3 anelli con larghezza 1 (quella superiore su ciascun piolo), 2 con larghezza 2 (il secondo anello sui due pioli che hanno più anelli) e così via. Ciò non è corretto e il motivo per cui il codice lo fa è che non ha la nozione di "quanto dovrebbe essere largo questo particolare anello", invece disegna l'anello superiore con larghezza 1, quello sottostante con larghezza 2, ecc.

Invece ecco un semplice insieme di oggetti per rappresentare gli anelli e pioli e il funzionamento di passare da uno all'altro:

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

creare 3 pioli e stack 8 anelli sul primo piolo si potrebbe usa questo codice:

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

Per disegnarli mi sono preso la libertà di ideare un programma che disegna LINQPad loro di dimostrare, ma si potrebbe facilmente adattare questo al codice console che hai ora:

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

L'output:

pegs and rings

+0

Questa è un'ottima soluzione. Ti apprezzo per il tempo che mi hai dedicato per aiutarmi a capire questo. Ma come farebbe a non utilizzare nessuno degli oggetti IEnumerable? Non c'è altro modo per farlo, ma quello? – youmeoutside

+0

Se hai sempre 3 pioli, fai in modo che i metodi che prendono i picchetti come una raccolta prendano i peg in modo specifico, come 'Peg a, Peg b, Peg c' (probabilmente con nomi migliori). –