基于Java RMI的双人Connect4游戏checkWin()方法失效问题排查
基于Java RMI的Connect4游戏checkWin()方法故障排查与解决
核心问题分析
- Piece实例匹配失败:Java RMI会对序列化对象进行远程传输,服务器存储的Piece是客户端实例的序列化副本,用
==判断实例相等必然失败——二者是完全独立的对象实例,即使颜色属性一致。 - Null引发的异常/无限循环:
checkWin()中未先判断board[row][col]是否为null就调用getColor(),会触发NullPointerException;同时垂直检查逻辑存在缺陷,当整列无棋子时,row会被循环递增至等于rows,后续若未处理边界会引发逻辑错误,甚至导致循环无法终止。 - checkWin()逻辑低效且易出错:当前
checkWin()需要自行查找棋子位置,不仅效率低,还容易因为空值处理不当引发问题。
具体修复方案
1. 修正Piece匹配逻辑,优先判断非空
永远不要用==比较远程传输的对象实例,改用颜色属性比较,且必须先检查对象是否为null:
// 错误写法 if (this.board[i][col] == currentPlayer.getPiece()) // 正确写法 if (this.board[i][col] != null && this.board[i][col].getColor().equals(currentPlayer.getColor()))
2. 传递准确棋子位置,修复checkWin()垂直检查逻辑
在updateBoard()中记录刚放置棋子的行号,直接传递给checkWin(),避免自行查找带来的错误:
// 修改updateBoard()方法,记录放置位置 @Override public synchronized int updateBoard(int col) throws RemoteException { if(col >= 0 && col < columns){ for(int row = rows - 1;row >=0;row--){ if(this.board[row][col]==null){ this.board[row][col] = currentPlayer.getPiece(); int placedRow = row; // 记录刚放置的行号 player1.updateGui(currentPlayer.getPiece(), col, this.board); player2.updateGui(currentPlayer.getPiece(), col, this.board); currentPlayer.setBoard(this.board); return placedRow; // 返回放置行号,-1表示失败 } } } return -1; }
修改checkWin()方法,基于已知位置检查垂直方向:
@Override public synchronized boolean checkWin(int col, int placedRow) throws RemoteException { Piece currentPiece = currentPlayer.getPiece(); if(currentPiece == null) return false; // 垂直检查:统计当前位置上下的连续同色棋子 int streak = 1; // 向下检查(行号更大的方向,rows-1为棋盘最底部) for(int i = placedRow + 1; i < rows; i++){ if(board[i][col] != null && board[i][col].getColor().equals(currentPiece.getColor())){ streak++; if(streak == 4) return true; } else { break; // 连续被打断,无需继续 } } // 向上检查(行号更小的方向) for(int i = placedRow - 1; i >= 0; i--){ if(board[i][col] != null && board[i][col].getColor().equals(currentPiece.getColor())){ streak++; if(streak == 4) return true; } else { break; } } // 此处添加水平、对角线等其他方向的检查逻辑,同样要先判断非空再比较颜色 // ... return false; }
3. 调整客户端调用逻辑
客户端的actionPerformed中,获取服务器返回的放置行号后再调用checkWin:
// 修改客户端actionPerformed方法 public void actionPerformed(ActionEvent e) { int column = Integer.parseInt(e.getActionCommand()); try { if(myTurn){ int placedRow = server.updateBoard(column); if(placedRow != -1){ if(server.checkWin(column, placedRow)){ server.showWinner(); } server.updateCurrentPlayer(); server.updateTitle(); } } } catch(RemoteException ex){ ex.printStackTrace(); } // ....Rest of code...}
4. 全面排查空值处理
在所有涉及board数组的遍历逻辑中,必须先判断当前位置是否为null,再调用getColor()方法,彻底避免NullPointerException和逻辑错误。
内容的提问来源于stack exchange,提问作者diego alamu
相关产品推荐
相关产品推荐

