C语言井字棋游戏循环异常及棋盘打印正确性排查请求
井字棋程序问题分析与修复
核心问题排查
1. 玩家名称输入错误
- 原代码用
scanf("%c", n1)读取玩家名称,%c仅能读取单个字符,还会捕获输入后的换行符,导致第二个玩家名称直接被赋值为换行符,后续逻辑完全混乱。 - 修正:改用
%s读取字符串,配合scanf(" %s", n1)(前置空格跳过换行等空白字符)。
2. 棋盘打印逻辑错误
functionboard函数内重新定义了局部space数组,覆盖全局棋盘数组,导致永远打印初始状态,无法显示玩家落子后的变化。- 修正:删除局部
space数组定义,直接使用全局数组;同时补全printf的格式占位符,比如将printf(" ", space[0][0], ...)改为printf(" %c | %c | %c \n", space[0][0], space[0][1], space[0][2]);,让棋盘内容正常输出。
3. 输入处理错误
scanf("&d", &dight)格式符错误,应为scanf("%d", &dight);存在拼写错误prinf,需改为printf。- 玩家提示语句
printf(n1, "please enter")格式错误,正确写法是printf("%s, please enter your move (1-9): ", n1);。 functionOne中dight的范围判断逻辑混乱:多个独立if后接else if,导致dight为1-9时该分支不会触发;若dight未被正确赋值(比如输入失败),row/column会是全局未初始化的随机值,访问棋盘时触发"There is no empty space!"提示。
4. 递归调用导致无限循环
functionOne末尾无条件递归自身,无论输入是否有效都会无限递归,既导致栈溢出,又会在错误输入时反复触发错误提示。- 修正:去掉递归,改用循环处理输入直到有效。
5. 胜负判断逻辑优化
functionDraw命名不准确,实际是判断胜负和平局,可改为checkGameStatus;当前逻辑中tie变量的全局依赖可以优化,整合到返回逻辑中。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <stdbool.h> char space[3][3] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}, }; int row; int column; char token = 'x'; bool tie = false; char n1[256]; char n2[256]; void functionboard() { printf(" | | \n"); printf(" %c | %c | %c \n", space[0][0], space[0][1], space[0][2]); printf("________|________|________\n"); printf(" | | \n"); printf(" %c | %c | %c \n", space[1][0], space[1][1], space[1][2]); printf("________|________|________\n"); printf(" | | \n"); printf(" %c | %c | %c \n", space[2][0], space[2][1], space[2][2]); printf(" | | \n"); } void functionOne() { int dight; bool validInput = false; while (!validInput) { if (token == 'x') { printf("%s, please enter your move (1-9): ", n1); if (scanf("%d", &dight) != 1) { printf("Invalid input! Please enter a number.\n"); while (getchar() != '\n'); continue; } } else { printf("%s, please enter your move (1-9): ", n2); if (scanf("%d", &dight) != 1) { printf("Invalid input! Please enter a number.\n"); while (getchar() != '\n'); continue; } } row = -1; column = -1; if (dight >= 1 && dight <= 9) { row = (dight - 1) / 3; column = (dight - 1) % 3; if (space[row][column] != 'x' && space[row][column] != '0') { if (token == 'x') { space[row][column] = 'x'; token = '0'; } else { space[row][column] = '0'; token = 'x'; } validInput = true; } else { printf("There is no empty space! Try again.\n"); functionboard(); } } else { printf("Invalid !!! Please enter a number between 1 and 9.\n"); functionboard(); } } } bool checkGameStatus() { for (int i = 0; i < 3; i++) { if ((space[i][0] == space[i][1] && space[i][0] == space[i][2]) || (space[0][i] == space[1][i] && space[0][i] == space[2][i])) { return true; } } if ((space[0][0] == space[1][1] && space[1][1] == space[2][2]) || (space[0][2] == space[1][1] && space[1][1] == space[2][0])) { return true; } tie = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (space[i][j] != 'x' && space[i][j] != '0') { tie = false; return false; } } } return true; } int main() { printf("Enter the name of the first player : \n"); scanf(" %s", n1); printf("Enter the name of the second player : \n"); scanf(" %s", n2); printf("%s is player1, so you will play first (using 'x')\n", n1); printf("%s is player2, so you will play second (using '0')\n", n2); while (!checkGameStatus()) { functionboard(); functionOne(); } functionboard(); if (!tie) { if (token == 'x') { printf("%s Wins!!\n", n2); } else { printf("%s Wins!!\n", n1); } } else { printf("It's a draw!!\n"); } return 0; }
说明
- 修复了玩家名称输入问题,支持读取完整字符串
- 棋盘打印现在会正确显示玩家落子状态
- 增加了输入有效性校验,包括非数字输入的处理
- 移除无限递归,改用循环处理输入直到有效
- 优化了胜负和平局判断逻辑,游戏结束时打印最终棋盘
内容的提问来源于stack exchange,提问作者Muhammad Hozaifa
相关产品推荐
相关产品推荐

