Forum: PC-Programmierung Prüfungsaufgabe hänge gerade


von Matthias Knab (Gast)


Lesenswert?

Servus,
ich muss als Prüfungsaufgabe die Türme von Hanoi programmieren.

Nun habe ich ein Menü erstellt wo ich einstellen kann wie viele Scheiben 
ich verwenden will.

jetzt fehlt mir aber irgendwie der Weg vom Code in die Grafik. Irgendwie 
kann ich mir vorstellen das ganze mit nem array zu lösen ala:

int RingeTurmA [Ringe eingestellt] = Ringe eingestellt.


Nur wenn ich das ganze dann ausgebe und durchzähle zeigt er mir beim 
aufzählen immer noch 13 und beim abzählen -1 an. ebenso will ich halt 
wenn ein überlauf is von 12 auf 0 zb dass die arrays dann auch wieder 0 
gesetzt werden nur wie kann ich dass bei allen auf einmal machen bzw 
wenn ich ein überlauf von 0 auf 12 habe sollen ja auch die zahlen dann 
drinn stehen.

Hab hier mal meinen Code is aber nur ein testcode. am richtigen arbeite 
ich weiter wenn ich dass hinbekommen habe.

Kann mir da mal jemand bischen unterstützung geben?

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include "Utilities.h"

#define Max 12

void Ausgabe (struct Konfiguration Ausgabe);
int Auswahl (struct Konfiguration* Ringe);

struct Konfiguration
{
  int iAnzahlRinge;
  int iModus;
  int iProgrammbeenden;
  int iRingeTurmA[Max];
};

void main (void)
{

  struct Konfiguration sKonfig;
  sKonfig.iAnzahlRinge = 0;
  sKonfig.iProgrammbeenden = 0;
  sKonfig.iRingeTurmA[sKonfig.iAnzahlRinge] = sKonfig.iAnzahlRinge;




  while (sKonfig.iProgrammbeenden != 'q')
  {
    Ausgabe(sKonfig);
    sKonfig.iProgrammbeenden = Auswahl(&sKonfig.iAnzahlRinge);
  }
}


void Ausgabe (struct Konfiguration Ausgabe)
{
  _gotoxy (15,22);              //Ausgabe Ringe
  if ( Ausgabe.iAnzahlRinge < 10)
  {
    printf("0%d", Ausgabe.iAnzahlRinge);
  }
  else
  {
    printf("%d", Ausgabe.iAnzahlRinge);
  }

}


int Auswahl(struct Konfiguration* Konfig)  //Funktionen
{

  int i = 0;
  Konfig->iAnzahlRinge;
  Konfig->iModus;

  Konfig->iProgrammbeenden = _getch();


  if ( Konfig->iProgrammbeenden == '+')    //ab hier werden die Ringe 
aufgezählt
    {
      (Konfig->iAnzahlRinge)++;
      Konfig->iRingeTurmA[Konfig->iAnzahlRinge] = Konfig->iAnzahlRinge;
      _gotoxy(10,16 - Konfig->iAnzahlRinge);
      printf("%d", Konfig->iRingeTurmA[Konfig->iAnzahlRinge]);

        if (Konfig->iAnzahlRinge > Max)
        {
          Konfig->iAnzahlRinge = 0;
        }
    }


  if ( Konfig->iProgrammbeenden == '-')    //ab hier werden die Ringe 
abgezählt
    {
      (Konfig->iAnzahlRinge)--;
      Konfig->iRingeTurmA[Konfig->iAnzahlRinge] = Konfig->iAnzahlRinge;
      _gotoxy(10,16 - Konfig->iAnzahlRinge);
      printf("%d", Konfig->iRingeTurmA[Konfig->iAnzahlRinge]);

        if (Konfig->iAnzahlRinge < 0)
        {
          Konfig->iAnzahlRinge = Max;
        }
    }


  return Konfig->iProgrammbeenden;
}

von Karl H. (kbuchegg)


Lesenswert?

Matthias Knab schrieb:
> Servus,
> ich muss als Prüfungsaufgabe die Türme von Hanoi programmieren.

Was genau musst du progammieren?

