# Fehler bei TicTacToe



## info=) (1. Jul 2012)

Hallo, 
ich muss nächste Woche ein Schulprojekt abgeben, in dem es darum geht ein TicTacToe-Spiel in BlueJ zu programmieren. Leider ist dabei jetzt ein Fehler aufgetreten und ich weiß ehrlich gesagt nicht, woran es liegt. 
Ich hoffe, ihr könnt mir dabei helfen. =)

Ich habe die Klassen SPIEL, SPIELER und SPIELFELD erstellt, als Hilfe waren die Klassen Kreis, Dreieck und Leinwand schon vorgegeben.
Die Attributdeklaration sieht folgendermaßen aus:
SPIEL:

```
private SPIELER aktuellerSpieler;
private SPIELFELD spielfeld1;
private SPIELFELD [] aktuellesSpielfeld;
private SPIELER spieler1;
private SPIELER spieler2;
```

und der Konstruktor von SPIEL:


```
public SPIEL(SPIELER NeuerSpieler1,SPIELER NeuerSpieler2){
spieler1=NeuerSpieler1;
spieler2=NeuerSpieler2;
spieler1.SpielBekanntmachen(this);
spieler2.SpielBekanntmachen(this);
spielfeld1=new SPIELFELD();
spielfeld1.SpielbrettZeichnen();
spieler1.SpielsymbolSetzen(1);
spieler2.SpielsymbolSetzen(2);
aktuellesSpielfeld=new SPIELFELD();
}
```

SPIELER:

```
public SPIEL spiel1;
public String name;
public int spielsymbol;
```

SPIELFELD:

```
private int [] spielfeld;
private SPIEL aktuellesSpiel;
private SPIELER spieler;
```

Jetzt erhalte ich beim Übersetzen aber die Fehlermeldung 'incompatible types' für die Zeile 
	
	
	
	





```
aktuellesSpielfeld=new SPIELFELD();
```
. Könnt ihr mir helfen, das zu beheben?

Für Eure Hilfe schon einmal Vielen Dank im Voraus!


----------



## pl4gu33 (1. Jul 2012)

private SPIELFELD [] aktuellesSpielfeld;

aktuellesSpielfeld=new SPIELFELD();


da liegt der Fehler du willst dem Array ein Spielfeld zuweisen 

du musst dem Spielfeld schon ein Array geben wie z.b. 

aktuellesSpielfeld =new SPIELFELD[5]; oder so ...


----------



## info=) (1. Jul 2012)

Oh, ja, danke.
Ich habe allerdings jetzt noch eine andere Frage/ bzw. ein anderes Problem:
In einer Methode habe ich folgenden Code programmiert:

```
public void SpielzugVerarbeiten(int feldnummer){
int symbol;
symbol=aktuellerSpieler.SpielsymbolGeben();
if(aktuellesSpielfeld[feldnummer]==null){
    aktuellesSpielfeld[feldnummer]=symbol;
    spielfeld1.NeuGesetztenSteinZeichnen(feldnummer);
}else{
    System.out.println("Das gewählte Feld ist leider bereits besetzt!");
}
...
[/Java]
Für die Zeile [c] aktuellesSpielfeld[feldnummer]=symbol;
```
 kommt diese Fehlermeldung auch. Was muss ich ändern?


----------



## njans (1. Jul 2012)

```
SPIELFELD [] aktuellesSpielfeld;
```
aktuellesSpielfeld ist ein Array vom Typ SPIELFELD. Da musst du dann auch Objekte vom Typ SPIELFELD reinpacken 
ints gehören da eben dann nicht rein.


----------



## pl4gu33 (1. Jul 2012)

```
aktuellesSpielfeld[feldnummer]=symbol;
```

aktuellesSpielfeld[...] kann nur Spielfelder aufnehmen, du versuchst symbol(was ein int ist soweit ich das sehe) zu zuweisen

[EDIT]zu spät [/EDIT]


----------



## info=) (1. Jul 2012)

Ja aber dann (wenn ich symbol vom typ SPIELFELD schreibe) kann ich SpielsymbolGeben() nicht mehr zuweisen. Wie könnte ich das dann lösen?


----------



## njans (1. Jul 2012)

```
private SPIELFELD spielfeld1;
private SPIELFELD [] aktuellesSpielfeld;
```

Die beiden variablen wundern mich. Wieso ist denn da ein Spielfeld und dann noch ein Spielfeld-Array? Reicht es nicht, wenn du aus aktuellesSpielfeld ein int array machst und dann einfach nur Einträge der Form hast: 0 = kein Spieler, 1 = Spieler1, 2 = Spieler2 ?


----------



## info=) (1. Jul 2012)

Danke.
Leider ist noch ein Fehler aufgetreten:
Ich habe noch folgende Methoden angelegt:
in SPIELER:

```
public void SpielzugAusführen(int feldnummer){
spiel1.SpielzugVerarbeiten(feldnummer);

}
```

in SPIELFELD:

```
public void NeuGesetztenSteinZeichnen(int feldnummer){
spieler.SpielzugAusführen(feldnummer);
if(spielfeld[feldnummer]==1){
    if(feldnummer==1){
        aktuellesSpiel.DreieckLinksOben();
    }
    if(feldnummer==2){
        aktuellesSpiel.DreieckMitteOben();
    }

usw...
```



Wenn ich das jetzt ausprobiere, erhalte ich für die Zeile [c]spieler.SpielzugAusführen(feldnummer); [/c] die Fehlermeldung:java.lang.NullPointerException:null.
Wo liegt der Fehler?


----------



## AquaBall (1. Jul 2012)

spieler == null


----------



## info=) (1. Jul 2012)

?
Kannst du mir das genauer erklären?


----------



## Schandro (1. Jul 2012)

hat er doch. Die Variable "spieler" ist null, deswegen wird eine NullPointerException geschmissen.


----------



## info=) (1. Jul 2012)

Tut mir leid, ich steh wahrscheinlich gerade auf der Leitung, aber wie kann ich das ändern?


----------



## pl4gu33 (1. Jul 2012)

dem Spieler einen Spieler zuweisen ... der is nämlich leer


----------



## AquaBall (1. Jul 2012)

info=) hat gesagt.:


> ?
> Kannst du mir das genauer erklären?



Warum dein 
	
	
	
	





```
spieler == null
```
 ist kann ich nicht sagen, dazu hast du zu wenig code gezeigt.

... weiter oben weist du zwar spieler1=NeuerSpieler1 zu, aber auch ohne Erklärung wo das herkommt.
Und "spieler" kann ich nirgends entdecken.
(PS: das sollte *n*euerSpieler1 heißen - lowerCamelCase)


----------



## info=) (1. Jul 2012)

@pl4gu33
?
Aber dann kann er doch das zugewiesene Attribut nicht finden, oder?


----------



## AquaBall (1. Jul 2012)

info=) hat gesagt.:


> ?
> Aber dann kann er doch das zugewiesene Attribut nicht finden, oder?



Wie meinen? wer? wessen Attribut?
Nochmal: ... weist du zwar spieler1=NeuerSpieler1 zu ... und "spieler" kann ich nirgends entdecken.


----------



## info=) (1. Jul 2012)

'spieler' wird in SPIELFELD als Attribut deklariert:

```
private int [] spielfeld;
private SPIEL aktuellesSpiel;
private SPIELER spieler;
```

Die Wertzuweisung kommt aus dem Konstruktor von SPIEL.


----------



## AquaBall (1. Jul 2012)

Ich seh noch immer keine Zuweisung.


----------



## pl4gu33 (1. Jul 2012)

info=) hat gesagt.:


> Die Wertzuweisung kommt aus dem Konstruktor von SPIEL.



in dem Konstruktor weißt du nur spieler 1 und spieler 2 einen Wert zu... klar kann er die finden aber poste doch mal mehr code


----------



## info=) (1. Jul 2012)

@ AquaBall
In SPIEL lege ich spieler1 als Attribut an und weise ihm dann über den Paramater im Konstruktor NeuerSpieler1 zu, dann kann ich beim Anlegen von jedem Objekt den Namen individuell eingeben. Stimmt doch, oder?
Aber wie bekomme ich jetzt die NullPointerException raus?


----------



## AquaBall (1. Jul 2012)

info=) hat gesagt.:


> In SPIEL lege ich spieler1 als Attribut an und weise ihm dann über den Paramater im Konstruktor NeuerSpieler1 zu, dann kann ich beim Anlegen von jedem Objekt den Namen individuell eingeben. Stimmt doch, oder?



Ich versteh nicht, wie du das meinst.
Natürlich kannst du jeden Objekt einen beliebigen Namen geben.
aber anlegen musst du es, *und* Wert zuweisen.


----------



## info=) (1. Jul 2012)

Ich schick den Code als PN, da wir in der Parallelklasse mal einen ähnlichen Fall hatten, wo mehr Leute ins Internet geschaut haben und dann alle die gleiche Lösung hatten. Es gab ne 6 für alle, weil niemand sagen konnte oder wollte, wer denn abgeschrieben hat.
Bin jetzt fast fertig mit dem Projekt und will kein Risiko mehr eingehen.


----------



## pl4gu33 (1. Jul 2012)

in SPIELFELD:

```
public void NeuGesetztenSteinZeichnen(int feldnummer){
spieler.SpielzugAusführen(feldnummer);
if(spielfeld[feldnummer]==1){
    if(feldnummer==1){
        aktuellesSpiel.DreieckLinksOben();
    }
    if(feldnummer==2){
        aktuellesSpiel.DreieckMitteOben();
    }

usw...
```


das hast du gepostet und wir wollen einfach nur sehen, wo du den spieler in Spielfeld einen Wert zuweist,... weil von allein nimmt der keinen Wert an


----------



## AquaBall (1. Jul 2012)

info=) hat gesagt.:


> ... wo mehr Leute ins Internet geschaut haben und dann alle die gleiche Lösung hatten ...


Das ist einer der Gründe, warum wir hier keine Hausübungen lösen, sondern nur Tips und Infos geben.

Es geht schlicht um die Frage, wo du 
	
	
	
	





```
spieler
```
 einen Wert zuweist.


----------



## info=) (1. Jul 2012)

soll ich die Zuweisung im Konstruktor machen? Dann müsste ich aber in SPIEL vieles ändern, weil ich da ja Referenzattribute habe.
Wäre es irgendwie möglich den Wert von aktuellerSpieler in SPIELFELD zu übertragen und spieler zuzuweisen?


----------



## AquaBall (1. Jul 2012)

Solange du keinen Code postest können wir kaum helfen.

Schon allein die Frage, ob du mit spieler den spieler1 oder spieler2 meinst, ist ja nicht klar.
irgendwo muss halt stehen:

```
spieler =...
```

Poste den Code-Ausschnitt, und dokumentier meinetwegen deinem Lehrer, dass hier gelernt hast, und nicht abgeschrieben.


----------



## pl4gu33 (1. Jul 2012)

du kannst es z.b. so machen :


```
public void NeuGesetztenSteinZeichnen(int feldnummer, Spieler sp){
sp.SpielzugAusführen(feldnummer);
if(spielfeld[feldnummer]==1){
    if(feldnummer==1){
        aktuellesSpiel.DreieckLinksOben();
    }
    if(feldnummer==2){
        aktuellesSpiel.DreieckMitteOben();
    }
```

du übergibst den Spieler einfach in der Methode

oder halt wirklich den Spieler vorher zuweisen


----------



## info=) (1. Jul 2012)

Vielen Dank, das konnte ich soweit jetzt umsetzen. Hab noch ein paar Ungenauigkeiten gefunden, um die ich mich jetzt kümmern muss, sollte allerdings klappen.
Sollte noch ein Problem auftauchen, werde ich mich nochmal melden.


----------



## info=) (3. Jul 2012)

Hallo,
wie gesagt habe ich heute mein Projekt nochmal verbessert - was ja auch relativ gesehen ist - aber es läuft immer noch nicht richtig. 
Sobald ich auf SpielzugAusführen(int feldnummer) eines Spielerobjekts klicke, kommt in der Konsole folgende Meldung:
Das gewählte Feld ist leider bereits besetzt!
Mike , jetzt bist du dran. Bitte wähle ein neues Feld aus!
Anna , jetzt bist du dran. Bitte wähle ein neues Feld aus!

Das kann irgendwie nicht stimmen, zumal auch nie ein Spielsymbol gezeichnet wird.

Könnt ihr bitte über meinen kompletten Code vielleicht nochmal drüberschauen und die Programmierfehler darin finden?
Im Moment bin ich mit meinem Latein echt am Ende, aber die Note auf das Projekt ist echt ein wesentlicher Bestandteil für die auf meinem Abschlusszeugnis und daher schon wichtig.
Vielen, vielen Dank für Eure Mühe!

Ach ja, der Code:

SPIEL:

