C++ Rössel schachbrett problem
-
ja also ich bin noch totaler c++ neuling (in der schule angefangen mit c++)
und wir sind jetzt an einem gröberen problem angelangt-> das rössel program
für alle die s noch nicht kennen.
man soll ein pferd auf ein schachbrett legen und es soll dann alle felder einmal besuchen (und nicht mehr).soweit so gut hier ist mein programm, das nicht funktioniert, habs mir schon 2 stunden angeschaut und nix gefunden
hab mir gedacht vielleicht können ein paar profis von hier mit bisschen weiter helfen also hir mal mein programm :
aja c kanns complieren aber der scheint in ner endlos schleife zu hängen.
und das ganze sollen wir nur mit den hilfe von arrays (feldern),if, case, anweisungen machen, da wir ja sonst nix gelernt haben ^^#include<iostream.h> #include<conio.h> #include<fstream.h> #include<Math.h> #include<stdlib.h> void main(){ int Hilfsfeld [3][65]; int Schachbrett[8][8]; int Zugtyp=1,a=0,b=0,Reihe1=4,Reihe2=4,Flag=0; Schachbrett[Reihe1][Reihe2]=1; for (int i=0;i<8;i++){ // sämtliche Felder mit 0 initialisieren. for (int j=0;j<8;j++){ Schachbrett[i][j]=0; } } // for (int i=2;i<65;i++){ Zugtyp=1; Flag=0; switch(Zugtyp){ case 1: a=1;b=2;break; // Sprungmöglichkeiten eines pferdes (max 8 möglichkeiten) case 2: a=1;b=-2;break; case 3: a=-1;b=2;break; // dies ist der normal ablauf, falls keine sackgasse etc erfolgt case 4: a=-1;b=-2;break; case 5: b=1;a=2;break; case 6: b=-1;a=2;break; case 7: b=1;a=-2;break; case 8: b=-1;a=-2;break; // } while ((Schachbrett[Reihe1+a][Reihe2+b]!=0)||Reihe1+a>7||Reihe1+a<0||Reihe2+b>7||Reihe2+b<0){ // falls das pferd über den rand hinausspringen würde bzw. ein feld besuchen sollte das bereits schon mal besucht war Zugtyp++; while (Zugtyp>8){ Reihe1=Hilfsfeld[0][i-1]; Reihe2=Hilfsfeld[1][i-1]; Schachbrett[Reihe1][Reihe2]=0; Reihe1=Hilfsfeld[0][i-1]=0; Reihe2=Hilfsfeld[1][i-1]=0; Reihe1=Hilfsfeld[0][i-2]; Reihe2=Hilfsfeld[1][i-2]; Zugtyp=Hilfsfeld[2][i-2]; i--; Flag=1; Zugtyp++; } switch(Zugtyp){ // auswahl eines neuen sprungtypes case 1: a=1;b=2;break; case 2: a=1;b=-2;break; case 3: a=-1;b=2;break; case 4: a=-1;b=-2;break; case 5: b=1;a=2;break; case 6: b=-1;a=2;break; case 7: b=1;a=-2;break; case 8: b=-1;a=-2;break; // } } if (Flag ==1) Schachbrett[Reihe1+a][Reihe2+b]=i; if (Flag ==0) Schachbrett[Reihe1+a][Reihe2+b]=i; Hilfsfeld[0][i]=Reihe1+a; // buchführung : einschreibung der x,y koordinaten und sprungtypes Hilfsfeld[1][i]=Reihe2+b; Hilfsfeld[2][i]=Zugtyp; // } for (int i=1;i<65;i++){ cout<<Hilfsfeld[0][i]<<" "<<Hilfsfeld[1][i]<<" "<<Hilfsfeld[2][i]<<" "<<endl; } getch(); }
-
while (Zugtyp>8){ Reihe1=Hilfsfeld[0][i-1]; Reihe2=Hilfsfeld[1][i-1]; Schachbrett[Reihe1][Reihe2]=0; Reihe1=Hilfsfeld[0][i-1]=0; Reihe2=Hilfsfeld[1][i-1]=0; Reihe1=Hilfsfeld[0][i-2]; Reihe2=Hilfsfeld[1][i-2]; Zugtyp=Hilfsfeld[2][i-2]; i--; Flag=1; Zugtyp++; }
Falls Zugtyp wirklich grösser als 8 ist, kommst du nicht mehr aus der Schleife raus.
Aber ich würde dir anraten das ganze Rekursiv zu programmieren, das ist wahrscheinlich einfacher.Edit: void main(), hattet ihr das so gelernt? Das sollte heissen int main(), ausserdem solltest du besser schreiben #include <iostream> anstatt <iostream.h>
Wenn du einfach alle möglichkeiten ausprobierst, kann es übrigens relativ lange dauern, bis die lösung auf einem 8x8 Feld errechnet wird, eine Verbesserungsmöglichkeit wäre, immer zuerst zu versuchen, in die Ecken zu springen. Dann geht es schneller.
-
wieso?
falls zugtyp grösser als 8 ist dann übernimmt zugtyp den wert eine runde davor (den ich ja in der buchführung geschrieben habe) und wird um eins erhöht, falls diese wieder grösser als acht ist übernimmt sie wieder den wert von zugtyp noch ne runde davor.bsp: zug 8 buchführung alles aufgezeichnet
zug 9 sackgasse, keine möglichkeiten ... zugtyp errreicht wert grösser als 8 und bekommt sämtliche werte von zug acht zurückgesetzt und probiert eine andere sprungmöcglichkeit aus .
ja wir machen es mit void main damit wir zum schluss kein return 0 schreiben müssen ^^.
-
Die Sackgasse ist wie lustig es bereits erwähnt hat
hier:while (Zugtyp>8){ Reihe1=Hilfsfeld[0][i-1]; Reihe2=Hilfsfeld[1][i-1]; Schachbrett[Reihe1][Reihe2]=0; Reihe1=Hilfsfeld[0][i-1]=0; Reihe2=Hilfsfeld[1][i-1]=0; Reihe1=Hilfsfeld[0][i-2]; Reihe2=Hilfsfeld[1][i-2]; Zugtyp=Hilfsfeld[2][i-2]; i--; Flag=1; Zugtyp++; }
die schleife wird ausgeführt wenn zugtyp > 8 ist und das geht so lange weiter bis Zugtyp nicht mehr 8 ist. ABER Zugtype kann nie mehr unter 8 kommen weil du immer 1 dazu zählst....
-
sorry, mein Fehler, habe das Zugtyp=Hilfsfeld[2][i-2]; übersehen.
-
Ich denke der fehler liegt trotzdem in der while schleife..
edit: die position des springers wird nicht aktualisiert. Ich denke das ist der fehler :>while ((Schachbrett[Reihe1+a][Reihe2+b]!=0)||Reihe1+a>7||Reihe1+a<0||Reihe2+b>7||Reihe2+b<0)
müsste imho heißen:
while (Reihe1+a>7||Reihe1+a<0||Reihe2+b>7||Reihe2+b<0 || (Schachbrett[Reihe1+a][Reihe2+b]!=0))
dann
while (Zugtyp>8){ //kein zug möglich daher anderen zug beim vorgängerzug wählen (wenn möglich) Reihe1=Hilfsfeld[0][i-1]; //reihe1, reihe2 beschreibt denk ich mal die position des springers, richtig? oO. Reihe2=Hilfsfeld[1][i-1]; //-->position des springers vom letzten zug wird wieder genommen -->wofür? sollte eh die werte haben (wenn reihe1 und reihe 2 am ende der forschleife mal aktualisiert werden würden) Schachbrett[Reihe1][Reihe2]=0; //markierung auf dem schachbrett wird wieder entfernt -->logisch Reihe1=Hilfsfeld[0][i-1]=0; //überflüssig Reihe2=Hilfsfeld[1][i-1]=0; //überflüssig Reihe1=Hilfsfeld[0][i-2]; //springerposition vom vorletzten zug wird genommen (aktueller zug konnte nicht gefunden werden -> letzter zug ist falsch --> letzten zug löschen und vorletzte springerpositionnehmen) -> logisch Reihe2=Hilfsfeld[1][i-2]; // " Zugtyp=Hilfsfeld[2][i-2]; //letzten zugtyp merken und gleich eins weiter setzen um anderen zug zu ermöglichen -->logisch i--; Flag=1; //i eins zurücksetzen, da neuer letzter zug gefunden werden muss --> logisch .. Flag --> ?? Zugtyp++; }
was soll eigentlich "flag" besagen? und hast du schonmal probiert, einfach mal nur 30 züge oder so berechnen zu lassen?
irgendwie fehlt auch ein "Reihe1+=a; Reihe2+=b;" nach jedem forschleifen durchlauf.. Ich glaub das ist der eigentliche fehler
-
lustig schrieb:
sorry, mein Fehler, habe das Zugtyp=Hilfsfeld[2][i-2]; übersehen.
Lol ich auch. Sorry
-
-
Hallo Leute,
zu dem Thema fällt mir ein, ich habe da letzten von einem Coder contest gelesen, wo genau dieses Problem gelöst werden sollte . Zwar haben die AFAIR in ASM programmiert(ging um schnellste Laufzeit und kleinstens Binary) , aber das Testprogramm, was die benutzt haben war in CPP soweit ich weiss.
Vielleicht ist es ja interessant für euch :
http://www.hugi.scene.org/compo/
also interessant finde ich das schon, wie kompakt man sowas in ASM lösen kann
:
The Knight's Tour ;Hugi Compo 23 (www.hugi.de/compo) ;Coded by G3 (tgm80@mail.ru) ;fasm.exe entry.asm entry.com org 100h start: pop cx ;cx=0 push '$' std scasw ;di=di-2 L10: pusha scasw inc cx mov bl,8 L20: dec bx jz L30 add al,[bx+si+dxy-100h-1] test al,88h jnz L20 pusha cld aam 10h ;ah=al / 10h, al=al mod 10h stosw repnz scasw std L30: popa jz L20 cmp cl,0FFh-64 ;same as cmp cl,63 but zf=0 jns L10 mov dx,di xchg ax,bp ;ah=9 dxy db -3*16-3,+2*16+1 ;int 21h db -2*16+1,+4*16 ;loope $+40h (useless) db -3*16-3,+2*16 ;int 20h db -1*16+2
gruss,
need_input
-
ich wollte nur noch etwas zu der geschwindigkeit sagen. Mach doch mal den Versuch, dein Programm über nacht laufen zu lassen, oder ändere es auf ein 7x7 Feld. Ich habe auch mal so ein Programm geschrieben (allerdings rekursiv). Jetzt habe ich mir den Quelltext nochmals angesehen und da steht:
//dieser Code hat nur bis 7x7 eine akzeptable geschwindigkeit (habe den Versuch mit dieser Funktion ein 8x8 Feld zu berechnen nach 30min abgebrochen).
Vielleicht waren da ja ganz grobe schnitzer drin, aber bis 7x7 hat der Code gut funktioniert. Ich habe es dann so gelöst, dass ich immer als erstes Versuchte in eine Ecke zu springen, falls möglich. So ging es dann ziemlich schnell.