Hallo zusammen,
ich habe derzeit ein kleines Problem mit der Umsetzung des Observer-Patters. Zur Zeit programmiere ich ein Schachspiel mit GUI, in welchem ich versuche das MVC-Prinzip umzusetzen.
Ein menschlicher Spieler nimmt beispielsweise Spielzüge auf der GUI des Spiels vor und Listener fungieren dabei als Controller, um die Veränderungen am model durchzuführen.
Außerdem soll es aber auch möglich sein, dass der Computer Züge durchführt, also ein Mensch gegen den Computer spielt.
Für diesen Fall hab ich mir das so gedacht, dass das Model Observable ist und die View einen Observer implementiert. Soll heißen, wenn der Computer eine Änderung am Model macht, indem er einen Spielzug durchführt, soll die View das mitbekommen und einen repaint() machen.
Ganz grob klappt das auch, allerdings mit einer Notlösung. Ich weiß nicht recht, an welcher Stelle bzw. zu welcher Zeit ich den Observer registrieren muss.
Model:
Controller:
View:
Wenn ich also nun im Konstruktor der BoardGraphic (view) den Controller erzeugen möchte und das Panel selbst übergebe, kommt es zur StackOverflow Exception. Das liegt wohl daran, dass das Game, welches mit getCurrentGame() geholt wird, zu der Zeit noch nicht besteht. (Vermute ich).
Wenn ich den Observer erst weiter unten in der paintComponent()-Methode registriere klappt das Ganze. Aber sinnvoll erscheint mir das nicht.
GameManager:
Game (grob):
Vielleicht steigt ja jemand durch meinen Code und kann mir einen Tipp geben Vielen Dank schonmal!
ich habe derzeit ein kleines Problem mit der Umsetzung des Observer-Patters. Zur Zeit programmiere ich ein Schachspiel mit GUI, in welchem ich versuche das MVC-Prinzip umzusetzen.
Ein menschlicher Spieler nimmt beispielsweise Spielzüge auf der GUI des Spiels vor und Listener fungieren dabei als Controller, um die Veränderungen am model durchzuführen.
Außerdem soll es aber auch möglich sein, dass der Computer Züge durchführt, also ein Mensch gegen den Computer spielt.
Für diesen Fall hab ich mir das so gedacht, dass das Model Observable ist und die View einen Observer implementiert. Soll heißen, wenn der Computer eine Änderung am Model macht, indem er einen Spielzug durchführt, soll die View das mitbekommen und einen repaint() machen.
Ganz grob klappt das auch, allerdings mit einer Notlösung. Ich weiß nicht recht, an welcher Stelle bzw. zu welcher Zeit ich den Observer registrieren muss.
Model:
Java:
package model;
import java.util.Observable;
import controller.BoardObserver;
public class Board extends Observable {
//Variablen
//Konstruktor
//Methoden
public void executeMove(Move move) {
// führt Änderungen am Model duch, Spielzug wird ausgeführt
setChanged();
IO.println(hasChanged());
notifyObservers();
Controller:
Java:
package controller;
import model.Board;
import model.Game;
import view.BoardGraphic;
public class BoardObserver {
Game currentgame;
public BoardObserver(BoardGraphic panel) {
//Holt das aktuelle Spiel, welches durch ein Singleton-Pattern instanziiert wird
Game currentgame = GameManager.getInstance().getCurrentGame();
Board model = currentgame.getBoard();
model.addObserver(panel);
//Testausgabe zur Prüfung
IO.println("neuerObserver");
}
}
View:
Java:
package view;
import model.Board;
import model.Game;
import controller.BoardObserver;
import controller.GameManager;
import controller.Mouselistener;
import controller.MousemotionListener;
etc....
public class BoardGraphic extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
ActivePiece activepiece = null;
boolean isDragging, isPressed, moveExecuted = false;
final int CELLSIZE = 80;
public BoardGraphic() {
this.setPreferredSize(new Dimension(650, 600));
this.setBackground(new Color(230, 230, 250));
this.addMouseListener(new Mouselistener(this));
this.addMouseMotionListener(new MousemotionListener(this));
//Erzeugen des Controllers
BoardObserver controller = new BoardObserver(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int xStart = this.getWidth() / 2;
int yStart = this.getHeight() / 2;
this.setFont(g);
..........usw.
@Override
public void update(Observable o, Object arg) {
IO.println("update");
this.repaint();
}
}
Wenn ich also nun im Konstruktor der BoardGraphic (view) den Controller erzeugen möchte und das Panel selbst übergebe, kommt es zur StackOverflow Exception. Das liegt wohl daran, dass das Game, welches mit getCurrentGame() geholt wird, zu der Zeit noch nicht besteht. (Vermute ich).
Wenn ich den Observer erst weiter unten in der paintComponent()-Methode registriere klappt das Ganze. Aber sinnvoll erscheint mir das nicht.
GameManager:
Java:
public class GameManager {
private static GameManager gameManager = null;
private Game currentGame;
protected GameManager() {
currentGame = newHumanGame();
}
public static GameManager getInstance() {
if (gameManager == null) {
gameManager = new GameManager();
}
return gameManager;
}
public Game getCurrentGame() {
return currentGame;
}
public Game newHumanGame() {
Player humanA = new HumanPlayer(true);
Player humanB = new HumanPlayer(false);
currentGame = new Game(humanA, humanB);
return currentGame;
}
public Game newGame(Player playerA, Player playerB) {
currentGame = new Game(playerA, playerB);
return currentGame;
}
// Start des Spiels
public static void main(String[] args) {
GameManager.getInstance();
}
}
Game (grob):
Java:
public class Game {
private Board board;
private Referee referee;
private GUI gui;
private Player[] player;
private Player currentPlayer;
private boolean end;
public Game(Player playerA, Player playerB) {
this.board = new Board();
this.referee = new Referee();
this.player = new Player[2];
this.player[0] = playerA;
this.player[1] = playerB;
this.currentPlayer = playerA;
this.gui = new GUI("Spiel");
this.end = false;
}
Vielleicht steigt ja jemand durch meinen Code und kann mir einen Tipp geben Vielen Dank schonmal!
Zuletzt bearbeitet: