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

C#开发井字棋while循环条件为真仍不退出的问题排查

C#井字棋while循环无法正常退出故障

问题背景

  • 游戏核心逻辑位于包含2个分支的switch语句中,通过Random.Next()随机选择分支执行
  • 设计规则:循环终止判定满足任意一项即可退出,执行winMessage()胜利提示:
    • 游戏结束标记变量gameEnd为true
    • 棋盘占满检测函数AllArrFilledEmptySpace()返回true
    • 检测函数内部已添加gameEnd = true赋值作为兜底逻辑
  • 初始化规则:游戏启动时声明string[]类型board棋盘数组,所有元素填充空格避免null值;AllArrFilledEmptySpace()通过遍历检测数组元素是否为空格,判断9个棋盘位置是否全部被"X"或"O"占满
  • 故障表现:即使手动调整过循环判断条件,且gameEnd已被赋值为true,循环仍无法正常break跳出,无法进入后续胜利提示逻辑

故障相关代码

主运行逻辑

public static string[] board { get; set; }
public static bool gameEnd { get; set; }

public static void Run()
{
    Clear();
    makeArr();
    gameEnd = false;
    ConsoleKey keyPressed;
    ConsoleKeyInfo keyInfo = ReadKey(true);
    keyPressed = keyInfo.Key;
    Random rOdd = new Random();
    int odds = rOdd.Next(0, 2);

    do
    {
        switch (odds)
        {
            case 0:
                while (!gameEnd || !AllArrFilledEmptySpace(board))
                {
                    Clear();
                    printBoard(board);
                    turnO(board);
                    WriteLine($"\n\nAll Blocks filled: {AllArrFilledEmptySpace(board)}, GameEnd variable: {gameEnd}");
                    ReadKey(true);

                    Clear();
                    printBoard(board);
                    turnX(board);
                    WriteLine($"\n\nAll Blocks filled: {AllArrFilledEmptySpace(board)}, GameEnd variable: {gameEnd}");
                    ReadKey(true);
                }
                break;
            case 1:
                while (!gameEnd || !AllArrFilledEmptySpace(board))
                {
                    Clear();
                    printBoard(board);
                    turnO(board);
                    WriteLine($"\n\nAll Blocks filled: {AllArrFilledEmptySpace(board)}, GameEnd variable: {gameEnd}");
                    ReadKey(true);

                    Clear();
                    printBoard(board);
                    turnX(board);
                    WriteLine($"\n\nAll Blocks filled: {AllArrFilledEmptySpace(board)}, GameEnd variable: {gameEnd}");
                    ReadKey(true);
                }
                break;
        }
    } while (!gameEnd) ;

    winMessage();
    ReadKey(true);
}

工具函数逻辑

public static bool AllArrFilledEmptySpace(string[] board)
{
    int count = 0;
    for (int i = 0; i < board.Length; i++)
    {
        if (!board[i].Equals(" "))
        {
            count++;
        }
    }

    if (count == 9)
    {
        gameEnd = true;
        return true;
    }
    return false;
}

public static string[] makeArr()
{
    board = new string[9];
    for (int i = 0; i < board.Length; i++)
    {
        string q = " ";
        board[i] = q;
    }
    return board;
}

根因分析

核心问题是内层while循环的条件逻辑运算符使用错误:

  • 原循环条件为!gameEnd || !AllArrFilledEmptySpace(board),使用逻辑或||的判定规则是:只要两个条件任意一个为真,就持续执行循环。也就是说哪怕gameEnd已经被设为true,只要棋盘还没被占满(!AllArrFilledEmptySpace()返回true),整个循环条件依然为真,循环不会终止,和设计预期完全相反。
  • 预期的循环执行条件应该是:游戏未结束 且 棋盘未被占满,两个条件同时满足时才继续循环,只要任意一个不满足就退出。

额外冗余问题:

  1. switch的两个分支代码完全重复,且随机值odds在do-while循环外赋值,进入循环后不会重新计算,分支选择没有实际作用
  2. 外层嵌套的do-while (!gameEnd)属于冗余逻辑,内层循环修正后退出时gameEnd必然为true,外层循环不会重复触发

修复方案

  1. 将内层两个while循环的条件中逻辑或||替换为逻辑与&&,修正为while (!gameEnd && !AllArrFilledEmptySpace(board))
  2. 可移除冗余的外层do-while循环和重复的switch分支代码,简化逻辑

修复后的核心循环参考:

public static void Run()
{
    Clear();
    makeArr();
    gameEnd = false;
    ReadKey(true);
    Random rOdd = new Random();
    int odds = rOdd.Next(0, 2);
    
    while (!gameEnd && !AllArrFilledEmptySpace(board))
    {
        Clear();
        printBoard(board);
        if (odds == 0) turnO(board);
        else turnX(board);
        if (gameEnd) break;
        WriteLine($"\n\nAll Blocks filled: {AllArrFilledEmptySpace(board)}, GameEnd variable: {gameEnd}");
        ReadKey(true);

        Clear();
        printBoard(board);
        if (odds == 0) turnX(board);
        else turnO(board);
        WriteLine($"\n\nAll Blocks filled: {AllArrFilledEmptySpace(board)}, GameEnd variable: {gameEnd}");
        ReadKey(true);
    }

    winMessage();
    ReadKey(true);
}

注:需要在turnO和turnX方法内部的落子逻辑后增加胜负判定,及时将gameEnd设为true,避免出现一方获胜后依然要等另一方落子才会触发退出的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:06:18