Я готовлю приложение для игры в гомоку.Нить, ожидающая щелчка пользователя
Я создал красивый графический интерфейс, теперь я сражаюсь с основным двигателем.
Существует класс 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();
}
}
}
и мой класс Клиент запуска() метод:
@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() «Клиент должен дождаться, когда пользователь наберет правильное место на доске. Итак ... есть MouseListener в моем классе Board:
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
или мои графические блоки.
Надеюсь, я объяснил свою проблему достаточно. Я был бы благодарен за любую помощь.
EDIT:
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, но я действительно не знаю, что.
EDIT 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();
}
}
}
}
* «Вот почему это так сложно». * Чтобы лучше помочь, отправьте [SSCCE] (http://sscce.org/) вашу лучшую попытку только с многопоточными и щелчками мыши. –
Свинг. Ну, это большое приложение с множеством классов. Я пытался вырезать важные вещи. Многопоточность между игрой и клиентами отлично работает. Я попытался сделать hardcode this currentMove. Проблема возникает, когда я пытаюсь подождать GUI. Я просто не уверен, что следует ждать, когда и где его следует уведомить. Так что я не знаю, как это сделать: Переместить waitForPickedMove() и уведомление как-то ... не так вот в movePicked() – aerion