Java井字棋开发:如何阻止玩家选择已被占用的坐标?
井字棋游戏:禁止玩家移动到已占据位置的实现方案
问题描述
我正在开发一款类似井字棋的游戏,两名玩家(playerX和playerO)轮流选择坐标放置'X'或'O'。当前测试时发现,当playerX先输入坐标(0,0)后,playerO再输入(0,0)会直接把'X'替换成'O',需要实现玩家无法移动到其他玩家已占据的位置。
当前代码
Methods类(负责合法性检查与棋盘修改)
import java.util.*; public class Methods { //Scanner in = new Scanner(System.in); // responsible for input // checks if the move is valid(if not it makes the player input moves until it is valid) public static void moveValid(int row ,int col,char[][] board) { Scanner in = new Scanner(System.in); // checks if a postion is taken boolean taken = false; for(int r = 0; r < board.length;r++) { for(int c = 0;c < board[row].length;c++) { if((row ==0)&& (col==0)) { if((board[0][1] == 'O') || (board[0][1] =='X')) { taken = true; } } } } if(((col >2 ) || (row > 2))|| taken) { boolean right = false; while(right == false) { System.out.println("Invalid move, enter a new move."); System.out.println("X enter the colum for your move (0-2):"); int newCol = in.nextInt(); System.out.println("X enter the row for your move(0-2):"); int newRow = in.nextInt(); System.out.println(""); if(((newCol <= 2) && (newRow <= 2)) || taken == false ) { right = true; } } } } // positioning of the pieces public static void change(char[][] board,char player, int row, int col) { if((row ==0) && (col ==0)) { board[0][1] = player; } if((row ==0) && (col ==1)) { board[0][5] = player; } if((row ==0) && (col ==2)) { board[0][9] = player; } if((row ==1) && (col ==0)) { board[2][1] = player; } if((row ==1) && (col ==1)) { board[2][5] = player; } if((row ==1) && (col ==2)) { board[2][9] = player; } if((row ==2) && (col ==0)) { board[4][1] = player; } if((row ==2) && (col ==1)) { board[4][5] = player; } if((row ==2) && (col ==2)) { board[4][9] = player; } } }
Main类(主程序入口)
import java.util.*; public class Main { public static void main(String[] args) { Scanner kb = new Scanner(System.in); // creating the board and pieces char [][] array = { {' ',' ',' ','|',' ',' ',' ','|',' ',' ',' '}, {'-','-','-','-','-','-','-','-','-','-','-'}, {' ',' ',' ','|',' ',' ',' ','|',' ',' ',' '}, {'-','-','-','-','-','-','-','-','-','-','-'}, {' ',' ',' ','|',' ',' ',' ','|',' ',' ',' '} }; char playerX = 'X'; char playerO ='O'; // positions char posOne = array[0][1]; char posTwo = array[0][5]; char posThree = array[0][9]; char posFour = array[1][1]; char posFive = array[1][5]; char posSix = array[1][9]; char posSeven = array[2][1]; char posEight = array[2][5]; char posNine = array[2][9]; boolean done = false; for(int row =0; row < array.length;row++) { System.out.println(array[row]); } System.out.println(""); // first move System.out.println("X enter the column for your move (0-2):"); int columnLocation = kb.nextInt(); System.out.println("X enter the row for your move (0-2):"); int rowLocation = kb.nextInt(); System.out.println(""); /* // if the first move is invalid if((columnLocation >2 ) || (rowLocation > 2)) { boolean right = false; while(right == false) { System.out.println("Invalid move, enter a new move."); System.out.println("X enter the colum for your move (0-2):"); columnLocation = kb.nextInt(); System.out.println("X enter the row for your move(0-2):"); rowLocation = kb.nextInt(); System.out.println(""); if((columnLocation <= 2) && (rowLocation <= 2)) { right = true; } } } */ Methods.moveValid(rowLocation,columnLocation,array); Methods.change(array,playerX,rowLocation,columnLocation); for(int row =0; row < array.length;row++) { System.out.println(array[row]); } System.out.println(""); // first O System.out.println("X enter the column for your move (0-2):"); columnLocation = kb.nextInt(); System.out.println("X enter the row for your move (0-2):"); rowLocation = kb.nextInt(); System.out.println(""); if((columnLocation >2 ) || (rowLocation > 2)) { boolean right = false; while(right == false) { System.out.println("Invalid move, enter a new move."); System.out.println("X enter the colum for your move (0-2):"); columnLocation = kb.nextInt(); System.out.println("X enter the row for your move(0-2):"); rowLocation = kb.nextInt(); System.out.println(""); if((columnLocation <= 2) && (rowLocation <= 2)) { right = true; } } } Methods.change(array,playerO,rowLocation,columnLocation); for(int row =0; row < array.length;row++) { System.out.println(array[row]); } System.out.println(""); } }
问题分析
当前代码存在以下核心问题:
moveValid方法仅检查(0,0)这一个位置是否被占用,其他位置完全未处理- 即使检测到位置被占,循环内也未重新验证新输入的坐标是否合法
- Player O的移动未调用合法性检查方法,直接执行棋盘修改,导致可以覆盖已有的棋子
- 棋盘位置映射使用大量
if判断,代码冗余且易出错
解决方案
修改后的Methods类
import java.util.Scanner; public class Methods { // 根据输入的(row, col)计算棋盘上的实际位置坐标 private static int[] getActualBoardPosition(int row, int col) { // 井字棋行对应棋盘数组的0、2、4行(间隔分隔线) int boardRow = row * 2; // 井字棋列对应棋盘数组的1、5、9列(间隔|符号) int boardCol = col * 4 + 1; return new int[]{boardRow, boardCol}; } // 获取玩家的合法移动坐标,循环直到输入符合要求 public static int[] getValidMove(char[][] board, Scanner scanner, String player) { while (true) { System.out.printf("%s enter the column for your move (0-2):%n", player); int col = scanner.nextInt(); System.out.printf("%s enter the row for your move (0-2):%n", player); int row = scanner.nextInt(); System.out.println(); // 检查坐标范围是否在0-2之间 if (row < 0 || row > 2 || col < 0 || col > 2) { System.out.println("无效移动:坐标必须在0-2之间,请重新输入。"); continue; } // 检查目标位置是否已被占据 int[] pos = getActualBoardPosition(row, col); char currentPiece = board[pos[0]][pos[1]]; if (currentPiece == 'X' || currentPiece == 'O') { System.out.println("无效移动:该位置已被占据,请重新输入。"); continue; } // 输入合法,返回坐标 return new int[]{row, col}; } } // 将棋子放置到棋盘的对应位置 public static void placePiece(char[][] board, char player, int row, int col) { int[] pos = getActualBoardPosition(row, col); board[pos[0]][pos[1]] = player; } }
修改后的Main类
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner kb = new Scanner(System.in); // 初始化棋盘 char[][] array = { {' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '}, {'-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-'}, {' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '}, {'-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-'}, {' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '} }; char playerX = 'X'; char playerO = 'O'; // 打印初始棋盘 printBoard(array); // Player X 回合:获取合法坐标并放置棋子 int[] xMove = Methods.getValidMove(array, kb, "X"); Methods.placePiece(array, playerX, xMove[0], xMove[1]); printBoard(array); // Player O 回合:获取合法坐标并放置棋子 int[] oMove = Methods.getValidMove(array, kb, "O"); Methods.placePiece(array, playerO, oMove[0], oMove[1]); printBoard(array); } // 辅助方法:打印棋盘,减少重复代码 private static void printBoard(char[][] board) { for (char[] row : board) { System.out.println(row); } System.out.println(); } }
修改关键点说明
- 坐标映射优化:用计算方式替代大量
if判断,获取棋盘实际位置,代码更简洁易维护 - 合法性检查重构:
getValidMove方法循环验证输入,确保坐标范围合法且位置未被占用,直到用户输入有效坐标 - 统一流程:Player X和Player O的移动都通过
getValidMove获取合法坐标,再调用placePiece放置棋子,避免直接修改棋盘的错误 - 代码复用:新增
printBoard辅助方法,减少重复打印棋盘的代码
内容的提问来源于stack exchange,提问作者Dylan Mingoia
相关产品推荐
相关产品推荐