```
public class SPIEL {

private SPIELER aktuellerSpieler;
private SPIELFELD spielfeld1;
private int [] aktuellesSpielfeld;
private SPIELER spieler1;
private SPIELER spieler2;


private Dreieck spielfigur1;
private Dreieck spielfigur2;
private Dreieck spielfigur3;
private Dreieck spielfigur4;
private Dreieck spielfigur5;
private Dreieck spielfigur6;
private Dreieck spielfigur7;
private Dreieck spielfigur8;
private Dreieck spielfigur9;

private Kreis spielfigur10;
private Kreis spielfigur11;
private Kreis spielfigur12;
private Kreis spielfigur13;
private Kreis spielfigur14;
private Kreis spielfigur15;
private Kreis spielfigur16;
private Kreis spielfigur17;
private Kreis spielfigur18;



public SPIEL(SPIELER NeuerSpieler1,SPIELER NeuerSpieler2){
spieler1=NeuerSpieler1;
spieler2=NeuerSpieler2;
spieler1.SpielBekanntmachen(this);
spieler2.SpielBekanntmachen(this);
spielfeld1=new SPIELFELD();
spielfeld1.SpielbrettZeichnen();
spieler1.SpielsymbolSetzen(1);
spieler2.SpielsymbolSetzen(2);
aktuellesSpielfeld=new int [9];
}

private void SpielfeldZeichnen(){
spielfigur1=new Dreieck(60, 60, 50, 20, "gelb");
spielfigur2=new Dreieck(60, 60, 120, 20, "gelb");
spielfigur3=new Dreieck(60, 60, 190, 20, "gelb");
spielfigur4=new Dreieck(60, 60, 190, 90, "gelb");
spielfigur5=new Dreieck(60, 60, 120, 90, "gelb");
spielfigur6=new Dreieck(60, 60, 50, 90, "gelb");
spielfigur7=new Dreieck(60, 60, 120, 160, "gelb");
spielfigur8=new Dreieck(60, 60, 50, 160, "gelb");
spielfigur9=new Dreieck(60, 60, 190, 160, "gelb");


spielfigur10=new Kreis(60, 50, 20, "blau");
spielfigur11=new Kreis(60, 120, 20, "blau");
spielfigur12=new Kreis(60, 190, 20, "blau");
spielfigur13=new Kreis(60, 190, 90, "blau");
spielfigur14=new Kreis(60, 120, 90, "blau");
spielfigur15=new Kreis(60, 50, 90, "blau");
spielfigur16=new Kreis(60, 120, 160, "blau");
spielfigur17=new Kreis(60, 50, 160, "blau");
spielfigur18=new Kreis(60, 190, 160, "blau");

}

public void DreieckLinksOben(){
spielfigur1=new Dreieck(60, 60, 50, 20, "gelb");
}
public void DreieckMitteOben(){
spielfigur2=new Dreieck(60, 60, 120, 20, "gelb");
}
public void DreieckRechtsOben(){
spielfigur3=new Dreieck(60, 60, 190, 20, "gelb");
}
public void DreieckMitteRechts(){
spielfigur4=new Dreieck(60, 60, 190, 90, "gelb");
}
public void DreieckMitteMitte(){
spielfigur5=new Dreieck(60, 60, 120, 90, "gelb");
}
public void DreieckMitteLinks(){
spielfigur6=new Dreieck(60, 60, 50, 90, "gelb");
}
public void DreieckMitteUnten(){
spielfigur7=new Dreieck(60, 60, 120, 160, "gelb");
}
public void DreieckLinksUnten(){
spielfigur8=new Dreieck(60, 60, 50, 160, "gelb");
}
public void DreieckRechtsUnten(){
spielfigur9=new Dreieck(60, 60, 190, 160, "gelb");
}


public void KreisLinksOben(){
spielfigur10=new Kreis (60, 20, 20, "blau");
}
public void KreisMitteOben(){
spielfigur11=new Kreis(60, 90, 20, "blau");
}
public void KreisRechtsOben(){
spielfigur12=new Kreis(60, 160, 20, "blau");
}
public void KreisMitteRechts(){
spielfigur13=new Kreis(60, 160, 90, "blau");
}
public void KreisMitteMitte(){
spielfigur14=new Kreis(60, 90, 90, "blau");
}
public void KreisMitteLinks(){
spielfigur15=new Kreis(60, 20, 90, "blau");
}
public void KreisMitteUnten(){
spielfigur16=new Kreis(60, 90, 160, "blau");
}
public void KreisLinksUnten(){
spielfigur17=new Kreis(60, 20, 160, "blau");
}
public void KreisRechtsUnten(){
spielfigur18=new Kreis(60, 160, 160, "blau");
}





public void SpielStarten(){
aktuellerSpieler=spieler1;
spielfeld1.SpielbrettZeichnen();
System.out.println("Spiel beginnt!");
String name;
name=aktuellerSpieler.NameGeben();
System.out.println(name  +  " beginnt! ");
}


public void SpielzugVerarbeiten(int feldnummer){
int symbol;
symbol=aktuellerSpieler.SpielsymbolGeben();
if(aktuellesSpielfeld[feldnummer]==0){
    aktuellesSpielfeld[feldnummer]=symbol;
    spielfeld1.NeuGesetztenSteinZeichnen(feldnummer, aktuellerSpieler);
}else{
    System.out.println("Das gewählte Feld ist leider bereits besetzt!");
}

if(SpielendeTesten()){
    String text;
    text = aktuellerSpieler.NameGeben();
    System.out.println(text  +  " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
}else{
    if(aktuellerSpieler==spieler1){
        aktuellerSpieler=spieler2;
    }else{
        aktuellerSpieler=spieler1;
    }
    String neu=aktuellerSpieler.NameGeben();
    System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
}
}


public boolean SpielendeTesten(){
boolean prüfung;
prüfung=false;
if(aktuellesSpielfeld[0]!=0){
if(aktuellesSpielfeld[4]!=0){
if(aktuellesSpielfeld[8]!=0){
if( aktuellesSpielfeld[0]==aktuellesSpielfeld[1] && aktuellesSpielfeld[1]==aktuellesSpielfeld[2]){
    prüfung=true;
    System.out.println("Das Spiel ist beendet!");
}else{
    if( aktuellesSpielfeld[3]==aktuellesSpielfeld[4] && aktuellesSpielfeld[4]==aktuellesSpielfeld[5]){
    prüfung=true;
    System.out.println("Das Spiel ist beendet!");
    }else{
        if( aktuellesSpielfeld[6]==aktuellesSpielfeld[7] && aktuellesSpielfeld[7]==aktuellesSpielfeld[8]){
            prüfung=true;
            System.out.println("Das Spiel ist beendet!");
        }else{
            if( aktuellesSpielfeld[0]==aktuellesSpielfeld[3] && aktuellesSpielfeld[3]==aktuellesSpielfeld[6]){
                prüfung=true;
                System.out.println("Das Spiel ist beendet!");
            }else{
                if( aktuellesSpielfeld[1]==aktuellesSpielfeld[4] && aktuellesSpielfeld[4]==aktuellesSpielfeld[7]){
                    prüfung=true;
                    System.out.println("Das Spiel ist beendet!");
                }else{
                    if( aktuellesSpielfeld[2]==aktuellesSpielfeld[5] && aktuellesSpielfeld[5]==aktuellesSpielfeld[8]){
                        prüfung=true;
                        System.out.println("Das Spiel ist beendet!");
                    }else{
                        if( aktuellesSpielfeld[0]==aktuellesSpielfeld[4] && aktuellesSpielfeld[4]==aktuellesSpielfeld[8]){
                            prüfung=true;
                            System.out.println("Das Spiel ist beendet!");
                        }else{
                            if( aktuellesSpielfeld[2]==aktuellesSpielfeld[4] && aktuellesSpielfeld[4]==aktuellesSpielfeld[6]){
                                prüfung=true;
                                System.out.println("Das Spiel ist beendet!");
                            }else{
                                System.out.println("Es steht noch kein Sieger fest!");
                            }
                        }
                    }
                }
            }
        }
    }
}
}
}
}
return prüfung;
}
}
```

SPIELER:

```
public class SPIELER{

public SPIEL spiel1;
public String name;
public int spielsymbol;
public SPIELFELD spielfeldJetzt;

 


public SPIELER(String NeuerName){
name=NeuerName;
}

public void SpielBekanntmachen(SPIEL spiel){
spiel1=spiel;
}


public void SpielsymbolSetzen(int symbol){
spielsymbol=symbol;
}

public String NameGeben(){
return name;
}

public int SpielsymbolGeben(){
return spielsymbol;
}

public void SpielzugAusführen(int feldnummer){
spiel1.SpielzugVerarbeiten(feldnummer);
}
}
```

SPIELFELD:

```
public class SPIELFELD{

private int [] spielfeld;
private SPIEL aktuellesSpiel;
private SPIELER spieler;
private Quadrat hintergrund;
private Quadrat quadrat1;
private Quadrat quadrat2;
private Quadrat quadrat3;
private Quadrat quadrat4;
private Quadrat quadrat5;
private Quadrat quadrat6;
private Quadrat quadrat7;
private Quadrat quadrat8;
private Quadrat quadrat9;




public SPIELFELD(){
spielfeld=new int [9];

for (int i=0; i<9; i++){
spielfeld[i]=0;
}
SpielbrettZeichnen();
}

public void BelegungAendern(int feldnummer, int spielfigur){
if (spielfeld[feldnummer]==0){
spielfeld[feldnummer]=spielfigur;
}else{
System.out.println("Das gewünschte Feld ist leider bereits belegt!");
}

}

public void SpielbrettZeichnen(){
hintergrund= new Quadrat(220, 10, 10, "schwarz");
quadrat1=new Quadrat (60, 20, 20, "rot");
quadrat2=new Quadrat (60, 90, 20, "rot");
quadrat3=new Quadrat (60, 160, 20, "rot");
quadrat4=new Quadrat (60, 160, 90, "rot");
quadrat5=new Quadrat (60, 90, 90, "rot");
quadrat6=new Quadrat (60, 20, 90, "rot");
quadrat1=new Quadrat (60, 90, 160, "rot");
quadrat1=new Quadrat (60, 20, 160, "rot");
quadrat1=new Quadrat (60, 160, 160, "rot");



}

public void NeuGesetztenSteinZeichnen(int feldnummer, SPIELER sp){
sp.SpielzugAusführen(feldnummer);
if(spielfeld[feldnummer]==1){
    if(feldnummer==1){
        aktuellesSpiel.DreieckLinksOben();
    }
    if(feldnummer==2){
        aktuellesSpiel.DreieckMitteOben();
    }
    if(feldnummer==3){
        aktuellesSpiel.DreieckRechtsOben();
    }
    if(feldnummer==4){
        aktuellesSpiel.DreieckMitteLinks();
    }
    if(feldnummer==5){
        aktuellesSpiel.DreieckMitteMitte();
    }
    if(feldnummer==6){
        aktuellesSpiel.DreieckMitteRechts();
    }
    if(feldnummer==7){
        aktuellesSpiel.DreieckLinksUnten();
    }
    if(feldnummer==8){
        aktuellesSpiel.DreieckMitteUnten();
    }
    if(feldnummer==9){
        aktuellesSpiel.DreieckRechtsUnten();
    }
}

if(spielfeld[feldnummer]==2){
    if(feldnummer==1){
        aktuellesSpiel.KreisLinksOben();
    }
    if(feldnummer==2){
        aktuellesSpiel.KreisMitteOben();
    }
    if(feldnummer==3){
        aktuellesSpiel.KreisRechtsOben();
    }
    if(feldnummer==4){
        aktuellesSpiel.KreisMitteLinks();
    }
    if(feldnummer==5){
        aktuellesSpiel.KreisMitteMitte();
    }
    if(feldnummer==6){
        aktuellesSpiel.KreisMitteRechts();
    }
    if(feldnummer==7){
        aktuellesSpiel.KreisLinksUnten();
    }
    if(feldnummer==8){
        aktuellesSpiel.KreisMitteUnten();
    }
    if(feldnummer==9){
        aktuellesSpiel.KreisRechtsUnten();
    }
}
}
}
```


----------



## Ikaron (3. Jul 2012)

Zur Not könntest du mich in Skype adden (xXIkaron) und wir das per Bildschirmübertragung machen.. ^^
Das Spielfeld kann man SEHR stark vereinfachen, einfach indem man 
	
	
	
	





```
int[][] spielfeld = new int[9][9];[/c] verwendet^^ Und dann beim Zeichnen einfach durchloopen und je nachdem einfach schauen: wenn spielfeld[x][y] == 0, dann ist es leer, bei 1 hat da Spieler 1 einen Stein und bei 2 Spieler 2. So würde ich das zumindest machen.
Wäre dann auch leichter auf 4x4 zu erhöhen^^
```


----------



## Crian (3. Jul 2012)

```
private Dreieck spielfigur1;
private Dreieck spielfigur2;
private Dreieck spielfigur3;
private Dreieck spielfigur4;
private Dreieck spielfigur5;
private Dreieck spielfigur6;
private Dreieck spielfigur7;
private Dreieck spielfigur8;
private Dreieck spielfigur9;
```

Sowas schreit nach Listen.


----------



## AquaBall (3. Jul 2012)

WOW!
Mir bleibt die Luft weg!

Gut dass du den Code gepostet hast.
Den schreibt auch sicher (hoffentlich) keiner ab!

Ich glaube du kannst schon recht gut programmieren, hast aber noch keine Ahnung von Strukturen.
Den Code solltest du mindestens um 90% kürzen können. Dann findest du auch Fehler leichter.

Der Sinn von Programmieren: Gleiches erkennen und im Idealfall NUR EINMAL schreiben.
Fang mal klein an und mach aus deinen Spielfiguren ein Array.

Wir helfen dir gerne. (Und du warst schon sehr fleißig im Tippen.)


----------



## info=) (3. Jul 2012)

