Вот требования: < /p>
одновременный тик-tac-toe-это упражнение, в котором две одновременные нити
представляют игроков и пытаются редактировать одну и ту же настройку таблицы 3x3 x и o. Единственное, что он должен ограничить
, - это установить значение в ячейке, которая уже имеет значение. Игровая таблица
не должна ограничивать установку нескольких одинаковых значений подряд. Игровая таблица
не должна ограничивать установку значения после того, как один из игроков выиграл. См.
«Методы Javadoc». Он расширяет выполняемый интерфейс, чтобы позволить отправить
it в поток для одновременного выполнения. Реализация
compam.pam.rd.autocode.concurrenttictactoe.player createPlayer Метод
подать свою реализацию игрока. Игроки знают
правил игры и прекратят исполнение, когда некоторые из них выиграли.
игроки уважают друг друга и делают свои повороты друг с другом. Процедура
игра выглядит следующим образом: создается пустая доска. Два игрока
получают марки (x и o), создали доску для игры, и стратегии для вычисления
еще один шаг. Оба игрока начинают исполнение в отдельных потоках.
игроки прекращают выполнение, когда Gameis закончится. Ожидаемое состояние таблицы
сравнивается с фактическим. Обратите внимание, каждая игра может длиться не более, чем
2 секунды.package concurrenttictactoe;
public class PlayerImpl implements Player {
private TicTacToe game;
private char mark;
private PlayerStrategy strategy;
private static final long MAX_GAME_DURATION = 2000;
public PlayerImpl(TicTacToe game, char mark, PlayerStrategy strategy) {
this.game = game;
this.mark = mark;
this.strategy = strategy;
}
@Override
public void run() {
Object lock = game.getLock();
while (true) {
synchronized (lock) {
if (game.isGameOver()) break;
while (!game.isGameOver() && ((mark == 'O' && game.lastMark() != 'X') || (mark == 'X' && game.lastMark() == 'X'))) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
if (game.isGameOver() || !isGameRunning(game)) {
lock.notifyAll();
break;
}
Move move = strategy.computeMove(mark, game);
if (move == null) {
throw new UnsupportedOperationException("move is null");
}
game.setMark(move.row, move.column, mark);
lock.notifyAll();
}
}
}
private boolean isGameRunning(TicTacToe game) {
char[][] table = game.table();
/**
* Check
*/
for (int i = 0; i < 3; i++) {
/** CASE 1 - 'Horizontal win case'
* 0 1 2
* 0 -> {'X', 'X', 'X'}
* 1 -> {' ' ' ', ' '}
* 2 -> {' ' ' ', ' '}
* */
if (table[0] != ' ' && table[0] == table[1]
&& table[1] == table[2])
return false;
/** CASE 2 - 'Vertical win case'
* 0 1 2
* 0 -> {'X', ' ', ' '}
* 1 -> {'X' ' ', ' '}
* 2 -> {'X' ' ', ' '}
* */
if (table[0] != ' ' && table[0] == table[1]
&& table[1] == table[2])
return false;
}
/** CASE 3 - 'Diagonal win case'
* 0 1 2
* 0 -> {'X', ' ', 'X'}
* 1 -> {' ' 'X', ' '}
* 2 -> {'X' ' ', 'X'}
* */
if (table[0][0] != ' ' && table[0][0] == table[1][1]
&& table[1][1] == table[2][2])
return false;
if (table[0][2] != ' ' && table[0][2] == table[1][1]
&& table[1][1] == table[2][0])
return false;
/**
* Check if there's still empty cell to move when neither side has won
*/
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (table[i][j] == ' ') {
return true;
}
}
}
return false;
}
}
< /code>
package concurrenttictactoe;
public class TicTacToeImpl implements TicTacToe{
private final Object lock = new Object();
private final long startTime = System.currentTimeMillis();
private volatile boolean gameOver = false;
private char[][] table = new char[][]{
{' ', ' ', ' '},
{' ', ' ', ' '},
{' ', ' ', ' '}
};
private char lastMark = ' ';
@Override
public void setMark(int x, int y, char mark) {
synchronized (lock) {
if (table[x][y] != ' ') {
throw new IllegalArgumentException("This cell already has a value");
}
if (lastMark == mark) {
throw new IllegalArgumentException("This mark already made a move");
}
table[x][y] = mark;
lastMark = mark;
/*//Just for testing!!//TODO: remove following lines after testing
System.out.println("Table state: ");
for (char[] chars : table) {
System.out.println("" + chars[0] + chars[1] + chars[2]);
}
System.out.println("Move ended! last move: " + lastMark + "\n");
/// /////////////////////////////////////*/
lock.notifyAll();
}
}
@Override
public char[][] table() {
char[][] result = new char[3][3];
for (int i = 0; i < result.length; i++) {
result[i][0] = table[i][0];
result[i][1] = table[i][1];
result[i][2] = table[i][2];
}
return result;
}
@Override
public char lastMark() {
return lastMark;
}
public Object getLock(){
return lock;
}
public long getStartTime(){
return startTime;
}
@Override
public boolean isGameOver() {
return gameOver;
}
public void stopGame() {
synchronized (lock) {
gameOver = true;
lock.notifyAll();
}
}
}
< /code>
package concurrenttictactoe;
public interface Player extends Runnable{
static Player createPlayer(final TicTacToe ticTacToe, final char mark, PlayerStrategy strategy) {
return new PlayerImpl(ticTacToe, mark, strategy);
}
}
< /code>
package concurrenttictactoe;
public class Move {
final int row;
final int column;
public Move(final int row, final int column) {
this.row = row;
this.column = column;
}
}
< /code>
package concurrenttictactoe;
public interface PlayerStrategy {
/**
* Computes a new Move.
* @param mark - mark to set in move.
* @param ticTacToe - board to make a move.
* @return a move - combination of x and y coordinates.
*/
Move computeMove(char mark, TicTacToe ticTacToe);
}
< /code>
But every time I run tests, they are exiting with timeoutException after 2 seconds. How can I do this? I have an access to test cases but it might be too much. What is failing and how can I make it exit in 2 seconds?
Подробнее здесь: https://stackoverflow.com/questions/797 ... -tictactoe