You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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("");
    }
}

问题分析

当前代码存在以下核心问题:

  1. moveValid方法仅检查(0,0)这一个位置是否被占用,其他位置完全未处理
  2. 即使检测到位置被占,循环内也未重新验证新输入的坐标是否合法
  3. Player O的移动未调用合法性检查方法,直接执行棋盘修改,导致可以覆盖已有的棋子
  4. 棋盘位置映射使用大量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();
    }
}

修改关键点说明

  1. 坐标映射优化:用计算方式替代大量if判断,获取棋盘实际位置,代码更简洁易维护
  2. 合法性检查重构:getValidMove方法循环验证输入,确保坐标范围合法且位置未被占用,直到用户输入有效坐标
  3. 统一流程:Player X和Player O的移动都通过getValidMove获取合法坐标,再调用placePiece放置棋子,避免直接修改棋盘的错误
  4. 代码复用:新增printBoard辅助方法,减少重复打印棋盘的代码

内容的提问来源于stack exchange,提问作者Dylan Mingoia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:05:56