你好,我现在正在做一个任务,当我必须做一个井字游戏模拟使用并发线程,但它不是很好,当我测试它。我想可能是问题在public interface Player extends Runnable
,因为我不是很精通线程管理。我会感激如果你能帮助我。
这是我的井字游戏界面
public interface TicTacToe {
void setMark(int x, int y, char mark);
char[][] table();
char lastMark();
static TicTacToe buildGame() {
return new TicTacToe() {
char prevMark='O';
char[][] board = new char[][]{{' ', ' ', ' '},
{' ', ' ', ' '},
{' ', ' ', ' '},
};
@Override
public void setMark(int x, int y, char mark) {
if(x>2||y>2||(mark!='X'&&mark!='O')) // if coordinates get outside the table or the mark is not X or O throw exception
throw new IllegalArgumentException();
if (board[x][y]==' ') { // if given place in the table is blank you can place the mark
board[x][y] = mark;
prevMark=mark;
}
else {
throw new IllegalArgumentException();
}
}
@Override
public char[][] table() {
return Arrays.stream(board).map(char[]::clone).toArray(char[][]::new);
}
@Override
public char lastMark() {
return prevMark;
}
};
}
}
这是由称为PlayerStrategy的任务给出的接口
public interface PlayerStrategy {
Move computeMove(char mark, TicTacToe ticTacToe);
}
以下是Move
的定义
public class Move {
final int row;
final int column;
public Move(final int row, final int column) {
this.row = row;
this.column = column;
}
}
这是我正在实现的player
接口
public interface Player extends Runnable{
static boolean wonBoard(char[][] table, char mark){ //check if there is a line of 3 consecutive marks on the board
for(int i=0; i<=2;i++){
if(table[0][i]==mark&&table[1][i]==mark&&table[2][i]==mark)
return true;
if(table[i][0]==mark&&table[i][1]==mark&&table[i][2]==mark)
return true;
}
if (table[0][0] == mark && table[1][1] == mark && table[2][2] == mark)
return true;
return table[0][2] == mark && table[1][1] == mark && table[2][0] == mark;
}
static Player createPlayer(final TicTacToe ticTacToe, final char mark, PlayerStrategy strategy) {
Object foo = new Object();
return new Player() {
@Override
public void run() {
do
{
while (mark == ticTacToe.lastMark())
{ // if the last placed mark is the same as this player's mark wait for the other thread
try {
foo.wait();
} catch (InterruptedException ex) {}
}
if (!wonBoard(ticTacToe.table(), mark))
{
ticTacToe.setMark(strategy.computeMove(mark, ticTacToe).row, strategy.computeMove(mark, ticTacToe).column, mark); // set the mark in place
}
} while (!wonBoard(ticTacToe.table(),mark)); //check if the board has 3 consecutive marks on any line
}
};
}
}
这是任务如何测试它的代码
class GameTest {
@Test
void testPlayers() {
testCase("" +
"XOO\n" +
"XXX\n" +
"O ",
new PlayerStrategy(), new PlayerStrategy());
}
private void testCase(String expected, PlayerStrategy... strategies) {
final TicTacToe ticTacToe = new TicTacToe();
final List<Thread> playerThreads = new ArrayList<>();
final List<Character> marks = Arrays.asList('X', 'O');
for (int i = 0; i < marks.size(); i++) {
Player player = Player.createPlayer(ticTacToe, marks.get(i), strategies[i]);
Thread thread = new Thread(player);
playerThreads.add(thread);
}
playerThreads.forEach(Thread::start);
playerThreads.forEach(silentConsumer(Thread::join));
assertEquals(expected, tableString(ticTacToe.table()));
}
}
问题是,它应该显示这样一些内容
"XOO"
"XXX"
"O "
但它显示了这一点,我不明白为什么
"X "
" X "
" "
我刚看到它也在刮这个
线程“线程-1”java.lang出现异常。非法监控状态异常:当前线程不是java.base/java.lang.Object.wait(本机方法)的所有者,java.base/java.lang.Object.wait(对象. java:338)位于com.epam.rd.autocode.concurrenttictactoe.Player$1.run()
1条答案
按热度按时间gzszwxb41#
嗯,我觉得createPlayer里面这一行不对:
使用两个不同移动的行和列设置标记。尝试:
但我不确定这是否导致了您看到的错误,因为setMark在获得奇怪的坐标时会抛出错误。