Brauchst du eine grafische Repräsentierung damit der Benutzer das Rätsel 
lösen kann oder brauchst du ein Programm welches dir sagt, welche 
Scheibe wohin verfrachtet werden muss.

Das ist ein Unterschied. Eine rekursive Lösung für Hanoi ist ein 
7-Zeiler


> struct Konfiguration
> {
>   int iAnzahlRinge;
>   int iModus;
>   int iProgrammbeenden;
>   int iRingeTurmA[Max];
> };

Sieht schon gut aus.

>   sKonfig.iProgrammbeenden = 0;
>   sKonfig.iRingeTurmA[sKonfig.iAnzahlRinge] = sKonfig.iAnzahlRinge;

Äh nein.
Irgendwie hab ich das Gefühl, dir ist noch nicht klar, was du überhaupt 
in deinem Array speichern willst.
Was bedeuten denn die Zahlen im Array? Wie willst du es verwenden?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Matthias Knab schrieb:
> if ( Ausgabe.iAnzahlRinge < 10)
>   {
>     printf("0%d", Ausgabe.iAnzahlRinge);
>   }
>   else
>   {
>     printf("%d", Ausgabe.iAnzahlRinge);
>   }

Du solltest Dir mal die Dokumentation von printf genauer ansehen.

Das geht auch mit einem einfachen

  printf("%02d", Ausgabe.iAnzahlRinge);

