chess ansatz

Nico1999

Aktives Mitglied
hallo ich möchte ein schachspiel programmieren, und ich habe jetzt schon alle Figuren außer dem könig programmiert und es funktiert alles. Allerdings bin ich beim König auf Schwierigkeiten gestoßen und bevor ich jetzt versuche wieder einen schlechten ansatz zu programmieren wollte ich euch mal fragen wie ihr das so machen würdet. Hiermal die methoden die schon zur verfügung stehen
Java:
public class Schachbrett{
    private int [][]schachbrett=new int [8][8];// alle Variablen in den methoden sind int außer es steht was anderes da
    private int [][][]spielverlauf=new int[300][8][8];
//getter setter konstruktur führe ich mal nicht auf sind aber vorhanden
    public void schachbrettausgeben();//drucke schachbrett in konsole
    public int [][] spielbeginn();//setze die anfangsaufstellung
    public int [][] figurbewegen(a[][], jetztx, jetzty, dannx, danny)// bewege figur
    public int [][][] spielverlaufaktualisieren(moveanzahl);// setze schachbrett auf moveanzahl in spielverlauf
    public void spielverlaufausgeben(moveanzahl);// gebe spielbrett in move x aus
}public class Figur{
    private int gaphik;
    private int x;
    private int y;
    private int movezähler=0;
    //Konstanten setzung (bsp static int TURMW=5)für alle Figuren (schwarz ist negativ weiß positiv)
    public static boolean istfreiturm(a[][], jetztx,jetzty,dannx,danny,graphik)// schaue ob die felder frei sind für turm
    public static boolean istfreiläufer(a[][],jetztx,jetzty,dannx,danny,graphik)// selbe für läufer
    public static boolean bauermovement(a[][], jetztx,jetzty,dannx,danny,graphik,movezähler,b[][][], moveanzahl)//prüfe auf anpasarschlagen 2 vormoven
    public boolean legalmove(a[][], jetztx,jetzty,dannx,danny,b[][][], moveanzahl)// nutze die drei obigen methoden um zurück zugeben ob der move erlaubt ist oder nicht
}public class Spiel{
    //erstelle figur array mit allen Figuren
    // methoden um nutzerinput für jetztx,jetzty,dannx,danny zu bekommen
    Schachbrett schachbrett1.new Schachbrett();
    schachhbrett1.spielbeginn;
    int moveanzahl=0;
    
    while(spielnichtzuende){
        moveanzahl++;
        schachbrett1.spielverlaufaktualisieren(moveanzahl);
        schachbrett1.schachbrettausgeben();
        //methoden für nutzerinput
        for(Figur a:figurliste){
            if(a.legalmove(schachbrett1.getschachbrett(),jetztx,jetzty,dannx,danny,schachbrett1.getSpielverlauf(),moveanzahl){
                
            }
        }
    }
}
legalmove enthält alle figuren außer dem König bis jetzt allerdings weiß ich nicht wie ich schachüberprüfen soll oder wenn z.b. die dame auf eine rochaden feld zeigt dann kann man ja nicht mehr rochieren. meine frage ist jetzt wie würdet ihr implementieren das der könig auf bestimmte felder nicht gehen kann weil er sonst dort geschmießen werden könnte mein ansatz bis jetzt ist
ich lass die figurliste durchlaufen für weiß nur die - wert und umgekehrt um dann irgentwie zu überprüfen ob eine figur auf dieses Feld könnte (allerdings ist das glaube ich mit legalmove nicht möglich den dann braucht man ja auch den jetztx, jetzty, wo geguckt wird ob das auch die klassenvariable ist)
ich freue mich auf feedback und wenn ihr sonstige verbesserungsvorschläge habt schreibt sie bitte rein, da ich noch recht neu im Programmiern bin gibts bestimmt auch einfachere Lösungen
 

Staarfightaar

Bekanntes Mitglied
viele parameter sind immer anzeichen für schlechtes design, genauso wie static in situationen wo man kein static braucht

ansatz würde ich dir für dein design mal geben

Java:
public abstract class Figur implements Transformable{
    protected Graphic figureGrahpics;
    protected Transform transform; // attribut das alles über die position weis
    public abstract Move(Move move);
    public abstract List<Move> getPossibleMoves();
    public Transform GetTransform();
}
public Interface Transformable{
    void Move(...);
    Transform GetTransform();
}
public class Transform{
    protected int x;
    protected int y;
    ....
}
wenn du dann für jede Figur eine klasse hast ( vllt gehts auch über lambda ausdruck ; DASS du die Move methode dann übergibst, aber weis nicht ob du das schon mal gemacht hattest )

solltest du dein schachbrett noch ädnern dass dieses die figuren verschieben kann ( in der grafik )
deinem schachbrett is ansich egal welche figur es ist.. es braucht als abhängigkeit irgendwas was Transformable impementiert
somit kannst dein schachbrett und die figuren "halbwegs unabhängig" von einander machen, dh auf deutsch wenn du was an deiner Turm klasse änderst kannst du dein programm immer noch starten ohne dass es deinen König zerschießt usw

die spiel logik sollte separat behandelt werden... dafür würde die logik eig nur die abstrakte figur klasse brauchen, da kann man vllt auch noch ein interface raus ziehen weil die Logik ja das Transform gar nicht braucht
usw...
 

Nico1999

Aktives Mitglied
was ist ein Interface
wenn ich das richtig verstehe tust du dann in transfrom quasi die eingabe speichern und diese wird dann in die jeweiligen funktionen gegeben
was bedeutet abstract
bei public abstract Move(Move move) heißt das dass ich ne klasse erstellen muss die Move heißt ?
und wo würde ich jetzt die logik speichern auch in move oder gesondert in nem boolean?
wie würde dann ein konstruktor aussehen bei transfrom bzw wie wird das objekt erstellt und ihm die daten zugewiesen
 
Zuletzt bearbeitet:

Staarfightaar

Bekanntes Mitglied
ein Interface ist ein verpsrechen nach außen...

dh wenn eine Klasse ein interface implementiert
wie zb
Java:
public interface Transformation{
    int getX();
    int getY();
}
und du hast eine transform klasse
Java:
public class Transform implements Transformation{
  
}
dann wird hier ein fehler aufkommen weil die Transform nicht die versprechen erfüllt

das sind zu einem
1. Die imlementation einer methode mit der Signatur "int getX()"
2. Die implementation einer methode mit der Signatur "int getY()"

wenn du das hast , hast du eine Klasse die die verprechen erfüllt
jetzt kannst du zb in einer anderen Klasse so ne methode schreibne
Java:
public class Schachbrett{
    public void move(Transformation transform){
        System.out.println(transform.getY());
    }
}
dh die move methode erwartet irgend ein objekt von irgendeiner klasse die die verpreschen des Transformation interfaces erfüllt

dh du könntest das tun
Java:
var schach = new SchachBrett();
schach.move(new Transform());
warum darf man hier ein Objekt von Transform übergeben ? es wird ja ein Transformation erwartet

ja das stimmt, aber Transform erfüllt die versprechen von Transformation deswegen darfst du es da übergeben, hierbei ist aber zu beachten dass IN der methode auch wenn ein Transform übergeben wird, das übergebene objekt als transformation behandelt wird

zum rest muss dir jemand anderes was sagen, muss weg gehen ins wirtshaus :D

PS dsa mit move(Move move) war nur eine idee kein zwang, würde aber implizieren ne neue klasse zu bauen... neue klassen wirst du 100% brauchen wenn du es besser machen möchtest
 

KonradN

Super-Moderator
Mitarbeiter
Also erst einmal die konkrete Frage bezüglich püfen, ob ein Feld oder eine Figur bedroht ist:
Wenn Du weisst, wie eine Figur ziehen kann, dann kannst Du ja prüfen, ob eine gegnerische Figur derzeit z.B. deinen König erreichen kann. (Dann würde er im Schach stehen). Wobei die Frage ungenau gestellt ist - die Frage ist ja, ob eine gegnerische Figur eine Figur auf dem Feld schlagen kann. (Beim Bauern ist gehen und schlagen ja unterschiedlich).

Aber die Struktur ist noch extrem schlecht. Wieso ist alles bei Dir ein int? Und Eine Klasse Spielfeld hat ein Spielfeld als Instanzvariable? Die Instanz der Klasse soll doch ein Spielfeld sein - was ist das dann?

Aus meiner Sicht müsstest Du die Objekte, mit denen Du hantieren willst, besser durchdenken. Was für Daten willst Du wie speichern?

Du kannst gerne Spielfelder haben. Die Instanzvariable wäre dann statt schachbrett etwas wie felder. Aber was speicherst Du da? Das sind doch keine int Werte - das sind dann doch eher Figuren, oder von mir aus eine neue Klasse Feld.

Also ehe ich über Interfaces nachdenken würde, würde ich die Struktur mir genauer überlegen. Ob dann ein Interfaces benötigt wird oder nicht ist da dann erst einmal zweitrangig. Wenn die figuren in dem Schachbrett gespeichert sind, dann hat das Schachbrett eine Methode um Figuren zu verschieben. Und da nur Figuren verschoben werden und wirklich nie etwas anderes, ist ein Interface hier unnötig: Du wirst es nie brauchen!

Schau, was Du alles hast und was zusammen gehört ..... x und y gehört zusammen - und das ist eine Koordinate.
Spielverlauf gehört nicht zum Spielbrett. Spielbrett ist ein Spielbrett und das hat Figuren. Also das ist irgendetwas, das zu einem Spiel gehört. Und was dies speichert muss man erst einmal sein - aber es ist eine eigene Klasse und die speichert irgendwas intern. Und wenn es Spielbretter sind dann wäre es eine List<Spielbrett> oder so.

Was hat die Figur miut Grafik zu tun? Hier würde ich deutlich unterscheiden zwischen Model und Darstellung!

Dein Code ist auch ansonsten schwer verständlich - woger kommt plötzlich eine Figurliste? Du scheinst Daten mehrfach gespeichert zu haben - zum einen in dem 2d (3d?) Array in Form von int, zudem in Figur als x/y Koordinate und dann noch in irgendwelchen Listen? Unnötige Redundanzen vermeiden!
 

KonradN

Super-Moderator
Mitarbeiter
Und Du implementierst hier ja auch etwas, das es real gibt. Das kann man sich also in Ruhe ansehen. Und dann schlicht abstrahieren, was man so sieht.

Spielverlauf: Wenn ich mir einen Spielverlauf ansehe, dann sehe ich da einfach etwas a.la.:
1. e2-e4 e7-e5
2. Sf1-f3 Sb8-c6
...

Spielbrett hat einfach die Felder mit 0-1 Figuren pro Feld.
Figuren haben eine Farbe und Funktion
Figuren haben Regeln zum Gehen und zum Schlagen.
Die Regeln setzen teilweise weitere Angaben voraus:
- Figuren dürfen noch nicht bewegt worden sein (Rochade - König und Turm dürfen nicht bewegt worden sein)
- Bewegungen hängen teilweise vom Bedrohungsstand ab.

Wenn man also erst einmal nur Züge prüfen können möchte, dann reicht es schon aus:
- Regeln haben eine prüfen Methode und die braucht die Figur, aktuelle Position, zielPosition, Schachbrett.
- Zurück kommt ein true bzw. false. das angibt, ob so ein Zug möglich wäre.

Und das Prüfen kann dann
- in mehrere Regeln aufgeteilt werden. Dann vermengt man da nicht den Zug beim König um ein Feld mit der Rochade.
- Regeln können universell sein: Die Dame hat dann einfach die TurmRegel und die LäuferRegel
- Aufbau kann intern aufgeteilt sein in gehen und schlagen:
--> ist auf dem Zielfeld eine eigene Figur, dann ist der Zug nicht erlaubt
--> ist auf dem Zielfeld eine fremde Figur, dann ist es ein Schlagen
--> Sonst wäre es ein Zug.

Das wäre ein schneller Ansatz für eine einfache Strukturierung. Anzeige selbst hat in den bisherigen Klassen nichts zu suchen! Eine Anzeige kannst Du in eigenen GUI Klassen machen. Von mir aus machst Du eine einfache Klasse SchachbrettAnzeiger, die dann das Schachbrett Feld für Feld durchgeht um das dann irgendwie anzuzeigen. Andere Klassen können Eingaben entgegen nehmen um dann einen Wunschzug zu ermitteln. Der kann dann geprüft werden und dann ggf. ausgeführt.
 

Staarfightaar

Bekanntes Mitglied
- Figuren dürfen noch nicht bewegt worden sein (Rochade - König und Turm dürfen nicht bewegt worden sein)
- Bewegungen hängen teilweise vom Bedrohungsstand ab.
das sind features...

erstmal sollte man das implementieren was spaß macht bei einem spiel
und das ist beim schach nunmal schlichtweg das hin und herfahren und könig werfen

und dabei sollte man bei den einfachsten dinge anfangen wie zb bauer der einfach nur gerade ausfahren kann und einen werfen kann

wenn man das einfache problem gleöst hat sind die schweren probleme wie zb pferd bewegung von der Lösung des bauerns abzuleiten
 

KonradN

Super-Moderator
Mitarbeiter
Ich bin mal wieder sprachlos. Soll ich jetzt noch einmal ausführlich erläutern, um was es mir ging - aber das ist doch eigentlich eindeutig:
Und Du implementierst hier ja auch etwas, das es real gibt. Das kann man sich also in Ruhe ansehen. Und dann schlicht abstrahieren, was man so sieht.

Und natürlich gehören dann Features dazu. Was Du bringst sind auch nur Features. Und wenn man etwas skizziert, dann sollte man doch bis zu dem Punkt kommen, zu dem der TE auch gekommen ist und das war nun einmal die Rochade:
legalmove enthält alle figuren außer dem König bis jetzt allerdings weiß ich nicht wie ich schachüberprüfen soll oder wenn z.b. die dame auf eine rochaden feld zeigt dann kann man ja nicht mehr rochieren.

Aber nein - ich denke ich verzichte da auf weitere Ausführungen für Dich. Warum hast Du Dir eigentlich einen neuen Account gemacht Joreyk?

@Nico1999 Das mit dem Verzicht auf weitere Ausführungen gilt natürlich nicht für Dich. Bei Fragen bitte schön weiter fragen. Wenn die Erläuterungen einer solchen Struktur noch nicht ausreichend waren oder Du das nicht umsetzen kannst, dann helfe ich da gerne weiter.
 

M.L.

Top Contributor
Bei einem Königszug sind rein mengenmässig mehr formelle Kriterien zu erfüllen als bei den anderen Figuren:
-steht der König auf dem Start- oder Zielfeld im Schach ? Wenn ja, lässt sich dieses mit legalen Zügen ändern ? (Prüfung auf Matt oder Patt)
-Rochade: haben König und betreffender Turm schon einmal gezogen ? Wenn nein, stehen irgendwelche Figuren im Weg und wird absolut keins der zwei (kurze Rochade) bis drei (lange Rochade) Felder zum Königszug von einer gegnerischen Figur kontrolliert ?
 

KonradN

Super-Moderator
Mitarbeiter
Bei einem Königszug sind rein mengenmässig mehr formelle Kriterien zu erfüllen als bei den anderen Figuren:
-steht der König auf dem Start- oder Zielfeld im Schach ?
Das ist aber eine generelle Regel. Die Regel besagt einfach: Nach dem Zug darf der eigene König nicht im Schach stehen.
Dabei ist es egal, ob der König gezogen wurde oder irgend eine andere Figur.

Und um das Ende Kriterium festzulegen:
Das Spiel ist u.a. dann zu Ende, wenn eine Person keinen Zug mehr machen kann.
- Ist der König in der aktuellen Stellung bedroht hat der Spieler, der an der Reihe ist, verloren.
- Ist dies nicht der Fall, dann ist es ein Unentschieden
 

Nico1999

Aktives Mitglied
ich werds erst ma nochma neu machen und dann vllt wieder posten und die hier genannten sachen versuchen zu berürcktsichtigen und dann vllt dannach noma hierrein posten
Was hat die Figur miut Grafik zu tun? Hier würde ich deutlich unterscheiden zwischen Model und Darstellung!

Dein Code ist auch ansonsten schwer verständlich - woger kommt plötzlich eine Figurliste? Du scheinst Daten mehrfach gespeichert zu haben - zum einen in dem 2d (3d?) Array in Form von int, zudem in Figur als x/y Koordinate und dann noch in irgendwelchen Listen? Unnötige Redundanzen vermeiden!
ich habe jetzt mal ganz unkompliziert (finde ich) graphik bedeutet wie ich meine sachen in der konsole anzeigen und da habe ich irgentwelche positiven zahlen für weiß und irgentwelche negativen zahlenfür schwarz genommen welche figur welche zahl bekommt ist ja erstma nicht so wichtig figurliste da hab ich halt alle figuren objekte gespeichert die ich erstellt habe und ja ich habe einmal die variable schachbrett und die spielverlauf was der 2d und 3d variable entspricht warum ich jetzt spielverlauf in der methode benötige ist, weil beim anpasar schlagen ich wissen muss ob im vorherigen move der bauer zwei gepusht wurde sonst ist das nämlich nicht möglich könnte natürlich auch gleich immer den 3 d array nehmen hatte aber keine lust das noma umzuschreiben jetzt wo ichs eh noma von vorne anfange nehm ich nur noch den 3d
Und Du implementierst hier ja auch etwas, das es real gibt. Das kann man sich also in Ruhe ansehen. Und dann schlicht abstrahieren, was man so sieht.

Spielverlauf: Wenn ich mir einen Spielverlauf ansehe, dann sehe ich da einfach etwas a.la.:
1. e2-e4 e7-e5
2. Sf1-f3 Sb8-c6
...

Spielbrett hat einfach die Felder mit 0-1 Figuren pro Feld.
Figuren haben eine Farbe und Funktion
Figuren haben Regeln zum Gehen und zum Schlagen.
Die Regeln setzen teilweise weitere Angaben voraus:
- Figuren dürfen noch nicht bewegt worden sein (Rochade - König und Turm dürfen nicht bewegt worden sein)
- Bewegungen hängen teilweise vom Bedrohungsstand ab.

Wenn man also erst einmal nur Züge prüfen können möchte, dann reicht es schon aus:
- Regeln haben eine prüfen Methode und die braucht die Figur, aktuelle Position, zielPosition, Schachbrett.
- Zurück kommt ein true bzw. false. das angibt, ob so ein Zug möglich wäre.

Und das Prüfen kann dann
- in mehrere Regeln aufgeteilt werden. Dann vermengt man da nicht den Zug beim König um ein Feld mit der Rochade.
- Regeln können universell sein: Die Dame hat dann einfach die TurmRegel und die LäuferRegel
- Aufbau kann intern aufgeteilt sein in gehen und schlagen:
--> ist auf dem Zielfeld eine eigene Figur, dann ist der Zug nicht erlaubt
--> ist auf dem Zielfeld eine fremde Figur, dann ist es ein Schlagen
--> Sonst wäre es ein Zug.

Das wäre ein schneller Ansatz für eine einfache Strukturierung. Anzeige selbst hat in den bisherigen Klassen nichts zu suchen! Eine Anzeige kannst Du in eigenen GUI Klassen machen. Von mir aus machst Du eine einfache Klasse SchachbrettAnzeiger, die dann das Schachbrett Feld für Feld durchgeht um das dann irgendwie anzuzeigen. Andere Klassen können Eingaben entgegen nehmen um dann einen Wunschzug zu ermitteln. Der kann dann geprüft werden und dann ggf. ausgeführt.

auf das spielbrett mit 0 und 1zu machen wäre ich nicht gekommen
Farbe und Funktion hängen bei mir ausschließlich von graphik ab (- oder + für farbe) zahl für bestimmte figur
ich habe jetzt versucht alle regeln in einer methode (die andere methoden aufruft) zu sammeln sollte ich das so machen oder eher für jede figur neue klasse und da dann einzeln die methode machen? und das sollte dann die prüfe methode sein also die regelsammlung
und bei dem prüfen habe ich das was du hast und noch die methode istfrei die schaut dass man mit den turm keine eigene und keine gegnerische figur überspringen kann

ich möchte lieber selber versuchen dsa hinzubekommen den bis jetzt habe ich denke ich schon recht viel gelernt

ich werde das ganze jetzt nochmal überarbeiten und dann nochmal in einem neuen thema posten oder soll ich es hier nochmal posten ?
 

KonradN

Super-Moderator
Mitarbeiter
auf das spielbrett mit 0 und 1zu machen wäre ich nicht gekommen
Das Feld enthält nicht 0 oder 1 sondern diese Anzahl an Figuren. Wenn Du eine Klasse Figur hast, dann kann Spielfeld z.B. ein 2D Array von Figur sein. Dann kann auf einem Feld keine Figur sein (Inhalt = null) oder es ist eine Figur drauf (Inhalt ist dann die Referenz zu der Figur).
ich habe jetzt versucht alle regeln in einer methode (die andere methoden aufruft) zu sammeln sollte ich das so machen oder eher für jede figur neue klasse und da dann einzeln die methode machen? und das sollte dann die prüfe methode sein also die regelsammlung
und bei dem prüfen habe ich das was du hast und noch die methode istfrei die schaut dass man mit den turm keine eigene und keine gegnerische figur überspringen kann
Also es gibt generell kein wirkliches richtig / falsch bei sowas. Wichtig ist, dass man versucht, es etwas zu strukturieren.

Dabei ist es nebensächlich, ob Du nun für jede einzelne Art von Figur eine eigene Klasse machst (Also abstrakte Klasse Figur und dann Klassen Bauer, Turm, Springer, ... ) oder ob Du da auf der Ebene des Verhaltens (das, was ich wohl Regeln genannt habe - ich habe das Grobkonzept jetzt nicht nochmal gelesen) aufteilst. Mir wäre nur wichtig, dass es eine saubere Unterteilung gibt und da dann auch mit entsprechenden Instanzen der Klassen gearbeitet wird. (Prinzipiell würde es auch anders gehen, aber dann wäre die Lösung eben nicht objektorientiert sondern halt (fast) nur Prozedural aufgeteilt. Das ist deutlich schwerer zu überschauen und du verzichtest auf die ganzen Vorteil objektorientierter Entwicklung.)

Wenn Du eine neue Aufteilung hast, dann kannst Du die Klassen ja vorstellen. Also ohne konkrete Implementation von Methoden sondern nur die Klassen selbst, die Methoden, die diese nach außen anbieten und was für Daten sie intern halten / benötigen (Also sozusagen das Datenmodell).
 

Ähnliche Java Themen

Neue Themen


Oben