Ich brauche dringend Hilfe bei einer Perlaufgabe. Kann mir jemand helfen?

...komplette Frage anzeigen

2 Antworten

Dein Programm gibt überhaupt keinen Schritt aus. In der Funktion move fehlt der Teil, der tatsächlich eine Scheibe bewegt. so ruft sie nur sich selbst auf und macht im Endeffekt nichts.

Ich denke, dass die Stäbe die Information enthalten müssen, welche Scheiben gerade darauf liegen. Der Algorithmus wird dann etwa so gestartet:

move($Scheibenanzahl, '54321', '', '');

Um solche Stäbe graphisch auszugeben, würde ich so vorgehen:

$stab_a = "542";
$stab_b = "";
$stab_c = "31";

for (my $i=$Scheibenanzahl-1; $i>=0; --$i)
{
 printf( " %*s : %*s : %*s\n"
, $Scheibenanzahl, $i<length $stab_a ? "X" x substr($stab_a,$i,1) : "|"
, $Scheibenanzahl, $i<length $stab_b ? "X" x substr($stab_b,$i,1) : "|"
, $Scheibenanzahl, $i<length $stab_c ? "X" x substr($stab_c,$i,1) : "|"
);
}

Sieht dann etwa so aus:

     | :     | :     |
| : | : |
XX : | : |
XXXX : | : X
XXXXX : | : XXX

Das lässt sich sicher noch kompakter schreiben und graphisch aufpeppen...

danmii 17.10.2016, 13:58

Wie würde diese Variante denn in meinem Code aussehen?

0
ralphdieter 17.10.2016, 14:15
@danmii

Klatsche die for-Schleife einfach in die move()-Funktion rein, direkt hinter die beiden rekursiven move()-Aufrufe.

Zwischen den beiden fehlt allerdings noch der Code zum Bewegen eines Steins...

0
danmii 17.10.2016, 14:30
@ralphdieter

print("Wie viele Scheiben sollen bei dem Spiel: Türme von Hanoi verwendet werden?\n");
my $Scheibenanzahl = ;
chomp $Scheibenanzahl;
if (!($Scheibenanzahl =~ /^[0-9]+$/))
{
print "Das war keine Zahl\n";
}

sub move {
my $anzahl = shift; my $stab_a = shift; my $stab_b = shift; my $stab_c = shift;
for (my $i=$Scheibenanzahl-1; $i>=0; --$i) {
 printf "%*s : %*s : %*s\n"

, $Scheibenanzahl, .......

...

      );

}

if ($anzahl > 0) {
move($anzahl - 1, $stab_a, $stab_c, $stab_b);
print("Verschiebe oberste Scheibe von $stab_a nach $stab_c \n");
move($anzahl - 1, $stab_b, $stab_a, $stab_c);
     }
}

move($Scheibenanzahl, '54321', '', '');

0
danmii 17.10.2016, 14:31
@ralphdieter

Hast du einen Vorschlag wie ich am besten die Steine verschieben könnte?

0
danmii 17.10.2016, 14:53
@ralphdieter

Ich wäre dir wirklich unglaublich dankbar wenn du den kompletten Code geben würdest. Ich stehe einfach gerade etwas auf dem Schlauch :(

1
ralphdieter 17.10.2016, 15:20
@danmii

Ich stehe einfach gerade etwas auf dem Schlauch :(

Darf ich raten: Du hast keinen Plan :-/

Ich habe mal 'rumprobiert: @board ist ein globales Array, das die 3 Stäbe als Strings enthält. move() erhält nur noch die Indizes darauf.

Zwischen den beiden rekursiven move() wird nun das globale board geändert (und ausgegeben). Das sieht dann fertig so aus:

@board = ( scalar(reverse 1..$Scheibenanzahl), '', '' );

sub move
{
my $anzahl = shift;
my $von = shift;
my $via = shift;
my $nach = shift;

if ($anzahl > 0)
{
move($anzahl-1, $von, $nach, $via);

$board[$nach] .= chop $board[$von];

for (my $i=$Scheibenanzahl-1; $i>=0; --$i)
{
printf( " %*s : %*s : %*s\n"
, $Scheibenanzahl, $i<length $board[0] ? "X" x substr($board[0], $i, 1) : "|"
, $Scheibenanzahl, $i<length $board[1] ? "X" x substr($board[1], $i, 1) : "|"
, $Scheibenanzahl, $i<length $board[2] ? "X" x substr($board[2], $i, 1) : "|"
);
}
print "\n";

move($anzahl-1, $via, $von, $nach);
}
}

move($Scheibenanzahl, 0..2);

Bei mir tut's — aber ich muss dazusagen, dass das mein erstes perl-Script ist. Ein Profi wird sich da wohl die Haare raufen.

1
ralphdieter 17.10.2016, 15:46
@ralphdieter

Eben fällt mir auf:

reverse 1..$Scheibenanzahl

arbeitet auf dem String der einzelnen Ziffern. Das geht bei mehr als 9 Scheiben natürlich in die Hose ("211101987654321"). Aber ich habe keine Ahnung, wie man in perl eine Liste aus Zahlen umdreht...

0

Die Formatierung ist etwas misslungen... Die Darstellung soll drei Türme mithilfe von Textzeichen darstellen.

Was möchtest Du wissen?