@Ikaron
Hab leider kein Skype;(
Ich muss mich an ein paar Vorgaben halten, die ich jetzt mal poste.


Projekt 10. Jahrgangsstufe – Tic Tac Toe 
Ihr sollt das Spiel TicTacToe programmieren. Das Spiel ist euch sicher (aus dem Unterricht) bekannt, trotzdem noch einmal die wichtigsten Regeln: 

• Das Spielfeld besteht aus 9 Kästchen. 
• Zwei Spieler belegen abwechselnd ein noch freies Kästchen mit ihrem Symbol (hier Kreis oder Dreieck). In unserer Variante soll es sich um menschliche Spieler handeln. Es ist aber grundsätzlich vorstellbar, dass der Rechner selbst einer der beiden Spieler ist. 
• Gewonnen hat der Spieler, der zuerst drei Symbole in einer 
Reihe, einer Spalte oder einer Diagonale anordnen kann. 


1. Folgendes Klassendiagramm ist Grundlage für euer Programm 

_*siehe Anhang1*_

2. Vorschläge für die Realisierung des Spielfeldes 

• Die aktuelle Belegung des Spielfeldes wird in einem int-Feld der Länge 9 abgespeichert. Dabei haben die Feldeinträge 0, 1 und 2 folgende Bedeutung: 0: Feld nicht belegt, 1: Spieler 1 hat Feld belegt, 2: Spieler 2 hat Feld belegt 
• Grafische Darstellung des Spielfeldes 
• Zeichnen eines großen Quadrats, auf dem 9 kleinere Quadrate anderer Farbe abgelegt sind. 
• Belegt Spieler 1 ein Feld, so wird einfach an der richtigen Stelle des Spielfelds ein Dreieck gezeichnet, bei Spieler 2 entsprechend ein Kreis. 
• Es gilt folgende Zuordnung zwischen dem Feld, in dem die Symbole abgespeichert sind und dem Spielbrett: 

_*siehe Anhang2*_


3. Hinweise zu den Methoden 
SPIEL: 

• SpielStarten() Das folgende Struktogramm gibt eine Überblick über die Schritte, die innerhalb der Methode abgearbeitet werden. 
_* siehe Anhang3*_

• SpielendeTesten() Es wird geprüft, ob beim Spielbrett eine Reihe, eine Spalte oder eine Diagonale mit gleichen Spielsteinen belegt ist. Da das Spielbrett in einem Feld „abgespeichert“ ist, wird also getestet, ob die Felder 0, 3 und 6 bzw. die Felder … mit einem identischen Wert belegt sind. 

• SpielzugVerarbeiten(int feldnummer) Das folgende Struktogramm zeigt den in dieser Methode abzuarbeitenden Algorithmus: 
_* siehe Anhang4*_


• Folgende Schritte sind im Konstruktor SPIEL(SPIELER spieler1, SPIELER spieler2) durchzuführen: 
_*siehe Anhang5 *_


SPIELER: 

• void SpielBekanntmachen(SPIEL spiel) Der Spieler muss das aktuelle Spiel „kennen“, d.h. nach dem Erzeugen eines SPIEL-Objekts muss einem geeigneten Referenzattribut des jeweiligen Spielers das aktuelle SPIEL-Objekt zugewiesen werden. 

• void SpielsymbolSetzen(int symbol) Als Spielsymbole stehen die Zahlen 1 und 2 zur Verfügung. Diese müssen bei Spieler 1 bzw. 2 festgelegt werden.  

• String NameGeben() Man braucht evtl. den Namen des Spielers, beispielsweise zur Ausgabe auf der Konsole. 

• int SpielsymbolGeben() Insbesondere beim Setzen des Spielsteins muss man wissen, welches Spielsymbol dem aktuellen Spieler gehört. 

• void SpielzugAusfuehren(int feldnummer) Der (vorerst menschliche) Spieler gibt über diese Methode die Nummer des Feldes ein, das er belegen möchte. 

SPIELFELD: 

• void SpielbrettZeichnen() Diese Methode zeichnet das Spielfeld, also ein großes Quadrat, auf dem 9 kleine Quadrate liegen. 

• void BelegungAendern (int feldnummer, int spielfigur) Das entsprechende Feld wird mit dem Spielsymbol des aktuellen Spielers (also 1 oder 2) belegt. In der einfachen Variante wird davon ausgegangen, dass nur freie Felder gewählt werden. 

• void NeuGesetztenSteinZeichnen(int feldnummer) Nachdem ein Spieler einen Spielzug ausgeführt hat, der gültig ist, wird ein neuer Stein (d.h. Kreis oder Dreieck) auf dem Spielfeld an der richtigen Position gezeichnet. 

Das folgende Sequenzdiagramm verschafft dir einen Überblick über die Kommunikation der am Spiel beteiligen Objekte. Der Spieler 01 (mit dem Spielsymbol 1) wählt dabei das Feld mit der Feldnummer 8.

_*siehe Anhang6*_


----------



## njans (3. Jul 2012)

Magst du dem Aufgabensteller bitte von mir mitteilen, dass er sich doch bitte an die Java Konventionen von Methoden halten mag, wenn er euch das schon beibringen will.


----------



## info=) (3. Jul 2012)

@aquaBall


> Fang mal klein an und mach aus deinen Spielfiguren ein Array.



Deklaration?
private Dreieck [] spielfigur;

und Anlegen im Konstruktor:
spielfigur=new Dreieck[9];

Aber wie lege ich dann die einzelnen Figuren an? Über eine for-Schleife? Und was ist mit den Koordinaten?

Stehe mitlerweile echt unter Zeitdruck...


----------



## njans (3. Jul 2012)

```
for(int i = 0 ; i < spielfigur.lentgth; i ++)
  spielfigur[i]  = new Dreieck(...);
```

Du kannst anhand i auch die Position setztn: z.b. (i%3) * 30
Wobei % der Modulooperator ist. Dieser berechnet den Rest eine Division.
Also  hier ein paar Beispiele:
10 % 2 = 0
10 % 3 = 1
10 % 4 = 2
10 % 5 = 0
10 % 6 = 4


----------



## info=) (3. Jul 2012)

njans hat gesagt.:


> Du kannst anhand i auch die Position setztn: z.b. (i%3) * 30



Die Funktion eines Moduloperators verstehe ich jetzt soweit, aber wie kann ich damit x-/y-Positionen setzen, ich brauche ja 3mal jeweils drei Figuren mitdemselben Rest?


----------



## timbeau (3. Jul 2012)

Willst du nicht statt Quadrate zu zeichnen Buttons nutzen?


```
private void initTttPanel() {
		tttPanel = new JPanel(new GridLayout(3, 3));
		tttPanel.setBackground(backGroundColor);
		List<Integer> buttonSorted = new LinkedList<Integer>();
		//Buttons befüllen & Actionlistener hinterlegen
}
```


----------



## njans (3. Jul 2012)

timbeau ich denke mal, er wird die vorgegebenen Klassen verwenden müssen :/ 
TO bitte mal bestätigen oder Widerlegen.
----------------------------------------


> Die Funktion eines Moduloperators verstehe ich jetzt soweit, aber wie kann ich damit x-/y-Positionen setzen, ich brauche ja 3mal jeweils drei Figuren mitdemselben Rest?



Naja du willst ja ein 3 x 3 Feld erzeugen, dazu brauchst du ja nur x, y Koordinaten.
Wenn du dann (Angenommen ein Rechteck soll 30x30 groß sein und x und y gehen von 1 - 3) jeden x,y Wert mit der Größe multiplizierst, dann geht das ganz einfach: 
xWert für die Stelle, an der das Quadrat gezeichnet wird ist x * 30  (30,60,90)
yWert ist analog dazu y * 30 (30,60,90)
Das kannst du über 2 verschachtelte Schleifen erreichen, oder: 

```
for(int i = 0; i < 9; i ++)
{
 int xKoordinate =  i % 3  // Ist die Spalte 0 - 2
 int yKoordinate =  i/3     // Ist die Zeile 0 - 2
}
```


----------



## info=) (3. Jul 2012)

Ok, ich kann dir soweit folgen. Aber wie muss ich jetzt sämtliche Methoden (die uns unser Lehrer empfohlen hat) wie DreieckLinksOben() usw. und die, die diese referenzieren, umschreiben?

Ja, wir müssen die vorgegebenen Klassen verwenden.


----------



## njans (3. Jul 2012)

Joar ein wenig müsstest du diese dann umschreiben.


----------



## timbeau (3. Jul 2012)

> void BelegungAendern (int feldnummer, int spielfigur)



sollte ausreichen. Diese Methode sorgt für die Änderung des Spielfeldes. 

Notfalls noch eine Methode die die Feldnummer in die Koordinaten umrechnet.

f-nr 1 = 0/0
f-nr 2 = 0/1
...


```
private int[] convertIdToRowCol(int input) {
		int[] arr = new int[2];
		if (input == 1) {
			arr[0] = 0;
			arr[1] = 0;
		} else if (input == 2) {
			arr[0] = 0;
			arr[1] = 1;
		} else if (input == 3) {
			arr[0] = 0;
			arr[1] = 2;
		} else if (input == 4) {
			arr[0] = 1;
			arr[1] = 0;
		} else if (input == 5) {
			arr[0] = 1;
			arr[1] = 1;
		} else if (input == 6) {
			arr[0] = 1;
			arr[1] = 2;
		} else if (input == 7) {
			arr[0] = 2;
			arr[1] = 0;
		} else if (input == 8) {
			arr[0] = 2;
			arr[1] = 1;
		} else if (input == 9) {
			arr[0] = 2;
			arr[1] = 2;

		}
		return arr;
	}
```


----------



## njans (3. Jul 2012)

Also das ist echt hässlich ^^
Sry timbeau, aber da nehme 
A) lieber einen Switch und  
B) leiber keinen  Switch, sondern berechne den index direkt  (siehe 2 posts vor diesem)


----------



## timbeau (3. Jul 2012)

Stimmt, du hast vollkommen recht.


----------



## info=) (3. Jul 2012)

Irgendwie komm ich jetzt nicht mehr recht vom Fleck und morgen ist Endspurt.  Kann bitte einer von Euch meinen Code soweit überarbeiten, sonst bin ich echt aufgeschmissen.
Vielen, vielen Dank!!


----------



## timbeau (3. Jul 2012)

Ähh, ich geh schlafen. In der Zeit heute wäre das locker drin gewesen...aber ich will deine Arbeit nicht schlecht machen. Wann muss das genau fertig sein? Morgen früh hätte ich Zeit.


----------



## info=) (3. Jul 2012)

Hallo timbeau,
das Projekt muss bis Donnerstag fertig sein. Morgen früh muss ich noch in die Schule, bin mittags ab halb zwei zu Hause.
Vielen Dank für deine -wohl echt notwendige- Unterstützung!


----------



## AquaBall (4. Jul 2012)

Daraus ein Programm zu machen wird ein gutes Stück Arbeit!

Bevor ich dir die Überarbeitung präsentiere ein paar Vorbemerkungen:

Programmieren lernen macht Spaß, ist aber auch Arbeit.
Meiner Meinung nach bist du noch völlig überfordert mit so einem Projekt.
Dir sind die wesentlichen Strukturen noch absolut zu wenig geläufig, und musst du dir anschauen.
Dazu ein wesentlicher Tip:
a) kleinerer Programme probieren, bis du mit Arrays, Switch, ... spielend umgehen kannst.
b) das Problem zuerst am Papier lösen, und Ablauf selbst erarbeiten.
c) Üben, experimentieren, denken und genaue Arbeitsweise aneignen.

z.B. versteh ich folgende Liste nicht:

```
KreisLinksOben(...
  KreisMitteOben(...
  KreisRechtsOben(...
  KreisMitteRechts(...
  KreisMitteMitte(...
  KreisMitteLinks(...
  KreisMitteUnten(...
  KreisLinksUnten(...
  KreisRechtsUnten(...
```
In der erste Zeile hast du die Reihenfolge: links, mitte, rechts
in der zweiten: rechts, mitte, links
in der dritten: mitte, links, rechts
Außerdem benennst du die mittlere Zeile anders als obere und untere.
Sowas von schlampig!
Das ist aber nicht nur schlampig anzusehen und zu lesen, sondern macht auch was mit dem Porgramm.
Deine Felder sind dadurch numeriert mit:
1 - 2 - 3
6 - 5 - 4
8 - 7 - 9
Dadurch wird der Index unberechenbar!
Wenn du etwas sorgfältiger bist und systematisch durchnumerierst

```
KreisLinksOben(...
  KreisMitteOben(...
  KreisRechtsOben(...
  KreisLinksMitte(...
  KreisMitteMitte(...
  KreisRechtsMitte(...
  KreisLinksUnten(...
  KreisMitteUnten(...
  KreisRechtsUnten(...
```
dann erhältst du:
1 - 2 - 3
4 - 5 - 6
7 - 8 - 9
Und plötzlich kannst du den Index ganz einfach berechnen:
Zeile = (Index-1)/3; Spalte = (Index-1) % 3
Index = Zeile *3 + Spalte +1
*Und schon kannst du alle Koordinaten mit EINEM Ausdruck berechnen!*

```
z.B.:  Dreieck(60, 60, (i%3)*70+50, (i/3)*70+20, "rot");
```

Deine SpielendeTesten() ist ja auch eine Katastrophe!
Schon die erste Zeile 
	
	
	
	





```
if (aktuellesSpielfeld[0] != 0) {
```
 blockiert alles.
Wenn Feld[0]==0 ist, dann wird in der ganzen Methode absolut nichts mehr getan!!
Formatier den Code richtig, dann siehst du das sofort!
Überleg dir außerdem ein grundlegend anderes Prüfkonzept, und arbeite dabei mit berechneten Indices!


*Aber ich will nicht nur meckern, sondern auch helfen:
*Hier der Code mal nur umgestellt auf Array und Indexberechnung.
OHNE jede weitere Änderung, und ohne getestet zu haben.
Einzig in der Absicht, dass du dir mal durchschaust, was hier passiert ist, und was du daraus lernst.


```
public class SPIEL {

	private SPIELER		aktuellerSpieler;
	private SPIELFELD	spielfeld1;
	private int[]		aktuellesSpielfeld;
	private SPIELER		spieler1;
	private SPIELER		spieler2;

	private Dreieck		spielfigurD[9];

	private Kreis		spielfigurK[9];

	public SPIEL(SPIELER NeuerSpieler1, SPIELER NeuerSpieler2) {
		spieler1 = NeuerSpieler1;
		spieler2 = NeuerSpieler2;
		spieler1.SpielBekanntmachen(this);
		spieler2.SpielBekanntmachen(this);
		spielfeld1 = new SPIELFELD();
		spielfeld1.SpielbrettZeichnen();
		spieler1.SpielsymbolSetzen(1);
		spieler2.SpielsymbolSetzen(2);
		aktuellesSpielfeld = new int[9];
	}

	private void SpielfeldZeichnen() {
		for (i=0;i<9;i++) {
			setzeDreieck(i);
			setzeKreis(i);
		}
	}

	public void setzeDreieck(int feld)   {
		spielfigurK[feld] = new Dreieck(60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb");
	}
	public void setzeKreis(int feld)   {
		spielfigurD[feld] = new Kreis  (60,     (feld%3)*70+50, (feld/3)*70+20, "blau");
	}
	
	public void SpielStarten() {
		aktuellerSpieler = spieler1;
		spielfeld1.SpielbrettZeichnen();
		System.out.println("Spiel beginnt!");
		String name;
		name = aktuellerSpieler.NameGeben();
		System.out.println(name + " beginnt! ");
	}

	public void SpielzugVerarbeiten(int feldnummer) {
		int symbol;
		symbol = aktuellerSpieler.SpielsymbolGeben();
		if (aktuellesSpielfeld[feldnummer] == 0) {
			aktuellesSpielfeld[feldnummer] = symbol;
			spielfeld1.NeuGesetztenSteinZeichnen(feldnummer, aktuellerSpieler);
		} else {
			System.out.println("Das gewählte Feld ist leider bereits besetzt!");
		}

		if (SpielendeTesten()) {
			String text;
			text = aktuellerSpieler.NameGeben();
			System.out.println(text + " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
		} else {
			if (aktuellerSpieler == spieler1) {
				aktuellerSpieler = spieler2;
			} else {
				aktuellerSpieler = spieler1;
			}
			String neu = aktuellerSpieler.NameGeben();
			System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
		}
	}

	public boolean isSpalteEinfärbig(int spalte) { // das machst du als Hausübung 
	}
	public boolean isSeileEinfärbig(int zeile) { // das machst du als Hausübung 
	}
	public boolean isDiagonale1Einfärbig() { // das machst du als Hausübung 
	}
	public boolean isDiagonale2Einfärbig() { // das machst du als Hausübung 
	}
	public boolean SpielendeTesten() {
		boolean prüfung;
		prüfung = false;
		for (i= 0;i<3;i++) {
			if (isSpalteEinfärbig(i)) {
				prüfung = true;
			}
			if (isZeileEinfärbig(i)) {
				prüfung = true;
			}
		}
		if (isDiagonale1Einfärbig()) {
			prüfung = true;
		}
		if (isDiagonale2Einfärbig()) {
			prüfung = true;
		}
		
		if (prüfung) System.out.println("Das Spiel ist beendet!");
		else System.out.println("Es steht noch kein Sieger fest!");

		return prüfung;
	}
}
```


```
public class SPIELFELD{
	 
	private int [] spielfeld;
	private SPIEL aktuellesSpiel;
	private SPIELER spieler;
	private Quadrat hintergrund;
	private Quadrat quadrat[9];
	 
	public SPIELFELD(){
		spielfeld=new int [9];
		 
		for (int i=0; i<9; i++){
			spielfeld[i]=0;
		}
		SpielbrettZeichnen();
	}
	 
	public void BelegungAendern(int feldnummer, int spielfigur){
		if (spielfeld[feldnummer]==0){
			spielfeld[feldnummer]=spielfigur;
		}else{
			System.out.println("Das gewünschte Feld ist leider bereits belegt!");
		}
	}
	 
	public void SpielbrettZeichnen(){
		hintergrund= new Quadrat(220, 10, 10, "schwarz");
		for (i=0;i<9;i++) {
			quadrat[i] = new Quadrat(60, 60, (i%3)*70+50, (i/3)*70+20, "rot");
		}
	}
	
	public void NeuGesetztenSteinZeichnen(int feldnummer, SPIELER sp){
		sp.SpielzugAusführen(feldnummer);
		if(spielfeld[feldnummer]==1) aktuellesSpiel.setzeDreieck(i -1);
		if(spielfeld[feldnummer]==2) aktuellesSpiel.setzeKreis  (i -1);
	}
}
```

Ganz dahingestellt seien noch hunderte Fehlerchen und Konzept-Probleme.
z.B. Wozu brauchst du überhaput spielfigur oder quadrat als Variable?


----------



## info=) (4. Jul 2012)

Erstmal vielen Dank für Deine Mühe!

Ich habe folgendermaßen ergänzt:


```
public boolean istSpalteEinfarbig(int spalte) {
        boolean kontrolle;
        if (spielfigur[spalte]==spielfigur[spalte+3] && spielfigur[spalte+3]==spielfigur[spalte+6]){
                kontrolle=true;
                String text;
                text=aktuellerSpieler.NameGeben();
                System.out.println( text + " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
                    }  
        return kontrolle;
    }
    public boolean istZeileEinfarbig(int zeile) { 
        boolean kontrolle;
        if( spielfigur[zeile+2*zeile]==spielfigur[zeile+2*zeile+1] && spielfigur[zeile+2*zeile+1]==spielfigur[zeile+2*zeile+2]){
                kontrolle=true;
                String text;
                text=aktuellerSpieler.NameGeben();
                System.out.println( text + " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
            }
    }
    public boolean istDiagonale1Einfarbig() { 
        booelan kontrolle;
        if(spielfigur[0]==spielfigur[4] && spielfigur[4]==spielfigur[8]){
                kontrolle=true;
                String text;
                text=aktuellerSpieler.NameGeben();
                System.out.println( text + " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
            }
    }
    public boolean istDiagonale2Einfarbig() { 
        boolean kontrolle;
        if(spielfigur[2]==spielfigur[4] && spielfigur[4]==spielfigur[6]){
                kontrolle=true;
                String text;
                text=aktuellerSpieler.NameGeben();
                System.out.println( text + " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
            }
```


Allerdings bekomme ich bei SPIEL bei setzeDreieck 'incompatible types' für [c]         
spielfigurK[feld] = new Dreieck(60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb");[/c].


----------



## AquaBall (4. Jul 2012)

info=) hat gesagt.:


> Allerdings bekomme ich bei SPIEL bei setzeDreieck 'incompatible types' für [c]
> spielfigurK[feld] = new Dreieck(60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb");[/c].



Das solltest du selbst herausbekommen.
Woran könnte es liegen, dass die ArrayVariable und die new Methode sich hier nicht vertragen?


Es gibt ja noch (sehr) viel zu optimieren:
Überleg mal wie du SpielendeTesten() abändern könntest, wenn du so prüfst:

```
public String istSpalteEinfarbig(int spalte) {
        if (spielfigur[spalte]==spielfigur[spalte+3] && spielfigur[spalte+3]==spielfigur[spalte+6])
                return aktuellerSpieler.NameGeben();
        else return null;
    }
```

PS: Was hast du dir eigentlich gedacht bei:

```
spielfigur[zeile+2*zeile] ... spielfigur[zeile+2*zeile+1] ... spielfigur[zeile+2*zeile+2])
```
Geht das nicht etwas besser?

Aber offensichtlich hast du nun ein bisschen von den Indices für diesen Fall gecheckt.
Weiter so!:toll:


----------



## info=) (4. Jul 2012)

> Woran könnte es liegen, dass die ArrayVariable und die new Methode sich hier nicht vertragen?


Weil Dreieck kein Array als Attribut hat?

Weil SpielendeTesten() ja laut Vorgabe vom Typ boolean sein muss, würde ich Folgendes ändern:

```
public void SpielendeTesten(){
boolean prüfung;
prüfung=false;
for(int i=0, i<3; i++){
  String text1;
  text1=istSpalteEinfarbig(i);
   if (text1!=null){
       prüfung=true;
   }
  String text2;
  text2=istZeileEinfarbig(i)
   if (text2!=null){
       prüfung=true;
   }
   if (istDiagonale1Einfarbig()) {
            prüfung = true;
        }
        if (istDiagonale2Einfarbig()) {
            prüfung = true;
        }
        
        if (prüfung){
            System.out.println("Das Spiel ist beendet!");
        }else{ 
            System.out.println("Es steht noch kein Sieger fest!");
        }
        return prüfung;
    }
```

Aber bekomme  ich bei istSpalteEinfarbig() nicht ein Problem mit der Konsolenausgabe, wo ich eindeutig ausgeben lassen muss, wer der Gewinner ist, z.B. 'Anna, du hast das Spiel gewonnen!'

Auch wenn wir aufgrund des allgemein eher miserablen Vortschritts in der Klasse *vielleicht* Abgabeaufschub bekommen, wäre ich wirklich froh, das jetzt bald abhaken zu können. Muss ja auch noch Physik lernen...=)


----------



## AquaBall (4. Jul 2012)

info=) hat gesagt.:


> Weil Dreieck kein Array als Attribut hat?


Nein. "Type mismach" heißt: Typen passen nicht zusammen.
Also schau die die beiden beteiligten Typen in der Zeile an!



info=) hat gesagt.:


> Weil SpielendeTesten() ja laut Vorgabe vom Typ boolean sein muss, würde ich Folgendes ändern:
> Aber bekomme  ich bei istSpalteEinfarbig() nicht ein Problem mit der Konsolenausgabe, wo ich eindeutig ausgeben lassen muss, wer der Gewinner ist, z.B. 'Anna, du hast das Spiel gewonnen!'


Naürlich musst du die Ausgabe machen. aber 
1) nicht in der Prüfroutine, (Logik und Ausgabe gehört getrennt)
2) nicht x-mal (Daten zuerst sammeln und dann 1x ausgeben!)
Probier mal:

```
public void SpielendeTesten() {
	String sieger = null;
	for (int i = 0; i < 3; i++) {
		if (sieger == null) sieger = istSpalteEinfarbig(i);
		if (sieger == null) sieger = istZeileEinfarbig(i);
	}
	if (sieger == null) sieger = istDiagonale1Einfarbig();
	if (sieger == null) sieger = istDiagonale2Einfarbig();

	if (sieger == null) {
		System.out.println("Es steht noch kein Sieger fest!");
	} else {
		System.out.println( ... );
	}
	return prüfung;
}
```


----------



## njans (4. Jul 2012)

Ich hab mich gestern noch mal fix hingesetzt und ein TicTacToe geschrieben (siehe Anhang). Ich mir auch die mühe gemacht es marginal zu kommentieren.


----------



## info=) (5. Jul 2012)

Vielen Dank, njans.
Habe nur ein kleines Problem: Kann den Anhang nicht mit BlueJ öffnen.
Welches Programm hast du verwendet? Könntest du mir bitte den Code irgendwie zukommen lassen?


----------



## njans (5. Jul 2012)

Das ganze ist ein Eclipse Projekt, allerdings sind die .java Files alle dort enthalten und du kannst diese einfach dort hinpacken, wo du magst, du musst vermutlich das "package" am Anfang jeder Klasse ändern, sollte kein Problem sein.


----------



## pl4gu33 (5. Jul 2012)

njans hat gesagt.:


> Das ganze ist ein Eclipse Projekt, allerdings sind die .java Files alle dort enthalten und du kannst diese einfach dort hinpacken, wo du magst, du musst vermutlich das "package" am Anfang jeder Klasse ändern, sollte kein Problem sein.



ich glaub er meint das ZIP 

damit geht das z.b. 
7-Zip (32 Bit) - Download - CHIP Online

[EDIT]okay Anhang hat sich nämlich irgendwie nach dem Zip angehört  [/EDIT]


----------



## info=) (5. Jul 2012)

Nein, ZIP ist an sich nicht das Problem, ich kann den Ordner schon extrahieren. Aber sobald ich ihn öffnen möchte, kommt die Meldung, dass die Datei nicht geöffnet werden konnte.


----------



## njans (5. Jul 2012)

Du versuchst das bestimmt direkt zu importieren. Das wird wohl nicht gehen, aber ich lad mir mal BlueJay runter und schaue mir das mal eben an.

Hier hast du mal eine Version ohne Packages, die dann für BlueJ funktioniert.


----------



## info=) (5. Jul 2012)

Zunächst einmal Danke für Deine Mühe.  =)))
Aber der Code ist in Englisch geschrieben und mein Lehrer wird sich sehr darüber wundern, dass ich seine Vorgaben (siehe Seite 2) so sehr erweitert und großzügig ausgelegt habe.
Wir sind dafür immer noch zu sehr Anfänger...


----------



## njans (5. Jul 2012)

Zumindest hast du da ein funktionsfähiges Beispiel welches ich, so hoffe ich, doch ausreichen kommentiert habe. Du kannst ja mal reinschauen und versuchen nachzuvollziehen, was ich da mache. Startpunkt ist die Klasse "Games" mit der main-Methode.


----------



## info=) (5. Jul 2012)

