# Netzwerkschach in JAVA



## Ohne? (28. Mai 2009)

Hallo liebe Community,

Als Projektarbeit in der Schule habe ich mich für ein Netzwerkschach entschieden.

Nun habe ich eine Frage zu einer Methode der Fachklasse Springer:

diese Methode gibt mir als boolean zurück, ob der Zug eines Springers möglich ist.
Dabei werden die Koordinaten des Startfelds und des Zielfelds angegeben.

hier der Code meiner Methode:

```
public boolean moeglichZug(int pyVonFeld, int pxVonFeld, int pyZuFeld, int pxZuFeld)
	{
		boolean a=false;
		
		int i1=pxVonFeld;
		int i2=pxZuFeld;
		int y1=pyVonFeld;
		int y2=pyZuFeld;
		
		if(i2-i1==2 && y2-y1==-1)
		{
			return a=true;	
		}
		if(i2-i1==1 && y2-y1==-2)
		{
			return a=true;	
		}
		if(i2-i1==-1 && y2-y1==-2)
		{
			return a=true;	
		}
		if(i2-i1==-2 && y2-y1==-1)
		{
			return a=true;	
		}
		if(i2-i1==-2 && y2-y1==1)
		{
			return a=true;	
		}
		if(i2-i1==-1 && y2-y1==2)
		{
			return a=true;	
		}
		if(i2-i1==1 && y2-y1==2)
		{
			return a=true;	
		}
		if(i2-i1==2 && y2-y1==1)
		{
			return a=true;	
		}
		return a;	
	}
```
Nun ist es umständlich, immer 4 Werte eingeben zu müssen, daher möchte ich nun nur das Startfeld angeben und alle möglichen Feldern sollen als ein array zurückgegeben werden (immer y1,x1,y2,x2...).

hier die neue Methode die ich überlegt habe:

```
public int[] moeglichZug_Array(int pyVonFeld, int pxVonFeld)
	{	
		int y1= pyVonFeld;
		int x1= pxVonFeld;
		
		int[] array = new int[16]; //Da es max 2*8 Koordinaten gibt
		

			array[0]=y1-2;
			array[0]=x1-1;

		

		return array;
	}
```
Nur habe ich das kleine Problem, dass die Speicheradresse des arrays zurückgeliefert wird, wenn ich die Methode aufrufe, anstatt die Inhalte.

Hat jemand von euch eine Idee?

Ich währe euch echt dankbar
Ohne?


----------



## Marco13 (28. Mai 2009)

*Kristallkugel auspackt*

Ah, du rufst auf
int array[] = machDenArray();
System.out.println("Array: "+array);

