五目並べをするアプリを準備中です。
見栄えの良い GUI を作成しましたが、今はコア エンジンと戦っています。
GameEngine
移動するための同期メソッドを持つクラスがあります。IClient
「プレーヤー」であるインターフェイスを実装するクラスもあります。最初に行うことは、(五目板を表す)で「と」と言ったときにPlayerClient
、に接続されてBoardPanel
動くものを実装することです。コンピューター プレーヤーも実装できるように、アプリケーションをオープンにしたいと考えています。それがとても複雑な理由です。MouseListener
BoardPanel
だから...問題:私GameEngine
のクラスは次のようになります:
public class GameEngine {
private IClient blackPlayer;
private IClient whitePlayer;
private GameState gameState;
...
public void play() {
blackPlayer.run();
whitePlayer.run();
}
public synchronized void move(Move move) throws IllegalMoveException {
gameState.move(move);
if (move.isBlackMove()){
whitePlayer.notify();
}else{
blackPlayer.notify();
}
}
public synchronized void waitForYourTurn(boolean color){
try {
while (gameState.isBlackToMove()!=color) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
私の Client クラスには run() メソッドがあります:
@Override
public void run() {
while (gameState.getWinner() == 0) {
move = null;
boolean moved = false;
while (!moved) {
gameEngine.waitForYourTurn(black);
try {
//waitForPickedMove();
gameEngine.move(move);
moved = true;
} catch (IllegalMoveException e) {
e.printStackTrace();
}
}
}
}
「//waitForPickedMove()」と書いた場所で、クライアントはユーザーがボード上の適切な場所をクリックするのを待つ必要があります。だから...私のBoardクラスにはMouseListenerがあります:
private class MoveMouseListener implements MouseListener {
@Override
public synchronized void mouseReleased(MouseEvent e) {
if (gameState == null) {
return;
}
if (currentMove != null) {
movePicked();
repaint();
}
}
}
currentMove はもちろん、ユーザーがボードをクリックして選択した移動です。movePicked() は次のようになります。
private synchronized void movePicked() {
if (gameState.isBlackToMove() && blackClient != null) {
blackClient.notify();
clearCurrentMove();
}
if (!gameState.isBlackToMove() && whiteClient != null) {
whiteClient.notify();
clearCurrentMove();
}
}
いろいろなところに入れてみましたwait()
。制御を逆にしてクラスに入れようとしたBoard
ので、Client クラスのメソッド (setCurrentMove(Move move)) を呼び出しました。残念ながら、私が望むものに到達することはできません。私はいつもIllegalMonitorStateException
GUIブロックを取得します。
私の問題を十分に説明したことを願っています。どんな助けにも感謝します。
編集:
public class MockComputerClient implements IClient {
private GameState gameState;
private GameEngine gameEngine;
private boolean black;
private ExecutorService executorService;
private boolean myTurn = false;
private int i = 3;
public MockComputerClient(GameEngine gameEngine, GameState gameState,
boolean black) {
this.gameEngine = gameEngine;
this.gameState = gameState;
this.black = black;
executorService = new ExecutorService();
executorService.run();
}
@Override
public void enemyMoved() {
myTurn = true;
executorService.notify();
}
private class ExecutorService implements Runnable {
@Override
public void run() {
while (gameState.getWinner() == 0) {
try {
while (!myTurn) {
wait();
}
// Hardcoded Moves
gameEngine.move(new Move(black, 3, i++));
myTurn = false;
} catch (InterruptedException | IllegalMoveException e) {
e.printStackTrace();
}
}
}
}
}
sth を同期する必要があることは確かですが、何を行うべきかはよくわかりません。
編集2:
@Override
public void enemyMoved() {
myTurn = true;
executorService.move();
}
private class ExecutorService implements Runnable {
@Override
public void run() {
while (gameState.getWinner() == 0) {
System.out.println("Calculating: j= " + j);
if (j == 3)
j = 4;
else
j = 3;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void move() {
while (myTurn) {
try {
gameEngine.move(new Move(black, j, i++));
myTurn = false;
} catch (IllegalMoveException e) {
e.printStackTrace();
}
}
}
}