Hallo,
ich komme einfach nicht drauf, warum er mir bei [c]         spielfigurK[feld] = new Dreieck (60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb"); [/c] incompatibletypes ausgibt. Im Konstruktor von Dreieck heißt es: [c] 	public Dreieck(int h, int b, int x, int y, String f)  [/c].
Könnte mir bitte jemand auf die Sprünge helfen?


----------



## njans (5. Jul 2012)

Von Welchem typ ist denn spielfigurK ?


----------



## info=) (5. Jul 2012)

Oh, Ok, hab mich verschaut und aus Versehen K und D bei Spielfigur vertauscht.
Aber ein neues Problem:
Ich habe die beiden Methoden programmiert:
[c]
    public void setzeDreieck(int feld)   {
        spielfigurD[feld] = new Dreieck (60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb");
        spielfigur[feld]=Dreieck;
    }
[/c]

[c]

    public void setzeKreis(int feld)   {
        spielfigurK[feld] = new Kreis  (60, 60, (feld%3)*70+50, (feld/3)*70+20, "blau");
        spielfigur[feld]=Kreis;
    }
[/c]

Er sagt für die Zeile [c]        spielfigur[feld]=Dreieck; [/c] acnnot find symbol variable Dreieck, dabei ist spielfigur ein Array vom typ String.


----------



## njans (5. Jul 2012)

Ja, weil du keine Variable mit dem Namen hast. Anstelle eine Variable zu deklarieren, weißt du deinem Array das Objekt doch direkt zu: 

```
public void setzeDreieck(int feld) { 
  Dreieck dreieck = new Dreieck (60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb"); 
  spielfigurD[feld] =  dreieck 
  spielfigur[feld]= dreieck ; 
}
```

Oder: 


```
public void setzeDreieck(int feld) { 
  spielfigurD[feld] = new Dreieck (60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb"); 
  spielfigur[feld]= spielfigurD[feld]; 
}
```


----------



## info=) (5. Jul 2012)

Deine zweite Lösung hat auch die Meldung incompatible types, da spielfigurD ein Array vom Typ Dreieck und spielfigur ein Array vom Typ String ist!?
Und bei der ersten kommt immer noch die Meldung, dass er die Variable nicht findet.


----------



## njans (5. Jul 2012)

Wenn das die 2te Methode hat, dann haben das beide, da beide das gleiche machen (sofern man hier keine Polymorphie ansetzt ). 


```
public void setzeDreieck(int feld) { 
  spielfigurD[feld] = new Dreieck (60, 60, (feld%3)*70+50, (feld/3)*70+20, "gelb"); 
  spielfigur[feld]= "Dreieck";  // Willst du hier nur einen String hinzufügen? 
}
```


----------



## info=) (5. Jul 2012)

Hallo,
also ich habe jetzt nochmal einen Code geschrieben, aber er verweigert SpielzugAusführen(int feldnummer), zeichnet überhaupt nicht und auch die Konsolenausgabe stimmt noch nicht so richtig. Muss das jetzt zum Laufen bekommen, könntest Du es also mal in BlueJ ausprobieren und dir die Unstimmigkeiten anschauen? Komme einfach nicht dahinter...
SPIELER:

```
public class SPIELER{

public SPIEL spiel1;
public String name;
public int spielsymbol;
public SPIELFELD spielfeldJetzt; 

 


public SPIELER(String NeuerName){
name=NeuerName;
}

public void SpielBekanntmachen(SPIEL spiel){
spiel1=spiel;
}


public void SpielsymbolSetzen(int symbol){
spielsymbol=symbol;
}

public String NameGeben(){
return name;
}

public int SpielsymbolGeben(){
return spielsymbol;
}

public void SpielzugAusführen(int feldnummer){
spiel1.SpielzugVerarbeiten(feldnummer);
}
}
```

SPIEL:

```
public class SPIEL {
 
    private SPIELER     aktuellerSpieler;
    private SPIELFELD   spielfeld1;
    private int[]       aktuellesSpielfeld;
    private SPIELER     spieler1;
    private SPIELER     spieler2;
 
    private Dreieck []    spielfigurD;
    private String  []   spielfigur;
    private Kreis  []     spielfigurK;
 
    public SPIEL(SPIELER NeuerSpieler1, SPIELER NeuerSpieler2) {
        spieler1 = NeuerSpieler1;
        spieler2 = NeuerSpieler2;
        spieler1.SpielBekanntmachen(this);
        spieler2.SpielBekanntmachen(this);
        spielfeld1 = new SPIELFELD(this);
        spieler1.SpielsymbolSetzen(1);
        spieler2.SpielsymbolSetzen(2);
        aktuellesSpielfeld = new int[9];
        spielfigur=  new String[9];
        spielfigurD= new Dreieck[9];
        spielfigurK= new Kreis [9];
    }
 
    private void SpielfeldZeichnen() {
        for (int i=0; i<9; i++) {
            setzeDreieck(i);
            setzeKreis(i);
        }
    }
 
    public void setzeDreieck(int feld)   {
        spielfigurD[feld-1] = new Dreieck (60, 60, ((feld-1)%3)*70+50, ((feld-1)/3)*70+20, "gelb");
        spielfigur[feld-1]= "Dreieck";
    }
    
    public void setzeKreis(int feld)   {
        spielfigurK[feld-1] = new Kreis  (60, ((feld-1)%3)*70+20, ((feld-1)/3)*70+20, "blau");
        spielfigur[feld-1]="Kreis";
    }
    
    public void SpielStarten() {
        aktuellerSpieler = spieler1;
        spielfeld1.SpielbrettZeichnen();
        System.out.println("Spiel beginnt!");
        String name;
        name = aktuellerSpieler.NameGeben();
        System.out.println(name + " beginnt! ");
    }
 
    public void SpielzugVerarbeiten(int feldnummer) {
        int symbol;
        symbol = aktuellerSpieler.SpielsymbolGeben();
        if (aktuellesSpielfeld[feldnummer] == 0) {
            aktuellesSpielfeld[feldnummer] = symbol;
            spielfeld1.NeuGesetztenSteinZeichnen(feldnummer, aktuellerSpieler);
        } else {
            System.out.println("Das gewählte Feld ist leider bereits besetzt!");
        }
 
        if (SpielendeTesten()) {
            String text;
            text = aktuellerSpieler.NameGeben();
            System.out.println(text + " , du hast das Spiel gewonnen. Herzlichen Glückwunsch!");
        } else {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
        }
    }
 
    
    public String istSpalteEinfarbig(int spalte) {
        if (spielfigur[spalte]==spielfigur[spalte+3] && spielfigur[spalte+3]==spielfigur[spalte+6]){
                return aktuellerSpieler.NameGeben();
            }else{ return null;}
    }
    
    public String istZeileEinfarbig(int zeile){
           //if( spielfigur[zeile+2*zeile]==spielfigur[zeile+2*zeile+1] && spielfigur[zeile+2*zeile+1]==spielfigur[zeile+2*zeile+2])
        if(spielfigur[3*zeile]==spielfigur[3*zeile+1] && spielfigur[3*zeile+1]==spielfigur[3*zeile+2]){
        return aktuellerSpieler.NameGeben();
       }else{ return null;
        }
    }
    
    public String istDiagonale1Einfarbig(){
        if(spielfigur[0]==spielfigur[4] && spielfigur[4]==spielfigur[8]){
        return aktuellerSpieler.NameGeben();
        }else{
        return null;
       }
    }
    
    public String istDiagonale2Einfarbig(){
        if(spielfigur[2]==spielfigur[4] && spielfigur[4]==spielfigur[6]){
        return aktuellerSpieler.NameGeben();
        }else{
        return null;
       }
    }
    
    public boolean SpielendeTesten() {
       boolean prüfung;
       String sieger = null;
        for (int i = 0; i < 3; i++) {
        if (sieger == null){
            sieger = istSpalteEinfarbig(i);
        }
        if (sieger == null){
            sieger = istZeileEinfarbig(i);
        }
       }
       if (sieger == null){
           sieger = istDiagonale1Einfarbig();
        }
       if (sieger == null){
           sieger = istDiagonale2Einfarbig();
        }
 
       if (sieger == null) {
        prüfung=false;
        System.out.println("Es steht noch kein Sieger fest!");
       } else {
        prüfung=true;
        System.out.println("Das Spiel ist beendet!");
       }
    return prüfung;
    }
    
    
    
}
```

SPIELFELD:

```
public class SPIELFELD{
     
    private int [] spielfeld;
    private SPIEL aktuellesSpiel;
    private SPIELER spieler;
    private Quadrat hintergrund;
    private Quadrat [] quadrat;
     
    public SPIELFELD(SPIEL a){
        spielfeld=new int [9];
        quadrat= new Quadrat [9];
        aktuellesSpiel=a;
        for (int i=0; i<9; i++){
            spielfeld[i]=0;
        }
    }
      
    public void BelegungAendern(int feldnummer, int spielfigur){
        if (spielfeld[feldnummer]==0){
            spielfeld[feldnummer]=spielfigur;
        }else{
            System.out.println("Das gewünschte Feld ist leider bereits belegt!");
        }
    }
     
    public void SpielbrettZeichnen(){
        hintergrund= new Quadrat(220, 10, 10, "schwarz");
        for (int i=0; i<9; i++) {
            quadrat[i] = new Quadrat(60, (i%3)*70+20, (i/3)*70+20, "rot");
        }
    }
    
    public void NeuGesetztenSteinZeichnen(int feldnummer, SPIELER sp){
        sp.SpielzugAusführen(feldnummer);
        if(spielfeld[feldnummer]==1)
            {aktuellesSpiel.setzeDreieck(feldnummer-1);}
        if(spielfeld[feldnummer]==2) 
            {aktuellesSpiel.setzeKreis  (feldnummer-1);}
    }
}
```

_*Vorgegeben*_ waren:
Dreieck:

```
import java.awt.Polygon;

/**
 * Ein Dreieck, das manipuliert werden kann und sich selbst auf einer Leinwand
 * zeichnet.
 * 
 * @author Michael Kölling und David J. Barnes
 * @version 2006.03.30
 */

public class Dreieck {
	private int hoehe;

	private int breite;

	private int xPosition;

	private int yPosition;

	private String farbe;

	private boolean istSichtbar;

	/**
	 * Erzeuge ein Dreieck mit einer Standardfarbe an einer Standardposition.
	 */
	public Dreieck(int h, int b, int x, int y, String f) {
		hoehe = h;
		breite = b;
		xPosition = x;
		yPosition = y;
		farbe = f;
		istSichtbar = false;
		sichtbarMachen();
	}

	/**
	 * Mache dieses Dreieck sichtbar. Wenn es bereits sichtbar ist, tue nichts.
	 */
	public void sichtbarMachen() {
		istSichtbar = true;
		zeichnen();
	}

	/**
	 * Mache dieses Dreieck unsichtbar. Wenn es bereits unsichtbar ist, tue
	 * nichts.
	 */
	public void unsichtbarMachen() {
		loeschen();
		istSichtbar = false;
	}

	/**
	 * Bewege dieses Dreieck einige Bildschirmpunkte nach rechts.
	 */
	public void nachRechtsBewegen() {
		horizontalBewegen(20);
	}

	/**
	 * Bewege dieses Dreieck einige Bildschirmpunkte nach links.
	 */
	public void nachLinksBewegen() {
		horizontalBewegen(-20);
	}

	/**
	 * Bewege dieses Dreieck einige Bildschirmpunkte nach oben.
	 */
	public void nachObenBewegen() {
		vertikalBewegen(-20);
	}

	/**
	 * Bewege dieses Dreieck einige Bildschirmpunkte nach unten.
	 */
	public void nachUntenBewegen() {
		vertikalBewegen(20);
	}

	/**
	 * Bewege dieses Dreieck horizontal um 'entfernung' Bildschirmpunkte.
	 */
	public void horizontalBewegen(int entfernung) {
		loeschen();
		xPosition += entfernung;
		zeichnen();
	}

	/**
	 * Bewege dieses Dreieck vertikal um 'entfernung' Bildschirmpunkte.
	 */
	public void vertikalBewegen(int entfernung) {
		loeschen();
		yPosition += entfernung;
		zeichnen();
	}

	/**
	 * Bewege dieses Dreieck langsam horizontal um 'entfernung'
	 * Bildschirmpunkte.
	 */
	public void langsamHorizontalBewegen(int entfernung) {
		int delta;

		if (entfernung < 0) {
			delta = -1;
			entfernung = -entfernung;
		} else {
			delta = 1;
		}

		for (int i = 0; i < entfernung; i++) {
			xPosition += delta;
			zeichnen();
		}
	}

	/**
	 * Bewege dieses Dreieck langsam vertikal um 'entfernung' Bildschirmpunkte.
	 */
	public void langsamVertikalBewegen(int entfernung) {
		int delta;

		if (entfernung < 0) {
			delta = -1;
			entfernung = -entfernung;
		} else {
			delta = 1;
		}

		for (int i = 0; i < entfernung; i++) {
			yPosition += delta;
			zeichnen();
		}
	}

	/**
	 * Ändere die Höhe in 'neueHoehe' und die Breite in 'neueBreite'. Beide
	 * Angaben müssen größer gleich Null sein.
	 */
	public void groesseAendern(int neueHoehe, int neueBreite) {
		loeschen();
		hoehe = neueHoehe;
		breite = neueBreite;
		zeichnen();
	}

	/**
	 * Ändere die Farbe dieses Dreiecks in 'neueFarbe'. Gültige Angaben sind
	 * "rot", "gelb", "blau", "gruen", "lila" und "schwarz".
	 */
	public void farbeAendern(String neueFarbe) {
		farbe = neueFarbe;
		zeichnen();
	}

	/**
	 * Zeichne dieses Dreieck mit seinen aktuellen Werten auf den Bildschirm.
	 */
	private void zeichnen() {
		if (istSichtbar) {
			Leinwand leinwand = Leinwand.gibLeinwand();
			int[] xpoints = { xPosition, xPosition + (breite / 2),
					xPosition - (breite / 2) };
			int[] ypoints = { yPosition, yPosition + hoehe, yPosition + hoehe };
			leinwand.zeichne(this, farbe, new Polygon(xpoints, ypoints, 3));
			leinwand.warte(10); 
		}
	}

	/**
	 * Lösche dieses Dreieck vom Bildschirm.
	 */
	private void loeschen() {
		if (istSichtbar) {
			Leinwand leinwand = Leinwand.gibLeinwand();
			leinwand.entferne(this);
		}
	}
}
```

Kreis:

```
import java.awt.geom.Ellipse2D;

/**
 * Ein Kreis, der manipuliert werden kann und sich selbst auf einer Leinwand
 * zeichnet.
 * 
 * @author Michael Kölling und David J. Barnes
 * @version 2006.03.30
 */

public class Kreis {
	private int durchmesser;

	private int xPosition;

	private int yPosition;

	private String farbe;

	private boolean istSichtbar;

	/**
	 * Erzeuge einen neuen Kreis an einer Standardposition mit einer
	 * Standardfarbe.
	 */
	public Kreis(int d, int x, int y, String f) {
		durchmesser = d;
		xPosition = x;
		yPosition = y;
		farbe = f;
		istSichtbar = false;
		sichtbarMachen();
	}

	/**
	 * Mache diesen Kreis sichtbar. Wenn es bereits sichtbar ist, tue nichts.
	 */
	public void sichtbarMachen() {
		istSichtbar = true;
		zeichnen();
	}

	/**
	 * Mache diesen Kreis unsichtbar. Wenn es bereits unsichtbar ist, tue
	 * nichts.
	 */
	public void unsichtbarMachen() {
		loeschen();
		istSichtbar = false;
	}

	/**
	 * Bewege diesen Kreis einige Bildschirmpunkte nach rechts.
	 */
	public void nachRechtsBewegen() {
		horizontalBewegen(20);
	}

	/**
	 * Bewege diesen Kreis einige Bildschirmpunkte nach links.
	 */
	public void nachLinksBewegen() {
		horizontalBewegen(-20);
	}

	/**
	 * Bewege diesen Kreis einige Bildschirmpunkte nach oben.
	 */
	public void nachObenBewegen() {
		vertikalBewegen(-20);
	}

	/**
	 * Bewege diesen Kreis einige Bildschirmpunkte nach unten.
	 */
	public void nachUntenBewegen() {
		vertikalBewegen(20);
	}

	/**
	 * Bewege diesen Kreis horizontal um 'entfernung' Bildschirmpunkte.
	 */
	public void horizontalBewegen(int entfernung) {
		loeschen();
		xPosition += entfernung;
		zeichnen();
	}

	/**
	 * Bewege diesen Kreis vertikal um 'entfernung' Bildschirmpunkte.
	 */
	public void vertikalBewegen(int entfernung) {
		loeschen();
		yPosition += entfernung;
		zeichnen();
	}

	/**
	 * Bewege diesen Kreis langsam horizontal um 'entfernung' Bildschirmpunkte.
	 */
	public void langsamHorizontalBewegen(int entfernung) {
		int delta;

		if (entfernung < 0) {
			delta = -1;
			entfernung = -entfernung;
		} else {
			delta = 1;
		}

		for (int i = 0; i < entfernung; i++) {
			xPosition += delta;
			zeichnen();
		}
	}

	/**
	 * Bewege diesen Kreis langsam vertikal um 'entfernung' Bildschirmpunkte.
	 */
	public void langsamVertikalBewegen(int entfernung) {
		int delta;

		if (entfernung < 0) {
			delta = -1;
			entfernung = -entfernung;
		} else {
			delta = 1;
		}

		for (int i = 0; i < entfernung; i++) {
			yPosition += delta;
			zeichnen();
		}
	}

	/**
	 * Ändere den Durchmesser dieses Kreises in 'neuerDurchmesser' (Angabe in
	 * Bildschirmpunkten). 'neuerDurchmesser' muss größer gleich Null sein.
	 */
	public void groesseAendern(int neuerDurchmesser) {
		loeschen();
		durchmesser = neuerDurchmesser;
		zeichnen();
	}

	/**
	 * Ändere die Farbe dieses Kreises in 'neueFarbe'. Gültige Angaben sind
	 * "rot", "gelb", "blau", "gruen", "lila" und "schwarz".
	 */
	public void farbeAendern(String neueFarbe) {
		farbe = neueFarbe;
		zeichnen();
	}

	/**
	 * Zeichne diesen Kreis mit seinen aktuellen Werten auf den Bildschirm.
	 */
	private void zeichnen() {
		if (istSichtbar) {
			Leinwand leinwand = Leinwand.gibLeinwand();
			leinwand.zeichne(this, farbe, new Ellipse2D.Double(xPosition,
					yPosition, durchmesser, durchmesser));
			leinwand.warte(10); 
		}
	}

	/**
	 * Lösche diesen Kreis vom Bildschirm.
	 */
	private void loeschen() {
		if (istSichtbar) {
			Leinwand leinwand = Leinwand.gibLeinwand();
			leinwand.entferne(this);
		}
	}

}
```

Quadrat:

```
import java.awt.Rectangle;

/**
 * Ein Quadrat, das manipuliert werden kann und sich selbst auf einer Leinwand
 * zeichnet.
 * 
 * @author Michael Kölling und David J. Barnes
 * @version 2006.03.30
 */

public class Quadrat {
	public int groesse;

	public int xPosition;

	public int yPosition;

	public String farbe;

	public  boolean istSichtbar;

	/**
	 * Erzeuge ein neues Quadrat mit einer Standardfarbe an einer
	 * Standardposition.
	 */
	public Quadrat(int g, int x, int y, String f) {
		groesse = g;
		xPosition = x;
		yPosition = y;
		farbe = f;
		istSichtbar = true;
		zeichnen();
	}

	/**
	 * Mache dieses Quadrat sichtbar. Wenn es bereits sichtbar ist, tue nichts.
	 */
	public void sichtbarMachen() {
		istSichtbar = true;
		zeichnen();
	}

	/**
	 * Mache dieses Quadrat unsichtbar. Wenn es bereits unsichtbar ist, tue
	 * nichts.
	 */
	public void unsichtbarMachen() {
		loeschen();
		istSichtbar = false;
	}

	/**
	 * Bewege dieses Quadrat einige Bildschirmpunkte nach rechts.
	 */
	public void nachRechtsBewegen() {
		horizontalBewegen(20);
	}

	/**
	 * Bewege dieses Quadrat einige Bildschirmpunkte nach links.
	 */
	public void nachLinksBewegen() {
		horizontalBewegen(-20);
	}

	/**
	 * Bewege dieses Quadrat einige Bildschirmpunkte nach oben.
	 */
	public void nachObenBewegen() {
		vertikalBewegen(-20);
	}

	/**
	 * Bewege dieses Quadrat einige Bildschirmpunkte nach unten.
	 */
	public void nachUntenBewegen() {
		vertikalBewegen(20);
	}

	/**
	 * Bewege dieses Quadrat horizontal um 'entfernung' Bildschirmpunkte.
	 */
	public void horizontalBewegen(int distance) {
		loeschen();
		xPosition += distance;
		zeichnen();
	}

	/**
	 * Bewege dieses Quadrat vertikal um 'entfernung' Bildschirmpunkte.
	 */
	public void vertikalBewegen(int entfernung) {
		loeschen();
		yPosition += entfernung;
		zeichnen();
	}

	/**
	 * Bewege dieses Quadrat langsam horizontal um 'entfernung'
	 * Bildschirmpunkte.
	 */
	public void langsamHorizontalBewegen(int entfernung) {
		int delta;

		if (entfernung < 0) {
			delta = -1;
			entfernung = -entfernung;
		} else {
			delta = 1;
		}

		for (int i = 0; i < entfernung; i++) {
			xPosition += delta;
			zeichnen();
		}
	}

	/**
	 * Bewege dieses Quadrat langsam vertikal um 'entfernung' Bildschirmpunkte.
	 */
	public void langsamVertikalBewegen(int entfernung) {
		int delta;

		if (entfernung < 0) {
			delta = -1;
			entfernung = -entfernung;
		} else {
			delta = 1;
		}

		for (int i = 0; i < entfernung; i++) {
			yPosition += delta;
			zeichnen();
		}
	}

	/**
	 * Ändere die Größe dieses Quadrates in 'neueGroesse'. 'neueGroesse' muss
	 * groesser gleich Null sein.
	 */
	public void groesseAendern(int neueGroesse) {
		loeschen();
		groesse = neueGroesse;
		zeichnen();
	}

	/**
	 * Ändere die Farbe dieses Quadrates in 'neueFarbe'. Gültige Angaben sind
	 * "rot", "gelb", "blau", "gruen", "lila" und "schwarz".
	 */
	public void farbeAendern(String neueFarbe) {
		farbe = neueFarbe;
		zeichnen();
	}

	/**
	 * Zeichne dieses Quadrat mit seinen aktuellen Werten auf den Bildschirm.
	 */
	private void zeichnen() {
		if (istSichtbar) {
			Leinwand leinwand = Leinwand.gibLeinwand();
			leinwand.zeichne(this, farbe, new Rectangle(xPosition, yPosition,
					groesse, groesse));
			leinwand.warte(10);
		}
	}

	/**
	 * Lösche dieses Quadrat vom Bildschirm.
	 */
	private void loeschen() {
		if (istSichtbar) {
			Leinwand leinwand = Leinwand.gibLeinwand();
			leinwand.entferne(this);
		}
	}
}
```


----------



## info=) (5. Jul 2012)

Leinwand war auch noch vorgegeben:



```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * Leinwand ist eine Klasse, die einfache Zeichenoperationen auf einer
 * leinwandartigen Zeichenfläche ermöglicht. Sie ist eine vereinfachte Version
 * der Klasse Canvas (englisch für Leinwand) des JDK und wurde speziell für das
 * Projekt "Figuren" geschrieben.
 * 
 * 
 * @author: Bruce Quig
 * @author: Michael Kölling (mik)
 * @author: Axel Schmolitzky
 * 
 * @version: 2006.03.30
 */
public class Leinwand {
	// Hinweis: Die Implementierung dieser Klasse (insbesondere die
	// Verwaltung der Farben und Identitäten der Figuren) ist etwas
	// komplizierter als notwendig. Dies ist absichtlich so, weil damit
	// die Schnittstellen und Exemplarvariablen der Figuren-Klassen
	// für den Lernanspruch dieses Projekts einfacher und klarer
	// sein können.

	private static Leinwand leinwandSingleton;

	/**
	 * Fabrikmethode, die eine Referenz auf das einzige Exemplar dieser Klasse
	 * zurückliefert. Wenn es von einer Klasse nur genau ein Exemplar gibt, wird
	 * dieses als 'Singleton' bezeichnet.
	 */
	public static Leinwand gibLeinwand() {
		if (leinwandSingleton == null) {
			leinwandSingleton = new Leinwand("BlueJ Figuren Demo", 300, 300,
					Color.white);
		}
		leinwandSingleton.setzeSichtbarkeit(true);
		return leinwandSingleton;
	}

	// ----- Exemplarvariablen -----

	private JFrame fenster;

	private Zeichenflaeche zeichenflaeche;

	private Graphics2D graphic;

	private Color hintergrundfarbe;

	private Image leinwandImage;

	private List<Object> figuren;

	private Map<Object, ShapeMitFarbe> figurZuShape;
	
	/**
	 * Erzeuge eine Leinwand.
	 * 
	 * @param titel
	 *            Titel, der im Rahmen der Leinwand angezeigt wird
	 * @param breite
	 *            die gewünschte Breite der Leinwand
	 * @param hoehe
	 *            die gewünschte Höhe der Leinwand
	 * @param grundfarbe
	 *            die Hintergrundfarbe der Leinwand
	 */
	private Leinwand(String titel, int breite, int hoehe, Color grundfarbe) {
		fenster = new JFrame();
		zeichenflaeche = new Zeichenflaeche();
		fenster.setContentPane(zeichenflaeche);
		fenster.setTitle(titel);
		zeichenflaeche.setPreferredSize(new Dimension(breite, hoehe));
		hintergrundfarbe = grundfarbe;
		fenster.pack();
		figuren = new ArrayList<Object>();
		figurZuShape = new HashMap<Object, ShapeMitFarbe>();
	}

	/**
	 * Setze, ob diese Leinwand sichtbar sein soll oder nicht. Wenn die Leinwand
	 * sichtbar gemacht wird, wird ihr Fenster in den Vordergrund geholt. Diese
	 * Operation kann auch benutzt werden, um ein bereits sichtbares
	 * Leinwandfenster in den Vordergrund (vor andere Fenster) zu holen.
	 * 
	 * @param sichtbar
	 *            boolean für die gewünschte Sichtbarkeit: true für sichtbar,
	 *            false für nicht sichtbar.
	 */
	public void setzeSichtbarkeit(boolean sichtbar) {
		if (graphic == null) {
			// erstmaliger Aufruf: erzeuge das Bildschirm-Image und fülle
			// es mit der Hintergrundfarbe
			Dimension size = zeichenflaeche.getSize();
			leinwandImage = zeichenflaeche.createImage(size.width, size.height);
			graphic = (Graphics2D) leinwandImage.getGraphics();
			graphic.setColor(hintergrundfarbe);
			graphic.fillRect(0, 0, size.width, size.height);
			graphic.setColor(Color.black);
		}
		fenster.setVisible(sichtbar);
	}

	/**
	 * Zeichne für das gegebene Figur-Objekt eine Java-Figur (einen Shape) auf
	 * die Leinwand.
	 * 
	 * @param figur
	 *            das Figur-Objekt, für das ein Shape gezeichnet werden soll
	 * @param farbe
	 *            die Farbe der Figur
	 * @param shape
	 *            ein Objekt der Klasse Shape, das tatsächlich gezeichnet wird
	 */
	public void zeichne(Object figur, String farbe, Shape shape) {
		figuren.remove(figur); // entfernen, falls schon eingetragen
		figuren.add(figur); // am Ende hinzufügen
		figurZuShape.put(figur, new ShapeMitFarbe(shape, farbe));
		erneutZeichnen();
	}

	/**
	 * Entferne die gegebene Figur von der Leinwand.
	 * 
	 * @param figur
	 *            die Figur, deren Shape entfernt werden soll
	 */
	public void entferne(Object figur) {
		figuren.remove(figur); // entfernen,falls schon eingetragen
		figurZuShape.remove(figur);
		erneutZeichnen();
	}

	/**
	 * Setze die Zeichenfarbe der Leinwand.
	 * 
	 * @param farbname
	 *            der Name der neuen Zeichenfarbe.
	 */
	public void setzeZeichenfarbe(String farbname) {
		if (farbname.equals("rot")) {
			graphic.setColor(Color.red);
		} else if (farbname.equals("schwarz")) {
			graphic.setColor(Color.black);
		} else if (farbname.equals("blau")) {
			graphic.setColor(Color.blue);
		} else if (farbname.equals("gelb")) {
			graphic.setColor(Color.yellow);
		} else if (farbname.equals("gruen")) {
			graphic.setColor(Color.green);
		} else if (farbname.equals("lila")) {
			graphic.setColor(Color.magenta);
		} else if (farbname.equals("weiss")) {
			graphic.setColor(Color.white);
		} else {
			graphic.setColor(Color.black);
		}
	}

	/**
	 * Warte für die angegebenen Millisekunden. Mit dieser Operation wird eine
	 * Verzögerung definiert, die für animierte Zeichnungen benutzt werden kann.
	 * 
	 * @param millisekunden
	 *            die zu wartenden Millisekunden
	 */
	public void warte(int millisekunden) {
		try {
			Thread.sleep(millisekunden);
		} catch (Exception e) {
			// Exception ignorieren
		}
	}

	/**
	 * Zeichne erneut alle Figuren auf der Leinwand.
	 */
	private void erneutZeichnen() {
		loeschen();
		for (Object figur : figuren) {
			figurZuShape.get(figur).draw(graphic);
		}
		zeichenflaeche.repaint();
	}

	/**
	 * Lösche die gesamte Leinwand.
	 */
	private void loeschen() {
		Color original = graphic.getColor();
		graphic.setColor(hintergrundfarbe);
		Dimension size = zeichenflaeche.getSize();
		graphic.fill(new Rectangle(0, 0, size.width, size.height));
		graphic.setColor(original);
	}

	/***************************************************************************
	 * Interne Klasse Zeichenflaeche - die Klasse für die GUI-Komponente, die
	 * tatsächlich im Leinwand-Fenster angezeigt wird. Diese Klasse definiert
	 * ein JPanel mit der zusätzlichen Möglichkeit, das auf ihm gezeichnet Image
	 * aufzufrischen (erneut zu zeichnen).
	 */
	private class Zeichenflaeche extends JPanel {
		private static final long serialVersionUID = 20060330L;

		public void paint(Graphics g) {
			g.drawImage(leinwandImage, 0, 0, null);
		}
	}

	/***************************************************************************
	 * Interne Klasse ShapeMitFarbe - Da die Klasse Shape des JDK nicht auch
	 * eine Farbe mitverwalten kann, muss mit dieser Klasse die Verknüpfung
	 * modelliert werden.
	 */
	private class ShapeMitFarbe {
		private Shape shape;

		private String farbe;

		public ShapeMitFarbe(Shape shape, String farbe) {
			this.shape = shape;
			this.farbe = farbe;
		}

		public void draw(Graphics2D graphic) {
			setzeZeichenfarbe(farbe);
			graphic.fill(shape);
		}
	}

}
```


----------



## njans (5. Jul 2012)

Leinwand fehlt auch 

Edit:
okay, hast du ja schon nachgereicht.


----------



## njans (5. Jul 2012)

*So fertig*. Sollte jetzt gehen. Ich hab mir kurz mal das "Klassen-Diagramm" von Aufgabe 1 angeschaut. Richtiges UML wäre mir lieber, da würde man auch sehen, was Public und private sein soll. 
Du hattest eine Menge unnötiger Variablen drin und hast vieles doppelt und dreifach gemacht. Was dir wohl das größte Problem gemacht hat, war die Struktur. Das Spielfeld hält den Zustand des Spiels und aktualisiert sich, je nachdem, was für Eingaben kommen. Das Spiel muss nicht wissen, wie das Spielfeld aufgebaut ist und wie es gerade aussieht, es muss nur abfragen können, ob ein Spiel fertig ist. 

Was das zeichnen angeht: Du musst da keine Objekte zwischenspeichern, sobald du ein neues Objekt erstellst, zeichnet es sich selbst. Daher kannst du dir das Dreieck[] und Kreis[] sparen 

Du solltest die Benennung von Klassen und Methoden aber noch mal überdenken, denn wenn dein Prof dir sagt, dass du so schreiben sollst, dann macht er etwas falsch. "MeineMethode()", das wäre okay, wenn wir in C-sharp wären, in java werden Methoden klein zu beginn geschrieben, also "meineMethode()". Klassen werden genauso geschrieben, wie Methoden, die dir dein Prof andrehen will, also "MeinKlasse", aber bitte nicht alles großschreiben.   

Selbst jetzt noch, sind viele Parameter und Referenzen nicht notwendig, aber ist ja nicht schädlich für die Funktionalität.

P.S. BlueJay ist zum Kotzen^^ Diese "IDE" kann so gut wie gar nichts und ist nicht besser als ein Text Editor.


----------



## AquaBall (5. Jul 2012)

info=) hat gesagt.:
			
		

> Oh, Ok, hab mich verschaut und aus Versehen K und D bei Spielfigur vertauscht.


Und wie hast du gesucht, dass das solange gedauert hat?

Und mit korrekter Formatierung würdest du viel beser suchen können!

Dein SpielendeTesten kann man nochmal optimieren, außerdem verwendest du 'sieger' gar nicht!

```
public String pruefe(int a, int b, int c)){
        if(spielfigur[a]==spielfigur[b] && spielfigur[b]==spielfigur[c]){
        return aktuellerSpieler.NameGeben();
        }else{
        return null;
       }
    }
    
    public boolean SpielendeTesten() {
       boolean prüfung;
       String sieger = null;
        for (int i = 0; i < 3; i++) {
        if (sieger == null){
            sieger = pruefe(i,i+3,i+6); // ist Spalte Einfarbig?
        }
        if (sieger == null){
            sieger = pruefe(3*i,3*i+1,3*i+2); // ist Zeile Einfarbig?
        }
       }
       if (sieger == null){
           sieger = pruefe(0,4,8); // ist Diagonale1 Einfarbig?
        }
       if (sieger == null){
           sieger = pruefe(2,4,6); // ist Diagonale2 Einfarbig?
        }
 
       if (sieger == null) {
        prüfung=false;
        System.out.println("Es steht noch kein Sieger fest!");
       } else {
        prüfung=true;
        System.out.println("Gratuliere "+sieger+", du hast gewonnen! Das Spiel ist beendet!");
       }
    return prüfung;
    }
```


----------



## njans (6. Jul 2012)

Die Methoden habe ich schon alle umgebaut  
Die sehen nun alle deutlich besser aus. 
Da war eben viel unnötiges drin und die Daten, die eigentlich SpielFeld haben sollte, sind dann auch in Spiel gewesen und umgekehrt.


----------



## info=) (6. Jul 2012)

njans, wirklich vielen Dank für Deine Mühe.
Ohne Deine Unterstützung wäre es wohl sehr problematisch geworden!!


----------



## AquaBall (6. Jul 2012)

info=) hat gesagt.:


> njans, wirklich vielen Dank für Deine Mühe.
> Ohne Deine Unterstützung wäre es wohl sehr problematisch geworden!!



Eher *ist *es jetzt problematisch!
Was lernst du, wenn du nun vorgefertigten Code abgibst?
Beim nächsten Projekt hast du vielleicht niemanden mehr, der für dich den Denker spielt.

Und bei dem, Code den du allein produziert hast, befürchte ich, dass auch schon bisher einiges Knowhow nicht selbst erarbeitet wurde.

Ohne das Ganze selbst zu erarbeiten kommst du nicht weiter!


----------



## njans (6. Jul 2012)

info=) hat gesagt.:


> njans, wirklich vielen Dank für Deine Mühe.
> Ohne Deine Unterstützung wäre es wohl sehr problematisch geworden!!



Keine Ursache, nur Lernen musst du es eben noch selbst. Das nimmt dir jetzt vielleicht den Druck der Abgabe, aber wenn das nächste mal etwas auf dich zu kommt, dann macht das vielleicht eben keiner für dich ^^. Ich kann nur empfehlen: Programmiere lieber ein ein kleines Projekt für dich selbst.


----------



## info=) (6. Jul 2012)

Hallo,
natürlich habt ihr Recht, dass ich das noch selbst erarbeiten und lernen muss (Im Gegensatz zu den meisten anderen in meiner Klasse habe ich mich aber zumindest hingesetzt und versucht, - wenn auch durchaus verbesserungswürdige - Vorschläge zu liefern). Da ich jedoch noch nie ein so großes Projekt bearbeitet habe, hätte ich mich als Einsteiger auch wohl eher nicht gleich für ein solches Projekt entschieden, wenn ich hätte wählen dürfen....
In diesem Sinne hat mir der Code sehr geholfen, da ich mich jetzt daran als Leitfaden orientieren kann. Ich möchte ihn aber auch gerne selbst zumindest vollständig verstehen können.
Daher - die wohl in euren Augen wohl eher banale - Frage: 
Was bedeutet [c] i+=3[/c] in der for-Schleife [c]for (int i = 0; i < spielfeld.length; i+=3) [/c]?

