C语言终端游戏角色与L型障碍物均无法移动问题排查
C语言游戏故障排查
故障描述
- 预期功能:
- 自带标题界面,支持退出或开始游戏
- 开始游戏后渲染游戏字符数组,玩家可通过
a/d/s按键控制角色O左移、右移、下移 - 每向下移动一行获得积分,踩到
P点位获得额外积分 - 玩家到达y坐标202且积分为正则获胜,渲染恭喜界面;积分变为负值(踩到
#点位或碰到每0.5秒下移的L型墙)则失败,渲染失败界面并支持退出或重开
- 故障现象:玩家控制的角色
O和L型障碍物完全无法移动
问题代码
#include <stdlib.h> #include <stdio.h> #include <time.h> #include <fcntl.h> #include <unistd.h> char quickchar(float delay); void render(); void titleRender(); void renderLoss(); void renderWin(); int score(); char titlescreen[20][59] = { }; char diffdiff[20][46] = { (Grid removed due to char limit) }; char gameover[20][50] = { (Grid removed due to char limit) }; char gameboard[203][26] = { (Grid removed due to char limit) }; int playerx; int playery; int pts; void entryRender(); void gameRender(); int main() { int input; char replay; int lx; int ly; char walkin; int gaming; char titlechoice; int diff; int running; lx = 0; ly = 0; running = 1; playerx = 13; playery = 5; pts = 25; gaming = 0; while (gaming == 0) { titleRender(); printf("\033[1;32m"); printf("\nPress 'p' to play or 'x' to exit!"); printf("\033[0m"); scanf(" %c", &titlechoice); if (titlechoice == 'p') { gaming += 4; } if (titlechoice == 'x') { return 0; } } while (gaming == 4) { system("stty -echo raw"); render(); printf("\033[1;35m"); printf("Choose a direction: s/Down, a/Left, d/Right.\n\r"); printf("\033[0m"); walkin = quickchar(0.5); scanf("%c", &walkin); //obj behaviour if (walkin == 's' && gameboard[playery +1][playerx] != '#' && gameboard[playery + 1][playerx] != '+' && gameboard[playery + 1][playerx] != '|' && gameboard[playery + 1][playerx] != '-') { playery++; pts += 5; if (gameboard[playery + 1][playerx] == '#') { pts -= 25; } if (gameboard[playery + 1][playerx] == 'P') { printf("Points increased!\n\r"); pts += 50; gameboard[playery + 1][playerx] = '_'; } } else if (walkin == 'a' && gameboard[playery][playerx - 1] != '#' && gameboard[playery][playerx - 1] != '+' && gameboard[playery][playerx - 1] != '|' && gameboard[playery][playerx - 1] != '-') { playerx--; if (gameboard[playery][playerx - 1] == '#') { pts -= 25; } if (gameboard[playery][playerx - 1] == 'P') { printf("Points increased!\n\r"); pts += 50; gameboard[playery][playerx - 1] = '_'; } } else if (walkin == 'd' && gameboard[playery][playerx + 1] != '#' && gameboard[playery][playerx + 1] != '+' && gameboard[playery][playerx + 1] != '|' && gameboard[playery][playerx + 1] != '-') { playerx++; if (gameboard[playery][playerx + 1] == '#') { pts -= 25; } if (gameboard[playery + 1][playerx] == 'P') { printf("Points increased!\n\r"); pts += 50; gameboard[playery][playerx + 1] = '_'; } } if (walkin == 'a' || walkin == 's' || walkin == 'd' || walkin != 'a' || walkin != ' ' || walkin != 'd' ) { for (ly = 0; ly = 202; ly++) { for (lx = 1; lx = 25; lx++) { gameboard[ly][lx] = 'L'; } } } if (pts <= 0) { system("clear"); renderLoss(); scanf("%c", &replay); if (replay == 'Y') { gaming = 3; } if (replay == 'N') { gaming = 5; } } if (playery == 202) { renderWin(); printf(""); printf("Congrats! You got a score of %d !", pts); printf(""); scanf("%c", &replay); if (replay == 'Y') { gaming = 4; } if (replay == 'N') { gaming = 5; } } //player postion == 203y, then congrta screen //ask player to set gaming to 4(replay) or none (exit program) } system("stty echo -raw"); return 0; } void render() { int y,x,k; system("clear"); printf("\033[01;33m"); printf("||POINTS: %d||\r\n", pts); printf("\033[0m"); for (y = 0; y < 203; y++) { for (x = 0; x < 26; x++) { if (y == playery && x == playerx) { printf("\033[0;32m"); printf("O"); printf("\033[0m"); } else { printf("\033[1;36m"); printf("%c", gameboard[y][x]); printf("\033[0m"); } } printf("\r\n"); } } void titleRender() { int y, x; system("clear"); for (y = 0; y < 20; y++) { for (x = 0; x < 59; x++) { printf("\033[0;32m"); printf(" %c", titlescreen[y][x]); printf("\033[0m"); } printf("\r\n"); } } void renderLoss() { int y, x; system("clear"); for (y = 0; y < 20; y++) { for (x = 0; x < 50; x++) { printf("\033[0;31m"); printf(" %c", gameover[y][x]); printf("\033[0m"); } printf("\r\n"); } } void renderWin() { int y, x; system("clear"); for (y = 0; y < 20; y++) { for (x = 0; x < 46; x++) { printf("\033[0;33m"); printf(" %c", diffdiff[y][x]); printf("\033[0m"); } printf("\r\n"); } } char quickchar(float delay) { int flags; char c; usleep((int)(delay*1000000)); flags = fcntl(0, F_GETFL, 0); fcntl(0, F_SETFL, flags | O_NONBLOCK); c = getchar(); fcntl(0, F_SETFL, flags ^ O_NONBLOCK); return c; }
错误排查结果
1. 角色无法移动的核心原因
调用quickchar(0.5)已经读取了一次按键输入,后续又用scanf("%c", &walkin)覆盖了读取结果,导致实际按键输入被丢弃,删掉多余的scanf行即可恢复角色控制。
此外移动判定逻辑存在顺序问题:在判断移动的条件里已经排除了目标点位是#的情况,后续检测踩#扣积分的分支永远不会执行,d键对应的P点位检测还存在坐标写错、引号缺失的语法错误,导致加分逻辑失效。
2. L型障碍物无法移动的核心原因
- 障碍物生成的循环条件写的是赋值操作
ly = 202、lx = 25,而非比较判断ly < 202、lx < 25,直接触发死循环卡住程序 - 外层触发生成L墙的if判断逻辑恒为真,不管输入是什么都会直接把游戏板所有位置覆盖为L,且完全没有写L墙逐行下移的逻辑,自然看不到障碍物正常移动
3. 其他潜在崩溃风险
- 失败界面的
scanf("%c", replay)缺少取地址符&,会触发段错误 renderWin函数原本直接打印数组名而非数组元素diffdiff[y][x],胜利界面会乱码renderLoss函数原本循环y到26,但gameover数组只有20行,会越界访问崩溃
内容的提问来源于stack exchange,提问作者David G.
相关产品推荐
相关产品推荐

