C#开发井字棋游戏时如何避免玩家落子覆盖已有棋子?
问题根因
- 之前的修改仅覆盖了(1,1)对应第一个格子的空位校验,其余8个落子位置没有任何判断,直接赋值覆盖原有棋子
- Main方法中玩家切换逻辑存在严重错误:每次循环都将player变量初始化为2,随后直接判定player==2改为1,导致全程只有玩家1(X)可以落子
- 没有落子失败的重试逻辑,哪怕校验到位置被占用,依然会消耗当前回合、切换玩家,不符合游戏规则
修复方案
第一步:修改XorO方法,增加全局空位校验并返回落子结果
将方法返回值改为bool,落子成功返回true,位置已被占用返回false,同时简化坐标到数组下标的转换逻辑,无需重复写9个判断:
private static bool XorO(int player, int[] input) { // 坐标转数组下标公式:(行-1)*3 + (列-1) int index = (input[0] - 1) * 3 + (input[1] - 1); // 全局空位校验,只要不是空格就判定为已占用 if (board[index] != ' ') { Console.WriteLine("该位置已被占用,请重新选择!"); return false; } // 落子逻辑 playerSignature = player == 1 ? 'X' : 'O'; board[index] = playerSignature; return true; }
第二步:修复Main方法的玩家切换和落子重试逻辑
把玩家变量移到循环外部,落子失败时直接重试,不切换玩家、不增加回合数:
public static void Main() { Introduction(); // 玩家变量移到循环外部,初始为玩家1先手 int player = 1; while(true) { bool isrow = false; bool iscol = false; int row = 0; int col = 0; while (!isrow) { Console.WriteLine($"玩家{player},请选择行号(1-3): "); try { row = Convert.ToInt32(Console.ReadLine()); } catch { Console.WriteLine("请输入1-3之间的数字。"); } if (row is >=1 and <=3) { isrow = true; } else { Console.WriteLine("\n无效行号!"); } } while (!iscol) { Console.WriteLine($"玩家{player},请选择列号(1-3): "); try { col = Convert.ToInt32(Console.ReadLine()); } catch { Console.WriteLine("请输入1-3之间的数字。"); } if (col is >=1 and <=3) { iscol = true; } else { Console.WriteLine("\n无效列号!"); } } int[] input = { row, col }; // 落子失败直接进入下一轮循环,不切换玩家不计数 if(!XorO(player, input)) { continue; } DrawBoard(board); turns++; // 原有胜负校验逻辑保持不变 CheckForDiagonal(); CheckForVertical(); CheckForHorizontal(); // 简化平局判断:回合数到9说明棋盘已满 if (turns == 9) { Draw(); } // 落子成功后切换玩家 player = player == 1 ? 2 : 1; } }
第三步:优化平局判断逻辑
原有平局判断逻辑冗余,turns累计到9时棋盘已经被占满,无需额外判断所有格子都是玩家标识,直接触发平局即可。
内容的提问来源于stack exchange,提问作者morloq
相关产品推荐
相关产品推荐