Und dort erscheint nur [@34beef123

Du mußt 
System.out.println("Array: "+Arrays.toString(array));
machen.


Wenn es aber darum geht, den Array über's Netz zu übertragen, musst du beschreiben, wie du das bisher machst.


----------



## Schandro (28. Mai 2009)

Du brauchst nicht nach jedem if(..) "return a=true/false" schreiben und am Schluss nochmal return a.

Sobald return aufgerufen wird, ist die Methode zuende.

(Ausnhame: Ein try{...}finally{..} Block, aber sowas benutzt du ja nicht)

Übrigens würd ich dir insgesamt empfehlen, eine Containerklasse "Field" zu machen, wo man die x- und  y-Koordinate eines Feldes zusammen speichern kann.


----------



## Ohne? (28. Mai 2009)

Marco13 hat gesagt.:


> *Kristallkugel auspackt*
> Du mußt
> System.out.println("Array: "+Arrays.toString(array));
> machen.



Also ich rufe ja die Methode so auf: 		System.out.print(s1.moeglichZug_Array(5,7));
s1 steht für das Objekt vom Typ Springer


so meinst du das bestimmt nicht: System.out.print(s1.moeglichZug_Array(5,5).toString());

Könnt ihr bitte noch mal helfen?

Danke Ohne?


----------



## Schandro (28. Mai 2009)

Die Methode
Arrays.toString
erwartet irgendein Array als Parameter und gibt einen String zurück.

Das heisst in die Klammer von Arrays.toString kommt die Methode die dein Array zurückgibt, und um das ganze kommt die Klammer vom System.out.println


----------



## Ohne? (28. Mai 2009)

Also so dann: System.out.print(Array.toString(s1.moeglichZug_Array(5,5)));

benötigt man dann noch einen bestimmten import?

Gruß


----------



## Marco13 (28. Mai 2009)

Du solltest dir zuerst die Fähigkeiten aneignen, die nötig sind, um herauszufinden, dass man dafür noch 
import java.util.*;
braucht. (Z.B. "java sun Arrays" in eine Suchmaschine eintippen)


----------



## Ohne? (28. Mai 2009)

danke es hat geklappt.
Man kann es lange versuchen, wenn da ein s bei Array(s)
fehlt 

System.out.print(Arrays.toString(s1.moeglichZug_Array(5,5)));

danke für eure Hilfe

Ohne?


----------



## Marco13 (28. Mai 2009)

Vielleicht noch nebenbei: WAS genau du mit dem Array dann vorhast, ist mir nicht ganz klar. Wenn das in einer KI verwendet werden soll, gäbe es evtl. günstigere Alternativen. Wenn es nur für die Überprüfung der Eingabe eines meschlichen Spielers ist, ist das aber OK.


----------



## Ohne? (28. Mai 2009)

Also folgendes habe ich mir mit dem Array gedacht:

Wenn ich z.B. den Springer anklicke, dann sollen alle möglichen Felder rot eingefärbt werden. Ob nun einer meiner Figuren oder der Gegner auf einem möglichen Feld steht wird dabei noch nicht berücksichtigt. 
Das Array soll einfach weiterverarbeitet werden, um letztlich alle möglichen Felder zu erhalten und diese dann einzufärben.


Oder was schlägt ihr mir vor?


----------



## Marco13 (28. Mai 2009)

Janeee, dafür ist das wie gesagt OK. Für eine KI müßte man sich eben sowieso eine "allgemeine" (und effiziente) Datenstruktur für Züge überlegen, d.h. das kann schon deutlich aufwändiger werden. Für solche GUI-Sachen ist das primäre Ziel: Bequeme und leicht verständliche Verwendbarkeit. (Und Themenbedingt sind auch (ansonsten "klassische") Anforderungen wie _Erweiterbarkeit_ hier kein Thema: So wie der Springer springt, springt er schon immer, und wird er immer springen  )

EDIT: Aber in bezug auf die einfache Verwendung hat Schandro schon recht: Eine Klasse "Field" oder "Position" statt eines Arrays (wo man beim Zugriff an Position 'n' nicht weiß, ob man da nun eine x- oder y-Koordinate bekommt) wäre vielleicht ganz nett. Denk' mal drüber nach, an wie vielen Stellen du mit den (x,y)-Koordinaten von Feldern rumhantieren musst...


----------



## KlinCh (29. Mai 2009)

Schandro hat gesagt.:


> man die x- und  y-Koordinate eines Feldes zusammen speichern kann.



java.awt.Point ?


----------



## Schandro (29. Mai 2009)

> java.awt.Point ?


Nö. Ne eigene Klasse, wo man dann auch noch andere Methoden/Membervarialbe/usw.. unterbringen kann.

Außerdem speichert "Point" double Werte, ist also grundsätzlich nicht dafür ausgelegt genaue Indexe zu enthalten.


----------



## Ohne? (29. Mai 2009)

Moin,

so, ich dachte ich lade mal den momentanen Zustand meines Schachprogramms auf den Server damit ihr mal meine Klassen anschauen könnt.

Wenn jemand von euch mir hilfreiche Tipps hat, bin ich dankbar!

hier der Link: Index of /schule/Projektarbeit_Schach


----------



## Marco13 (29. Mai 2009)

Von verletzten Naming-Conventions, nichtssageneden Methodennamen, schrechlichstem Denglisch und Tippfehlern (hey, das sind ja gleich 4 Wünsche auf einmal - das geht nun wirklich nicht - DOCH! Mit "getStr_Groese" :autsch: ) mal abgesehen: "Turm" und "Läufer" erben von "Dame" ???:L "Extends" ist eine "ist-ein"-Beziehung. Die Beziehung, die du jetzt modelliert hast, ist als: "Ein Turm IST EINE Dame" .... ?!


----------



## Ohne? (29. Mai 2009)

Marco13 hat gesagt.:


> "Turm" und "Läufer" erben von "Dame" ???:L "Extends" ist eine "ist-ein"-Beziehung. Die Beziehung, die du jetzt modelliert hast, ist als: "Ein Turm IST EINE Dame" .... ?!


Ja ich dachte mir, dass der Turm "nur" eine Zugmöglichkeit hat, entweder horizontal oder vertikal, beim Läufer ist es dabei immer nur diagonal. Und Weil die Dame beide Zug varianten hat, dachte ich mir, dass ich den Läufer und den Turm mit der Dame beschreiben kann...

Guß


----------



## Marco13 (29. Mai 2009)

Die Intention ... ist ... nachvollziehbar. Aber es ist wichtig, dass durch eine Vererbung keine Einschränkung beschrieben wird - nicht zuletzt weil dadurch das Liskov substitution principle - Wikipedia, the free encyclopedia verletzt wird.

Es wäre ... aus rein theoretisch-architektonischer Sicht vielleicht noch vertretbar, wenn es umgekehrt wäre: "Dame extends Turm", denn sie _erweitert_ ihn ja quasi um die Fähigkeit, auch diagonal gehen zu können. Genausogut könnte man sagen "Dame extends Läufer", dann sie _erweitert_ ihn ja darum, horizontal&vertikal gehen zu können. Da wäre dann (GANZ theoretisch!) Mehrfachvererbung sinnvoll, und GANZ theoretisch und abstrakt könnte man sagen

```
interface HorizontalUndVertikalZiehenKönner { ... }
interface DiagonalZiehenKönner { ... }

class Turm implements HorizontalUndVertikalZiehenKönner { ... }
class Läufer implements DiagonalZiehenKönner { ... }

class Dame implements HorizontalUndVertikalZiehenKönner, DiagonalZiehenKönner {}
```

Aber wie gesagt: Alles ganz theoretisch und abstrakt - objektiv-praktisch gesehen ist das gröbster Unfug ("over-engineering"), weil die Figuren beim Schach vorgegeben sind, und einem die Interfaces nichts bringen außer Schreibarbeit und einer komplizierteren Struktur.

Überleg' dir lieber genauer, was in das Interface/die Klasse "Figur" rein muss. Wenn die z.B. eine abstrakte Methode hat wie

```
public Feld[] getErreichbareFelder();
```
dann können alle Figuren davon erben, und diese Methode ganz pragmatisch und für sie passend implementieren. Ist aber nur ein ("unverbindlicher") Vorschlag.

Übrigens ist es empfehlenswert, Modell und View zu trennen: Im Moment hat deine "Brett"-Klasse eine "zeichne"-Methode - das sollte so nicht sein. Stattdessen solltest du (speziell weil es um Netzwerkschach geht) das Spiel komplett abstrakt und eigenständig implementieren. Und wenn du mit dem Spiel und der ganzen Steuerungslogik usw. fertig bist, kannst du noch das GUI dazubasteln. In der GUI (View) gäbe es dann sowas wie einen "BrettZeichner", der ein Brett übergeben bekommt, und es z.B. in ein JPanel reinzeichnen kann.

Und auch noch ganz nebenbei: Schach (also nur das Spiel an sich) ist aus Software-Engineering-Sicht ein bißchen ein Spezialfall: Es ändert sich nie mehr etwas. Es wird nie zusätzliche Figuren geben, die Figuren werden nie etwas anderes können, usw - das ganze ist recht "starr". Zusätzlich gibt es aber einen Haufen Spezialfälle, die einer "Vereinheitlichung", die man bei einem theoretischen Entwurf häufig zu maximieren versucht, entgegenstehen:
- Eine Figur bewegt sich IMMER senkrecht, waagerecht oder diagonal - AUSSER den Springern
- Wenn man eine gegnerische Figur schlägt, dann IMMER weil eine eigene Figur ihren Platz engenommen hat - AUSSER beim Schlagen en passant.
- Es wird in jedem Zug IMMER nur _eine_ Figur bewegt - AUSSER bei der Rochade
- Ein König kann IMMER nur ein Feld weit laufen - AUSSER bei der Rochade
- Man kann eine Figur IMMER auf ein freies Feld ziehen - AUSSER wenn dadurch der eigene König im Schach steht
...

Das sind Sachen, die man von vornherien berücksichten sollte. Noch ein (auch unverbindlicher) Tipp: Erstelle dir eine Klasse "Zug", die ALLE relevanten Informationen über einen Zug speichert (Start- und Zielfelder, geschlagene Figur, etc...). Wenn du es schaffst, irgendwo zwei Methoden zu haben

```
brett.macheZug(zug);
// und
brett.macheZugRückgängig(zug); // !!!
```
kannst du einen Lehrer vielleicht noch mit einer kleinen, rudimentären KI beeindrucken. (_Viel_ mehr als diese beiden Methoden braucht man dafür erstmal nicht)


----------



## Ohne? (29. Mai 2009)

Folgendes Problem:

Es tauchte soeben die Frage auf, wie man eine externe .jar-Datei ausführen kann.

Es soll durch einen Klick auf den Button eine externe .jar-Datei ausgeführt werden. Durch den Buttonklick sollen Parameter an die .jar-Datei übergeben werden (diese sind dann in args[0],args[1]...usw.).

Was benötige ich im Quellcode, um die .jar-Datei ausführen zu können.

Gruß Ohne?


----------