PS:
Mein Lehrer hat wie bereits angedeutet die Abgabefrist bis Mittwoch verlängert, da in dieser Woche wegen diverser Veranstaltungen ca. die Hälfte der Klasse gefehlt hat.
Dafür hat er uns eine weitere Auflage gegeben, nämlich einen Computer zu programmieren, der gegen einen Spieler spielt und dabei automatisch zieht.

Da ich mir noch nicht ganz zutraue, das alles selbst programmieren zu können, würde ich mich freuen, wenn wir das zusammen erarbeiten könnten.


----------



## njans (6. Jul 2012)

```
for (int i = 0; i < spielfeld.length; i+=3)
```

i+=3 ist einfach nur i = i + 3.
Selbes gilt für *=, -=, etc.


----------



## info=) (6. Jul 2012)

Danke, njans.

Ich fürchte, du müsstest mir beim Computer nochmal helfen. Unser Lehrer meinte, wir könnten Computer als Unterklasse von SPIELER anlegen (andere Lösungen sind auch möglich).
Dazu hab ich jetzt mal das Grobgerüst + Methode zur Erzeugung einer Zufallszahl, die ich ja später als Feldnummer brauche:

```
public class COMPUTER extends SPIELER{


public COMPUTER(String NeuerName){
super(NeuerName);
}

//Zufallszahl zwischen 0 und 9 -> für high später als Parameter 9 einsetzen
public static int myRandom(int low, int high) {  
    return (int) (Math.random() * (high - low) + low);  
} 

}
```


----------



## njans (6. Jul 2012)

Kleiner Tipp: Verwende lieber java.util.Random.
Also Random radnom = new Random(seed); wobei seed eine Konstante ist, somit kriegst du immer die selbe Folge von Zahlen und du kannst Fehler leichter finden. random sollte dann eine Exemplarvariable/Instanzvariable sein.

Nebenbei; Hat euer Lehrer gesagt, dass ihr Klassen GANZ IN GROßBUCHTSATBEN schreiben sollt?


----------



## info=) (6. Jul 2012)

Ja, hat er tasächlich gesagt.


> Kleiner Tipp: Verwende lieber java.util.Random.


???:L
Ich muss wohl dazu sagen, dass wir Zufallszahlen noch nicht in Java hatten, aber gesagt wurde, dass dies hier ganz nützlich wäre.

Dann hab ich noch eine Frage:
Wie soll ich ein Refernzattribut von Computer in Spiel unterbringen und in die Methoden integrieren? Ich muss das Projekt doch erst mal dazu bringen, zu unterscheiden, ob es sich um 2 menschliche Spieler oder um einen menschlichen und einen Computer handelt.


----------



## njans (6. Jul 2012)

```
public class COMPUTER extends SPIELER{
private Random random; 

public COMPUTER(String NeuerName){
  super(NeuerName);
  random = new Random(0);
}

// Du rufst beim Computer eben nicht einfach SpielzugVerarbeiten auf, sondern diese Methode.
public void zufaelligerZug()
{
  // Hier muss was hin
} 
 
}
```


----------



## info=) (6. Jul 2012)

So hätte ich das jetzt mal gemacht. Geht das so?


```
import java.util.Random;
public class COMPUTER extends SPIELER{
private Random random; 
private SPIELFELD spielfeldAktuell;
private COMPUTER computer;
 
public COMPUTER(String NeuerName){
  super(NeuerName);
  NeuerName="Maschine";
  random = new Random(0);
  spielfeldAktuell=new SPIELFELD (this);
}
 
// Du rufst beim Computer eben nicht einfach SpielzugVerarbeiten auf, sondern diese Methode.
public void zufaelligerZug(int random){
    spielfeldAktuell.BelegungAendern(random, SpielsymbolGeben());
    if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = computer;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
        }
  
} 
 
}
```

Aber er hängt bei der Zeile [c]   spielfeldAktuell=new SPIELFELD (this);[/c].


----------



## njans (7. Jul 2012)

Hier zeigt sich wieder, dass du nicht verstehst, was du da eigentlich machst. Du kannst nicht einfach ein neues Spielfeld erzeugen und dann davon ausgehen, dass dieses irgendeinen Bezug auf das Spielfeld hat, welches in deiner SPIEL Klasse instanziert wird. 
Auch sollte Spieler nichts über Spielfeld wissen. Für eine AI bräuchtest du dieses wissen zwar, aber dieses Programm soll ja wohl eher Naiv bleiben  

```
private SPIELFELD spielfeldAktuell; // raus damit
private COMPUTER computer; // Du bist in einem Computer Objekt und brauchst keine Referenz auf ein anderes, raus auch damit.
```

Schau mal in die Spieler Klasse und in die Methode, die du da verwendest, um einen Zug auszuführen und dann überlege dir, wie du diese hier umschreiben musst um einen zufälligen Zug daraus zu machen.


----------



## timbeau (7. Jul 2012)

http://www.java-forum.org/spiele-multimedia-programmierung/135095-tictactoe-bitte-um-feedback.html

Hier habe ich mein TicTacToe mit 3 KIs vorgestellt, der Sourcecode ist auch da drin. Dabei hatte ich auch das Problem, dass ich zwischen manueller und automatischer Eingabe wechseln musste. 

Ich würde eine Methode aufrufen, die mir eine Zahl zurück gibt. Nämlich die ID des Spielfeldes. Diese ID wird dann zusammen mit dem Spieler der diese aufruft (besser: der vom Spiel(leiter) als aktiver Spieler geführt wird) ausgeführt indem das korrekte Symbol ins korrekte Feld geschrieben wird. 

Was machst du, wenn ein Spaßvogel einen Spieler schreibt, der immer 3 Züge aufeinmal macht? 


```
public void zufaelligerZug(int random){
    spielfeldAktuell.BelegungAendern(random, SpielsymbolGeben());
    if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = computer;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
zufaelligerZug(int random) {
.....
}
        }
  
}
```

Dein Spieler darf nur einen Zug machen, die Möglichkeit dazu muss ihm zentral gegeben werden und er darf nur 1 Wert zurückliefern. Keine Aktionen auf dem Spielfeld. Bei der Randommethode braucht er das Spielfeld noch nichtmal zu kennen.


```
public int macheZug(){ //Berechnungen.... hier Random}
```


----------



## njans (7. Jul 2012)

Manche Methoden haben eine Vorgegebene Signatur. Ebenfalls sind viele Klassen und Abhängigkeiten vorgegeben. Generell würde ich es ja auch nicht so machen, wie das aktuelle TTT ist, meine Implementation hätte auch kein Problem mit einer oder mehrerer AIs. Diese Struktur schon, da das Spielfeld so abgekapselt ist, dass man als Spieler nicht daran kommt. Und in BlueJay, bitte korrigiert mich hier, würde ich die SpielzugAusführen Methode an einem Spieler Objekt aufrufen.


----------



## info=) (7. Jul 2012)

Habe zufaelligerZug() nochmal überarbeitet:

```
import java.util.Random;
public class COMPUTER extends SPIELER{
private Random random; 

public COMPUTER(String NeuerName){
  super(NeuerName);
  NeuerName="Maschine";
  random = new Random(0); 
}

public static int gebeZufallszahl(int low, int high) { 
    int zahl= (int) (Math.random() * (high - low) + low);
    return   zahl;
} 



public void zufaelligerZug(){
   SpielzugAusführen(gebeZufallszahl(0, 9));
     
} 
 
}
```

Wie kann ich ihn dazu bringen, dass der Computer automatisch zieht?


----------



## njans (7. Jul 2012)

Wenn er vollkommen automatisch reagieren soll musst du das im SPIEL regeln, dass, wenn der neue Spieler ein Computer ist, er dann automatisch zieht.

// So ist es besser 

```
public COMPUTER(){
  super("Maschine");
```


----------



## info=) (7. Jul 2012)

> Wenn er vollkommen automatisch reagieren soll musst du das im SPIEL regeln, dass, wenn der neue Spieler ein Computer ist, er dann automatisch zieht.


???:L
An sich ist mir das klar, aber wie soll in SPIEL dann die Bedingung dafür aussehen? Ich müsste ja eigentlich prüfen, ob einer der beiden Spieler ein Objekt vom Typ COMPUTER ist!?


----------



## njans (7. Jul 2012)

```
myObject instanceof COMPUTER
```

Damit kriegst du heraus, ob es ein Computer ist


----------



## info=) (7. Jul 2012)

Hätte mir Folgendes gedacht, wobei ich mir bei der Umsetzung nicht sicher bin.
Ich ergänze SpielzugVerarbeiten(int feldnummer) in SPIEL durch:

```
public void SpielzugVerarbeiten(int feldnummer) {
   if(aktuellerSpieler instance of COMPUTER){
   spielfeld1.BelegungAendern(computer.gebeZufallszahl(0,9), aktuellerSpieler.SpielsymbolGeben());
   }else{       
    spielfeld1.BelegungAendern(feldnummer, aktuellerSpieler.SpielsymbolGeben());
   }
        if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
        }
    }
```

Reicht das, wenn ich computer als Referenzattribut von COMPUTER als Variable bei SPIEL deklariere? Oder kommt dann wieder eine NullPointerException?


----------



## njans (7. Jul 2012)

```
spielfeld1.BelegungAendern(((COMPUTER)aktuellerSpieler).gebeZufallszahl(0,9), aktuellerSpieler.SpielsymbolGeben());
```

Das ist besser, als sich extra eine Referenz zurechtzulegen. Du weißt ja schon, dass der aktuelle Spieler eine Instanz von COMPUTER ist, daher kannst du ihn auch ohne Probleme casten.


----------



## info=) (7. Jul 2012)

Danke.
Jetzt ist das Problem aufgetreten, dass der Computer nach dem Aufruf von SpielzugVerarbeiten(int feldnummer) zwar automatisch zieht, aber erst nachdem ich unabhängig davon eine Zahl eingegeben habe, da ja SpielzugVerarbeiten einen Parameter verlangt.
Habe folgenden Lösungsvorschlag:

```
public void ziehen(){
        if(aktuellerSpieler instanceof COMPUTER{
            spielfeld1.BelegungAendern(((COMPUTER)aktuellerSpieler).gebeZufallszahl(0,9), aktuellerSpieler.SpielsymbolGeben());
            if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
           }
        }else{
            SpielzugVerarbeiten(int feldnummer);
        }
    }
    
    
    public void SpielzugVerarbeiten(int feldnummer) {
        spielfeld1.BelegungAendern(feldnummer, aktuellerSpieler.SpielsymbolGeben());
        if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
        }
    }
```