von Matthias Knab (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Brauchst du eine grafische Repräsentierung damit der Benutzer das Rätsel
> lösen kann oder brauchst du ein Programm welches dir sagt, welche
> Scheibe wohin verfrachtet werden muss.

das programm muss entweder automatisch durchlaufen oder wenn ich die 
leertaste drücke schritt für schritt durchlaufen. sprich bei jedem druck 
der leertaste muss er einen schritt weiter gehn. also eine scheibe 
verschieben.

das ganze soll in etwa so aussehen:

#                #                #
##               ##               ##
###              ###              ###
####             ####             ####
#####            #####            #####
######           ######           ######

Turm A           Turm B           Turm C

am anfang soll man auf Turm a die Ringe aufzählen können, diese Funktion 
hab ich ja schon. Nur wie gebe ich es eben aus?

Karl heinz Buchegger schrieb:
> Äh nein.
> Irgendwie hab ich das Gefühl, dir ist noch nicht klar, was du überhaupt
> in deinem Array speichern willst.
> Was bedeuten denn die Zahlen im Array? Wie willst du es verwenden?

ich nehme mal an deine aussage bezieht sich hier drauf:

sKonfig.iRingeTurmA[sKonfig.iAnzahlRinge] = sKonfig.iAnzahlRinge;


hier hab ich mir gedacht dass ich in das array von [1-12] die Ringe 
eintrage also 1-12 und die dann irgendwie ausgebe. Sprich 1 wäre das 
kleinste # und 12 wäre das größte #.

Rufus Τ. Firefly schrieb:
> Das geht auch mit einem einfachen
>
>   printf("%02d", Ausgabe.iAnzahlRinge);

danke hab ich nicht gewusst habs bislang immer so gemacht und mirs halt 
so hergeleitet da hab ichs auch verstanden. aber dein vorschlag ist halt 
kürzer.

von Matthias Knab (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Äh nein.
> Irgendwie hab ich das Gefühl, dir ist noch nicht klar, was du überhaupt
> in deinem Array speichern willst.
> Was bedeuten denn die Zahlen im Array? Wie willst du es verwenden?

steht aber weiter unten nochmal drinn jeweils beim auf und abzählen. 
hier abzählen.



Matthias Knab schrieb:
> if ( Konfig->iProgrammbeenden == '-')    //ab hier werden die Ringe
> abgezählt
>     {
>       (Konfig->iAnzahlRinge)--;
>       Konfig->iRingeTurmA[Konfig->iAnzahlRinge] = Konfig->iAnzahlRinge;
>       _gotoxy(10,16 - Konfig->iAnzahlRinge);
>       printf("%d", Konfig->iRingeTurmA[Konfig->iAnzahlRinge]);
>
>         if (Konfig->iAnzahlRinge < 0)
>         {
>           Konfig->iAnzahlRinge = Max;
>         }
>     }

von Karl H. (kbuchegg)


Lesenswert?

Matthias Knab schrieb:

> das ganze soll in etwa so aussehen:
>
> #                #                #
> ##               ##               ##
> ###              ###              ###
> ####             ####             ####
> #####            #####            #####
> ######           ######           ######
>
> Turm A           Turm B           Turm C

ok.
also brauchst du eine grafische Anzeige. Gut


>> Was bedeuten denn die Zahlen im Array? Wie willst du es verwenden?
>
> ich nehme mal an deine aussage bezieht sich hier drauf:
>
> sKonfig.iRingeTurmA[sKonfig.iAnzahlRinge] = sKonfig.iAnzahlRinge;
>
>
> hier hab ich mir gedacht dass ich in das array von [1-12] die Ringe
> eintrage also 1-12 und die dann irgendwie ausgebe. Sprich 1 wäre das
> kleinste # und 12 wäre das größte #.

Wenn schon, dann brauchst du 3 Arrays, in denen du speichern kannst 
welche Rungnummer da gerade abgelegt sind.

  int TurmA[12];
  int TurmB[12];
  int TurmC[12];

dazu nach 3 Variablen, die einem sagen wieviele Ringe gerade in jedem 
Turm sind.

Bei 3 Ringen hast du also (die Arrays sind durch ... nur angedeutet)

  TurmA      3  2  1  0  0 ...        AnzRingeA  3
  TurmB      0  0  0  0  0 ...        AnzRingeB  0
  TurmC      0  0  0  0  0 ...        AnzRingeC  0


Das bedeutet: Im Turm A sind momentan 3 Ringe, in den Türmen B und C 
noch keine (AnzRingeX ist jeweils 0).
Die 3 Ringe, die im Turm A sind, sind (von unten nach oben):
  Ring mit der Nummer 3
  Ring mit der Nummer 2
  Ring mit der Nummer 1

Jetzt kommt der Benutzer und macht seinen ersten Zug. Er verlegt den 
obersten Ring von A nach C. Und genau das führst du in deinen Arrays 
aus.
Der oberste Ring von A (die Anzahl Ringe kennst du ja, steht in 
AnzRingeA) wird von A nach C überführt. Danach ist im Turm A 1 Ring 
weniger und dafür in C 1 Ring mehr. Das Endergebnis der Operation sieht 
daher so aus


  TurmA      3  2  0  0  0 ...        AnzRingeA  2
  TurmB      0  0  0  0  0 ...        AnzRingeB  0
  TurmC      1  0  0  0  0 ...        AnzRingeC  1


Der Benutzer legt den obersten Ring von A nach B um. Da die Anzahl der 
Ringe in A 2 Stück sind, ist daher der oberste Ring im Turm A an der 
Stelle TurmA[ AnzRingeA - 1] oder TurmA[1] zu finden. Dort steht 2 
drinnen (weil die oberste Scheibe jetzt die mit der Nummer 2 ist). Diese 
Scheibe kommt auf den Turm B (wo sie dorthin kommt, sagt dir wieder die 
Anzahl der in diesem Turm aktuell enthaltenen Ringe) und wieder werden 
die Anzahl der Ringe entsprechend korrigiert: in A 1 weniger, dafür in B 
1 mehr.

  TurmA      3  0  0  0  0 ...        AnzRingeA  1
  TurmB      2  0  0  0  0 ...        AnzRingeB  1
  TurmC      1  0  0  0  0 ...        AnzRingeC  1


und so gehts weiter.
C nach B
  TurmA      3  0  0  0  0 ...        AnzRingeA  1
  TurmB      2  1  0  0  0 ...        AnzRingeB  2
  TurmC      0  0  0  0  0 ...        AnzRingeC  0

A nach C
  TurmA      0  0  0  0  0 ...        AnzRingeA  0
  TurmB      2  1  0  0  0 ...        AnzRingeB  2
  TurmC      3  0  0  0  0 ...        AnzRingeC  1

B nach A
  TurmA      1  0  0  0  0 ...        AnzRingeA  1
  TurmB      2  0  0  0  0 ...        AnzRingeB  1
  TurmC      3  0  0  0  0 ...        AnzRingeC  1

B nach C
  TurmA      1  0  0  0  0 ...        AnzRingeA  1
  TurmB      0  0  0  0  0 ...        AnzRingeB  0
  TurmC      3  2  0  0  0 ...        AnzRingeC  2

und A nach C
  TurmA      0  0  0  0  0 ...        AnzRingeA  0
  TurmB      0  0  0  0  0 ...        AnzRingeB  0
  TurmC      3  2  1  0  0 ...        AnzRingeC  3



Ehe du dich da jetzt mit einer graphischen Repräsentierung verzettelst, 
sieh erst mal zu, dass du deine Ausgabe so oder so ähnlich hinkriegst, 
wie hier in diesem Posting. Einfach die 3 Türme untereinander, daneben 
welche Ringnummern jeweils im Turm sind und wieviele Ringe in diesem 
Turm sind.

Wenn dann erst mal die Array-Operationen korrekt sind, kannst du dich 
mit einer ansprechenderen Ausgabe beschäftigen.

von Karl H. (kbuchegg)


Lesenswert?

> das programm muss entweder automatisch durchlaufen oder wenn ich
> die leertaste drücke schritt für schritt durchlaufen.

Darf ich fragen, wo du die Lösung her hast wenn das automatisch 
durchlaufen soll?

Irgendwie will mir das nicht in den Schädel, dass du zwar einen 
rekursiven Hanoi-Algorithmus hinkriegst, aber mit Arrays und eigentlich 
trivialer Ausgabe auf Kriegsfuss stehst. Das ergibt keinen Sinn. Hanoi 
zu lösen ist so unedlich schwerer als eine Ausgabe zu programmieren, 
dass da etwas ganz gewaltig nicht zusammenpasst.

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> Irgendwie will mir das nicht in den Schädel, dass du zwar einen
> rekursiven Hanoi-Algorithmus hinkriegst

Das Internet ist lang und breit, Hanoi ist da gelegentlich zu finden.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Karl heinz Buchegger schrieb:
>> Irgendwie will mir das nicht in den Schädel, dass du zwar einen
>> rekursiven Hanoi-Algorithmus hinkriegst
>
> Das Internet ist lang und breit, Hanoi ist da gelegentlich zu finden.

Nun ja.
Wenn ich jetzt noch den Thread-Titel mit dazunehme, in dem das Wort 
"Prüfungsaufgabe" vorkommt, frage ich mich ob ich hier das Richtige tue.

Aber: in dubio
vielleicht hatte er wirklich nur einen Hänger. Manchmal muss man mit der 
Nase auf eine erfolgverpsrechende Datenstruktur gestossen werden.

Wenn da dann nicht wieder die Nachfrage nach dem "Wie gebe ich das aus?" 
wäre :-)

von MaWin (Gast)


Lesenswert?

> das ganze soll in etwa so aussehen:
>
> #                #                #
> ##               ##               ##
> ###              ###              ###
> ####             ####             ####
> #####            #####            #####
> ######           ######           ######
>
> Turm A           Turm B           Turm C

Falsch.

Die Position sagt nichts über den Durchmesser der Scheibe aus.
Es kann sehr gut auch so aussehen:

                                     #
  ##                                ###
######           ####             ######

Turm A           Turm B           Turm C

Du brauchst also eine Anzeige auf welchem Stapel in welcher Position 
welcher Durchmesser liegt.

int tower[3][7];

Das sollte doch einfach zu programmieren sein.

von Matthias Knab (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wenn schon, dann brauchst du 3 Arrays, in denen du speichern kannst
> welche Rungnummer da gerade abgelegt sind.

weiß ich, ich wollte es halt zuerst hinbekommen dass er mir den ersten 
turm wenigstens mal anzeigt wenn ich die ringe einstelle.

Karl heinz Buchegger schrieb:
> Darf ich fragen, wo du die Lösung her hast wenn das automatisch
> durchlaufen soll?

hä? ich hab gar nix. Das is ja das Problem. bislang bin ich nur soweit 
dass ich den modus von hand auf automatik umstellen kann und das 
programm bei verschiedenen tastendrücken etwas tut. zb beendet, die 
ringe hochzählt usw.

Mir fehlt lediglich der übergang wie ich es mit der eigentlichen 
funktion die das programm ausüben soll verschachtele.

von Karl H. (kbuchegg)


Lesenswert?

Matthias Knab schrieb:
> Karl heinz Buchegger schrieb:
>> Wenn schon, dann brauchst du 3 Arrays, in denen du speichern kannst
>> welche Rungnummer da gerade abgelegt sind.
>
> weiß ich, ich wollte es halt zuerst hinbekommen dass er mir den ersten
> turm wenigstens mal anzeigt wenn ich die ringe einstelle.

Na, ja.
Jetzt weißt du ja, wie du die Arrays am besten benutzt. In jeweiligen 
Turm-Array steht an der Index-Position 0 die jeweils unterste Scheibe.
Und von dort ausgehend ist es ja nicht mehr schwer da eine entsprechend 
ansprechende Ausgabe zu erzeugen.

> hä? ich hab gar nix. Das is ja das Problem.

Das sehe ich allerdings mitlerweile genauso.
Das du ein Problem hast, mein ich.

> bislang bin ich nur soweit
> dass ich den modus von hand auf automatik umstellen kann und das
> programm bei verschiedenen tastendrücken etwas tut. zb beendet, die
> ringe hochzählt usw.

Auf deutsch: Du hast noch gar nichts.
Zumindest nichts wesentliches. :-)

> Mir fehlt lediglich der übergang wie ich es mit der eigentlichen
> funktion die das programm ausüben soll verschachtele.

Das sehe ich eigentlich nicht so. 'ledglich' ist in diesem Zusammenhang 
die Untertreibung des Jahres. Denn diese Anbindung ist trivial. Der 
Hammer kommt erst, wenn du die Züge an sich generieren sollst (und dabei 
nicht auf Code aus dem Web zurückgreifen willst)

Aber ich will dich nicht aufhalten. Mach mal.


PS: MaWin hat Recht. Mit einem 2D Array für die Türme wirds 
Code-technisch einfacher, wenn auch gedanklich für dich mglw. etwas 
schwieriger.

von Matthias Knab (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> PS: MaWin hat Recht. Mit einem 2D Array für die Türme wirds
> Code-technisch einfacher, wenn auch gedanklich für dich mglw. etwas
> schwieriger.

das heißt?
ich soll Turm 1 in [0][0] speichern, turm 2 in [1][0] unt turm 3 in 
[2][0]?

von Matthias Knab (Gast)


Lesenswert?

Was mir eufgefallen ist wir haben irgendwie aneinander vorbei geredet. 
Und zwar wollte ich in erster linie eigentlich wissen warum er mir wenn 
ich die aufgezaehlte zahl in ein array speichere und probeweise ausgebe 
er mir beim aufzaehlen von 1-13 speichert und beim abzaehlen von -1-11. 
Dass waere eigentlich vorerst mein einziges problem. Kann mir dass 
jemand kurz sagen?

von Karl H. (kbuchegg)


Lesenswert?

gehs doch einfach durch

Hier ist der Code
1
if ( Konfig->iProgrammbeenden == '+')    //ab hier werden die Ringe
2
aufgezählt
3
    {
4
      (Konfig->iAnzahlRinge)++;
5
      Konfig->iRingeTurmA[Konfig->iAnzahlRinge] = Konfig->iAnzahlRinge;
6
      _gotoxy(10,16 - Konfig->iAnzahlRinge);
7
      printf("%d", Konfig->iRingeTurmA[Konfig->iAnzahlRinge]);
8
9
        if (Konfig->iAnzahlRinge > Max)
10
        {
11
          Konfig->iAnzahlRinge = 0;
12
        }
13
    }

Konfig->iAnzahlRinge sei 11
Was passiert?

   (Konfig->iAnzahlRinge)++;

es wird erhöht, also 12

   Konfig->iRingeTurmA[Konfig->iAnzahlRinge] = Konfig->iAnzahlRinge;

zugewiesen (wozu das auch immer gut sein soll)

     _gotoxy(10,16 - Konfig->iAnzahlRinge);
      printf("%d", Konfig->iRingeTurmA[Konfig->iAnzahlRinge]);

ausgegeben -> daher Ausgabe von 12

       if (Konfig->iAnzahlRinge > Max)

Max ist 12, Konfig->iAnzahlRinge (auch 12) ist nicht größer als Max, 
daher passiert nichts weiter.

Gut. Und jetzt erhöhst du nocheinmal
Wieder beginnt die Sequenz

  (Konfig->iAnzahlRinge)++;

erhöhen, also 13

   Konfig->iRingeTurmA[Konfig->iAnzahlRinge] = Konfig->iAnzahlRinge;

zuweisen

     _gotoxy(10,16 - Konfig->iAnzahlRinge);
      printf("%d", Konfig->iRingeTurmA[Konfig->iAnzahlRinge]);

Ausgeben. Also steht jetzt 13 dort

       if (Konfig->iAnzahlRinge > Max)

diesmal ist Konfig->iAnzahlRinge größer als Max, daher
         Konfig->iAnzahlRinge = 0;

auf 0 setzen.


Aber: Die 13 wurden schon ausgegeben, und aufs Array hast du auch schon 
an der falschen Stelle zugegriffen. Ein Arrayelement 
Konfig->iRingeTurmA[12] existiert nicht.

von Matthias (Gast)


Lesenswert?

Dacht ichs mir doch dass ein gleichheitszeichen rein muss. Habs gestrern 
bereits mal probiert und dann kam gar nix mehr. Gut vielleicht war noch 
ein anderer fehler drinn so dass es mir nicht aufgefallen ist. Danke 
schon mal. Muss nachher wenn vorlesung vorbei ist nochmal schauen.

von Karl H. (kbuchegg)


Lesenswert?

Matthias schrieb:
> Dacht ichs mir doch dass ein gleichheitszeichen rein muss.

Keine gute Idee.
D.h. Schon. Aber es behebt das Problem noch nicht wirklich.

von Matthias Knab (Gast)


Lesenswert?

habs auch beim heimfahren überlegt. muss mir das nochmal durch den kopf 
gehen lassen.

von Matthias Knab (Gast)


Lesenswert?

kurze frage wie bekomme ich es hin dass zb:

void Towers (int iy, int ix, struct Konfiguration Ringe)

sich selbst wieder aufruft?

Hab mir das ganze mal mit der Uhrzeigersinn lösung angeschaut und will 
dass nun irgendwie so lösen. nur muss ich da halt rekursiv arbeiten. 
irgendwie.

von Klaus W. (mfgkw)


Lesenswert?

Rekursion sieht im einfachsten Fall so aus:
1
f()
2
{
3
   f();
4
}

von Matthias Knab (Gast)


Lesenswert?

jop dass weiß ich nur wie füge ich eine array nochmals ein? so wie in 
meinem fall halt.

von Schorsch (Gast)


Lesenswert?

1
void Towers (int iy, int ix, struct Konfiguration Ringe) {
2
  if (irgendwas)
3
    Towers(iy+1, ix-1, Ringe);
4
}
1
funktion bewege (Zahl i, Stab a, Stab b, Stab c) {
2
    falls (i > 0) {
3
       bewege(i-1, a, c, b);
4
       verschiebe oberste Scheibe von a nach c;
5
       bewege(i-1, b, a, c);
6
    }
7
}


Ach ja, liess dir bei Gelegenheit mal irgend einen Coding-Style-Guide 
durch.

von Matthias Knab (Gast)


Lesenswert?

coding style guide hab ich hier wie gesagt dass ist ein testprogramm wo 
ich alles einfach so reinpacke.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Matthias Knab schrieb:
> coding style guide hab ich hier wie gesagt dass ist ein testprogramm wo
> ich alles einfach so reinpacke.

Sowas gilt nicht. Und sollte auch nicht so gehandhabt werden, so ein 
coding style hilft auch Fehler zu vermeiden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.