# Design von Userinteraktion versus KI-only



## member4711JF (18. Dez 2008)

Hi,

ich programmiere ein kleines Spiel und kann es in zwei Modis laufen lassen: entweder KI gegen User, oder KI gegen KI.

Mein problem ist jetzt dass ich für die Implementierung der Modies sehr unterschiedliche Klassen kreiert habe (von der GUI für die Userinteraktion mal ganz abgesehen), obwohl eigentliche in beiden Varianten das gleiche gemacht wird.

Der Ablauf bei KI gegen KI ist simpel:


```
void spiele() {

   lass_KI_A_was_machen();

   lass_KI_B_reagieren();

   ...

   ...

} //spiel beendet
```



Aber der Ablauf KI gegen User lässt sich einfach nicht schön programmieren (weil asynchron):


```
void spiele() {

  lass_User_was_machen(); //er agiert hier auf einer GUI (JFrame etc.)

  return; // !!! ich muss erst warten bis der benutzer was gemacht, solange kann die KI nicht reagieren

  // lass_KI_reagieren() geht hier nicht

}
```



```
//call-back: die Spieleklasse muss darauf vertrauen dass diese Methode von der GUI aufgerufen sobald der 
//Benutzer seine Aktion ausgeführt hat
void benutzer_hat_reagiert() {  
    
    lass_KI_reagieren()

    ...  //weitere Spielpfade werden jedesmal (wie oben) durch das Benutzerhandling "zerhackt",
        //was immer wieder neue call-back methoden erfordert

    ...
}
```

Je komplizierter die Spielpfade, desto unübersichtlicher wird die Implementierung durch die "User-Interrupts".


Idealerweise sollten beide Modis durch die gleiche spiele() methode implementiert werden. Ich möchte am liebsten eine Spielehandlingklasse unabhängig davon implementieren ob Benutzer oder KIs agieren.

Bisher fällt mir nur eine (unschöne) Lösung ein:


```
void spiele() {
   
  lass_Spieler_A_was_tun(); (Benutzer oder KI)

  while (!Spieler_A_hat_reagiert()) {
      //loop solange bis der Spieler fertig ist
      //auch hier muss man darauf vertrauen dass vom Spieler ein  flag gesetzt wird sobald er fertig ist,
      //sodass Spieler_A_hat_reagiert() true zurückliefert und die Schleife beendet wird
  }

  lass_Spieler_B_reagieren();

  ...

  ...

}
```

Jetzt aber die Frage an euch! Gibt es da noch andere Möglichkeiten  der Implementierung der beiden Modies, beziehungsweise leicht einzubauende User-callbacks die den "Flow" der Spiel-Implementierung nicht stören? Hab mich bisher kaum mit sowas beschäftigen müssen...


Grüße und Danke im vorraus,
Sebastian


----------



## Marco13 (18. Dez 2008)

Ein Ansatz wäre, dass der eigentliche "Kern" des Spiels, der ja ggf. solche Methoden anbietet wie

```
void doNextMove() { ... }
```
in diesen Methoden bleibt, bis der nächste Zug abgeschlossen ist. Die Methode kann dann z.B. so implementiert sein

```
void doNextMove() 
{ 
    Move move = activePlayer.getNextMove();
    ...
}
```
wobei "getNextMove" für die KI eben einfach den Zug ausrechnet. Für den menschlichen Spieler würde man da auf die GUI-Eingabe warten, mit wait und notify

```
class HumanPlayer implements Player
{
    private Move nextMove;

    public synchronized Move getNextMove()
    {
        while (nextMove == null)
        {
            try { wait();  } catch ...
        }
        Move toReturn = nextMove;
        nextMove = null;
        return toReturn;
    }

    public synchronized void setNextMoveFromGUI(Move nextMove)
    {
        this.nextMove = nextMove;
        notifyAll();
    }

}
```
Die Methode setNextMoveFromGUI kann dann vom GUI (z.B. in einer actionPerformed- oder mouseClicked-Methode) aufgerufen werden.


----------



## member4711JF (18. Dez 2008)

notify/wait - sehr interessant!!

Vielen Dank für die Idee!
Sebastian


----------

