# abstrakte Klassen, Konstanten und Konstruktor



## jason (16. Okt 2010)

Hallo,

ich bin gerade dabei/ich habe vor, ein TicTacToe-Programm zu programmieren, das zur Laufzeit eine selbstgeschriebene KI laden kann.
Das Laden selbst ist kein Problem, allerdings bereitet mir die abstrakte Klasse, von der alle KIs erben müssen, einige Kopfschmerzen.
Bisher sieht es so aus:

TicTacToeAI.java

```
package controller;

import model.TicTacToeField;

public abstract class TicTacToeAI {

    protected final int PLAYER;

    protected final int ENEMY;
    
    protected final int EMPTY_FIELD;

    public TicTacToeAI(int playerField, int enemyField, int emptyField) {
        PLAYER = playerField;
        EMPTY_FIELD = emptyField;
        ENEMY = enemyField;
    }
    
    public abstract void compute(TicTacToeField field);

    public abstract String getDeveloper();

    public abstract String getAIName();
}
```
Die Konstanten dienen dazu, um zu erkennen, ob das Feld, auf das die KI setzen will, leer, vom Feind oder schon selbst besetzt wurde.

Eine einfache KI sieht so aus:

```
import controller.TicTacToeAI;
      import model.TicTacToeField;
      
      import java.util.Random;
      
      public class MyTicTacToeAI extends TicTacToeAI {
          
          private Random r;
          
          public MyTicTacToeAI(int playerField, int enemyField, int emptyField) {
              super(playerField, enemyField, emptyField);
              r = new Random();
          }
          
          public String getAIName() {
              return "MyAI";
          }
          
          public String getDeveloperName() {
              return "jason";
          }
          
          public void compute(TicTacToeField field) {
              int randX, randY;
              
              do {
                  randX = r.nextInt() % 3;
                  randY = r.nextInt() % 3;
                  
                  if (randX < 0)
                      randX *= -1;
                      
                  if (randY < 0)
                      randY *= -1;
                  
              } while (field.get(randX, randY) != EMPTY_FIELD);
              
              field.set(randX, randY);
          }
      }
```

Meine Kopfschmerzen bereitet der Konstruktor:
Ich würde das gerne so machen, dass die Werte für die Konstanten nicht immer weitergereicht werden müssen. (Die Konstanten (außer EMPTY) sind unterschiedlich, weil KI Nr. 1 
	
	
	
	





```
PLAYER = 1
```
 und 
	
	
	
	





```
ENEMY = 2
```
 und KI Nr. 2 gerade umgedreht hat.)
Hat da jemand eine Idee?

MfG jason


----------



## Gast2 (16. Okt 2010)

Also so ganz hab ich den sinn deiner Konstanten noch nicht verstanden.
Sollte nicht besser das spielfeld auskunft darüber geben welches Feld von wem besetzt ist?


----------



## jason (16. Okt 2010)

TicTacToeField hat die Funktion 
	
	
	
	





```
get(int, int)
```
.
Dadurch bekommt man eine bestimmte Zahl zurück.
Ist 
	
	
	
	





```
field.get(0, 0) == EMPTY_FIELD
```
, dann ist das Feld 0, 0 leer.
Ist 
	
	
	
	





```
field.get(0, 0) == PLAYER
```
, dann hat die KI, die an der Reihe ist, schon an dieser Stelle gesetzt.
Ist 
	
	
	
	





```
field.get(0, 0) == ENEMY
```
, dann hat die andere KI schon an dieser Stelle gesetzt.

Oder sollte ich eher Methoden wie:

```
field.isEmpty(int, int)
```
 usw. machen?


MfG jason


----------



## Gast2 (16. Okt 2010)

Ich denke es wäre besser wenn du in der Spielfeldklassen Konstanten EMPTY, PLAYER1 und PLAYER2 hast. Deine get Methode würde diese dann dementsprechend zurückgeben.
Deine KI Klasse müsste dann nur wissen ob sie Player1 oder Player2 ist (das könntest du im Konstruktor übergeben). Die Konstanten in der KI Klasse brauchste dann gar nichtmehr.


----------



## jason (16. Okt 2010)

OK, danke.

MfG jason


----------



## Gelöschtes Mitglied 5909 (16. Okt 2010)

Dann kannst du daraus auch ein interface machen.

Und wenn dir dann noch langweilig ist, kannst du das ganze noch mit OSGi umsetzen, dann kann jeder ein KI Plugin-machen


----------



## jason (16. Okt 2010)

Wenn ich es doch aber als Interface mache, dann habe ich doch keinen vorgegebenen Konstruktor und kann es dann doch auch nicht dynamisch zur Laufzeit laden, oder nicht?

MfG jason


----------



## Gelöschtes Mitglied 5909 (16. Okt 2010)

Wie lädst du es denn bisher? Über Reflection?

Das geht genauso 

Und das mit dem Konstruktor: du hast ihn ja jetzt eh weg, von daher kannst du einen Standard-Konstruktor vorraussetzen.
Wenn du noch andere Sachen brauchst, dann kannst du das über setter regeln (im interface)

Aber warscheinlich hab ich dich jetzt eher verwirrt. Wenn das der Fall ist, dann mach es so wie du denkst


----------



## jason (16. Okt 2010)

Ja, Reflection.

Verwirrt hast du mich (noch) nicht, aber eine Bedingung, die nicht durch Code "erzwungen" wird, finde ich nicht so ... toll, wenn du verstehst, was ich meine. 

Mfg jason


----------



## Landei (16. Okt 2010)

Du kannst dir eine "Übergabe" sparen, wenn du einfach im Konstruktor ENEMY = 3 - PLAYER; setzt.


----------