Er sagt '.class' expected für die Zeile [c] SpielzugVerarbeiten(int feldnummer); [/c].
Was sollte ich ändern?


----------



## timbeau (7. Jul 2012)

Code muss in ne Class Datei...

public class name { . .. .


----------



## info=) (7. Jul 2012)

Könntest du mir das bitte genauer erklären?


----------



## njans (7. Jul 2012)

Hast du den ganzen Kram in einer Klassse stehen:


```
public class ClassName{
  // Methode
}
```


----------



## AquaBall (8. Jul 2012)

[OT]Wir helfen gerne.
Aber ich hab mich längst rausgeklinkt.
Ist doch mühsam jede Zeile 3 mal erklären müssen und dann wird sie noch nicht richtig eingebaut.
[/OT]

@TO:
Ich empfehle dir erstmal ein Buch zu lesen, und mit Projektgrößen zu arbeiten die du verstehst.


----------



## info=) (8. Jul 2012)

Da wir alle erst in diesem Schuljahr in Java/BlueJ eingeführt wurden und noch ziemliche Anfänger sind,
blickt bei uns keiner bei dem Projekt wirklich durch, aber die anderen lassen es sich halt von irgenwelchen Vätern/Freunden im LK schreiben und geben es ab, ohne es überhaupt mal angeschaut zu haben. Wir 'ohne connections' haben da schon fast keine Chance mehr, deshalb bin ich wirklich auf Euch angewiesen.
Glaubst du wirklich, irgendwer von uns hätte ein so großes Projekt gewählt, wenn wir wirklich die Wahl gehabt hätten?
Und bei dem kurzfristig angesetzten Termin bleibt zum Einlesen eigentlich keine Zeit mehr.
Im Unterricht bin ich immer gut mitgekommen, aber das Projekt ist viel anspruchsvoller als alles, was wir bisher programmieren mussten und da hier offensichtlich häufig Dinge anzuwenden sind, die wir in der Schule noch nie angesprochen haben, werde ich es als Anfänger wohl kaum sofort verstehen und richtig umsetzen.

@ njans
Vielleicht habe ich ja was falsch gemacht, aber selbst wenn ich das in eine Klase schreibe, kommt die Fehlermeldung immer noch.


----------



## timbeau (8. Jul 2012)

Dann poste die gesamte Klasse in der der Fehler kommt.


----------



## njans (8. Jul 2012)

Schreibe einmal die ganze Klasse hier rein dann kann man den Fehler sicher sehen.


----------



## info=) (8. Jul 2012)

```
public class ZUG{
    public void ziehen(){
        if(aktuellerSpieler instanceof COMPUTER){
            spielfeld1.BelegungAendern(((COMPUTER)aktuellerSpieler).gebeZufallszahl(0,9), aktuellerSpieler.SpielsymbolGeben());
            if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
           }
        }else{
            SpielzugVerarbeiten(int feldnummer);
        }
    }
}
```

Hab einfach ziehen() aus SPIEL in ZUG. Wir sind im Unterricht noch nicht so weit, also verzeiht mir die Frage: Warum brauche ich dafür jetzt eine neue Klasse?



ps: Soll ich den Rest der SPIEL-Klasse auch posten?


----------



## njans (8. Jul 2012)

ich habe keine Ahnung, warum du da nun eine neue Klasse gebaut hast...
Du solltest nur die Klasse Posten, in dem du den Fehler hattest. Eine vollkommen neue Klasse macht da wenig Sinn.


----------



## info=) (8. Jul 2012)

oh, war wohl ein Missverständnis. 

```
public class SPIEL {
 
    private SPIELER     aktuellerSpieler;
    private SPIELFELD   spielfeld1;
    private SPIELER     spieler1;
    private SPIELER     spieler2;

    
    public SPIEL(SPIELER NeuerSpieler1, SPIELER NeuerSpieler2) {
        spieler1 = NeuerSpieler1;
        spieler2 = NeuerSpieler2;
        spieler1.SpielBekanntmachen(this);
        spieler2.SpielBekanntmachen(this);
        spielfeld1 = new SPIELFELD(this);
        spieler1.SpielsymbolSetzen(1);
        spieler2.SpielsymbolSetzen(2);
    }
    
    public void SpielStarten() {
        aktuellerSpieler = spieler1;
        spielfeld1.SpielbrettZeichnen();
        System.out.println("Spiel beginnt!"); 
        String name = aktuellerSpieler.NameGeben();
        System.out.println(name + " beginnt! ");
        // 
    }
    
    public void ziehen(){
        if(aktuellerSpieler instanceof COMPUTER){
            spielfeld1.BelegungAendern(((COMPUTER)aktuellerSpieler).gebeZufallszahl(0,9), aktuellerSpieler.SpielsymbolGeben());
            if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
           }
        }else{
            SpielzugVerarbeiten(int feldnummer);
        }
    }

    
    public void SpielzugVerarbeiten(int feldnummer) {
        spielfeld1.BelegungAendern(feldnummer, aktuellerSpieler.SpielsymbolGeben());
              if (!SpielendeTesten()) {
            if (aktuellerSpieler == spieler1) {
                aktuellerSpieler = spieler2;
            } else {
                aktuellerSpieler = spieler1;
            }
            String neu = aktuellerSpieler.NameGeben();
            System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
        }
    }

    
       
    private boolean SpielendeTesten() {
        boolean gewonnen = spielfeld1.hatSpielerGewonnen();
        boolean weiterZugMoeglich = spielfeld1.istWeitererZugMoeglich();
        
        if (gewonnen){
            System.out.println("Spieler " + aktuellerSpieler.NameGeben() + " hat gewonnen!");
        } else if (!weiterZugMoeglich){
            System.out.println("Es gab ein Unentschieden");
        }
        return  gewonnen || !weiterZugMoeglich;
    }
    
    
    
}
```

Den Fehler erkennt er in Zeile 42.


----------



## njans (8. Jul 2012)

```
SpielzugVerarbeiten(int feldnummer);
```
Dann nehm doch das "in" da weg^^


----------



## info=) (8. Jul 2012)

Irgenwie findet er dann entweder feldnummer als Variable nicht oder er schreibt er erwartet ')' .


----------



## njans (8. Jul 2012)

Woher sollte er denn feldnumemr als Variable kennen ? Du hast die doch in der Methode gar nicht deklariert.
Warum machst du überhaupt eine "ziehen" Methode wenn du schon SpielzugVerarbeiten  hast?


----------



## info=) (8. Jul 2012)

Vorher hatte ich ja in SpielzugVerarbeiten den automatischen Zug des Computers, nachdem überprüft wurde, ob ein Spieler vom Typ COMPUTER ist. Das Problem war aber dann, dass ich immer eine Nummer vorher eingeben musste, da ja SpielzugVerarbeiten einen int-Parameter verlangt. Der Computer ist dann später wirklich unabhängig von dieser Zahl gezogen, aber ohne Zahleneingabe gings eben nicht, was aber irgendwie blöd und irritierend ist, wenn der Computer wirklich von selber ziehen soll. 
Das wollte ich dann lösen, indem ich mit ziehen() eine Methode ohne Parameter angelegt habe, aber jetzt hängt er eben bei SpielzugVerarbeiten, da eben hier jetzt der Parameter fehlt.


----------



## AquaBall (8. Jul 2012)

info=) hat gesagt.:


> Da wir alle erst in diesem Schuljahr in Java/BlueJ eingeführt wurden und noch ziemliche Anfänger sind,
> blickt bei uns keiner bei dem Projekt wirklich durch, aber die anderen lassen es sich halt von irgenwelchen Vätern/Freunden im LK schreiben und geben es ab, ohne es überhaupt mal angeschaut zu haben. Wir 'ohne connections' haben da schon fast keine Chance mehr, deshalb bin ich wirklich auf Euch angewiesen.
> Glaubst du wirklich, irgendwer von uns hätte ein so großes Projekt gewählt, wenn wir wirklich die Wahl gehabt hätten?
> Und bei dem kurzfristig angesetzten Termin bleibt zum Einlesen eigentlich keine Zeit mehr.
> ...



Ich mach dir ja keinen Vorwurf.
Ich weiß  ja auch nicht, aus welcher Altersstufe / Ausbildungsniveau ihr kommt.
Aber:
Wenn "keiner durchblickt": Dann müsst Ihr das euerem Lehrer sagen.
Wenn "zum Einlesen keine Zeit mehr bleibt": Dann hätte das wahrscheinlich früher passieren sollen.
Wenn "Dinge in der Schule nie angesprochen wurden": Dann fragt eueren Lehrer, wie das lösen zu sein soll.
Wenn "Fehlermeldungen kommen": Dann solltest du in der Lage sein, diese zu lesen, und die betroffene Zeile durchzuenken.
Im Allgemeinen sind die Fehler recht klar beschreiben, und so gut wie wörtlich zu nehmen.

Letztlich macht das, was hier produziert werden soll, den Eindruck, dass es gar schon an SpielTheorie grenzen soll. Das wäre (wenn auch hier an einem primitiven BeiSpiel) die Königsklasse.
Wenn dann noch nicht mal Klassen definiert werden können, ist das so, als wollte ich einem 7-jährigen Wurzelziehen beibringen: Bei Genies kann's funktionieren, über ein Scheitern braucht man sich nicht wundern.

Du kannst "'incompatible types" nicht selbständig lösen, erkennst "NullExceptions" nicht, kennst "i+=3" nicht, ...
Alles Dinge, die ein Anfänger nicht können muss, aber sich erarbeiten muss (wenn er's wissen will).
Du lässt dir aber Zeile für Zeile vorkauen, und kommst nach jeder Ausscheidung wieder mit eienr neuen Frage.

Das ist kein Bashing, sondern ich will dir eine ganz ehrlich Hilfe bieten:

Gib das Projekt jetzt so ab wie es ist.
Tu dich mit dienen Mitschülern zusammen, und sagt dem Lehrer, dass das weit entfernt von dem ist, was unterrichtet wurde.
Und dann setzt du dich hin, schlag ein Buch auf, und beginne mit Projekten, die du solange durcharbeitest, bist du JEDE ZEILE VERSTEHST(!) und selbständig erzeugen kannst!

Und sollte Punkt 3 nicht funktionieren (oder nicht richtig sein), dann:
*!! setz dich hin, schlag ein Buch auf, und beginne mit Projekten, die du solange durcharbeitest, bist du JEDE ZEILE VERSTEHST(!) und selbständig erzeugen kannst!!*

[EDIT]eigentlich wollte ich sagen: 
sollte Punkt ZWEI nicht funktionieren (oder nicht richtig sein), dann:
*!! setz dich hin, schlag ein Buch auf, und beginne mit Projekten, die du solange durcharbeitest, bist du JEDE ZEILE VERSTEHST(!) und selbständig erzeugen kannst!!*
[/EDIT]


----------



## info=) (8. Jul 2012)

> aber die anderen lassen es sich halt von irgenwelchen Vätern/Freunden im LK schreiben und geben es ab, ohne es überhaupt mal angeschaut zu haben. Wir 'ohne connections' haben da schon fast keine Chance mehr, deshalb bin ich wirklich auf Euch angewiesen.


Ich hab ja nichts dagegen, das Projekt so abzugeben, wie ichs kann, wenn alle ehrlich arbeiten würden. Nur das Problem (siehe oben) ist eben, dass das bei uns keiner macht und das ist echt ungerecht. Ich kann nichts dafür, dass meine Eltern/näheren Bekannte keine Programmierer/Informatiker sind, aber deswegen will ich mir jetzt meine (Abschluss-)Note auch nicht versauen.
Um ehrlich zu sein, checken (bis auf 2 Ausnahmen) die anderen (26!) noch weniger als ich, aber wer würde das denn ernsthaft zugeben, wenn er weiß, dass er letztlich ein Super-Projekt abgeben wird? Keiner fragt bei uns, wo das herkommt, es zählt nur, was abgegeben wird, und da ist es egal wer es letztlich geschrieben hat, zumal man das sowie so nicht kontrollieren kann. Und dann bin ich wieder der, der in die Röhre und blöd aus der Wäsche schaut, wenn die anderen Spitzennoten für gar nichts bekommen und ich schlecht bewertet werde, weil *nur ich* an dem Projekt gearbeitet habe, so gut wie ich eben konnte, zumal die Note wirklich wichtig ist.
Ich will ja auch nicht, dass mir jemand von Euch den fertigen Code einfach so gibt - da ich in anderen Fächern selbst Nachhilfe gebe, weiß ich, dass das niemand ohne Eigenleistung des anderen gerne macht-, und Erarbeiten gehört- wie ihr zurecht sagt- letztlich zwangsläufig dazu, aber, um ganz ehrlich zu sein, allein schaff ich das jetzt einfach noch nicht und muss deswegen auf Euch zählen.
Deswegen muss ich auch Fragen stellen (dadurch lerne ich ja auch was) - zum einen, weil ich das auch wirklich verstehen will und zum anderen, wenn Probleme auftreten, wo ich bezweifle, allein weit zu kommen.
Ich hoffe, ihr habt dafür Verständnis und noch ein wenig Geduld mit mir!


----------



## njans (8. Jul 2012)

Hab das mal einfach so gefixt, sieht nicht schön aus, sollte aber tun was es soll. Schau mal drüber, probiere es aus und dann versuch es zu verstehen 


```
public void SpielzugVerarbeiten(int feldnummer) {
		
		if (aktuellerSpieler instanceof COMPUTER)
		{
			verarbeiteCompuerZug();
			wechsleSpieler();
		}
		else
		{
			spielfeld1.BelegungAendern(feldnummer, aktuellerSpieler.SpielsymbolGeben());
			if (!SpielendeTesten()){
				wechsleSpieler();
				String neu = aktuellerSpieler.NameGeben();
				System.out.println(neu + " , jetzt bist du dran. Bitte wähle ein neues Feld aus!");
			}
		}

        if(aktuellerSpieler instanceof COMPUTER){
        	verarbeiteCompuerZug();
        	wechsleSpieler();
        }
    }
	
	
	private void verarbeiteCompuerZug()
	{
		spielfeld1.BelegungAendern(((COMPUTER)aktuellerSpieler).gebeZufallszahl(0,9), aktuellerSpieler.SpielsymbolGeben());
	}
	
	private void wechsleSpieler()
	{
		if (aktuellerSpieler == spieler1){
			aktuellerSpieler = spieler2;
		}else{
			aktuellerSpieler = spieler1;
		}
	}
```


----------

