java 并发线程井字游戏模拟无法正常工作

bnl4lu3b  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(118)

你好,我现在正在做一个任务,当我必须做一个井字游戏模拟使用并发线程,但它不是很好,当我测试它。我想可能是问题在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()

gzszwxb4

gzszwxb41#

嗯,我觉得createPlayer里面这一行不对:

ticTacToe.setMark(strategy.computeMove(mark, ticTacToe).row, strategy.computeMove(mark, ticTacToe).column, mark); // set the mark in place

使用两个不同移动的行和列设置标记。尝试:

Move move = strategy.computeMove(mark, ticTacToe);
ticTacToe.setMark(move.row, move.column, mark);

但我不确定这是否导致了您看到的错误,因为setMark在获得奇怪的坐标时会抛出错误。

相关问题