C语言潜艇对战游戏循环迭代异常问题排查求助
潜艇击沉游戏循环逻辑输出异常问题修复
问题描述
开发一款类似战舰的变体游戏,目标是在5轮内击沉一艘潜艇。游戏采用10×10坐标系,用户输入坐标后程序需反馈击中、未击中(附带瞄准方位提示)或输入坐标非法。各功能单独运行正常,但加入循环(处理非法输入重输及5轮次数限制)后,程序出现输出异常。
原代码
#include <stdio.h> #include <ctype.h> const char* southNorth(int row, int uRow); const char* eastWest(int col, int uCol); int main(void) { int col, row; char k; int uCol = 3; int uRow = 8; printf("The submarine is hiding at the ocean floor.\n"); printf("You have five depth charges. Try to sing the submarine!\n"); printf("\n"); for (int i = 1; i <=5; i++) { while (1) { printf("Where to try next (col row)? "); scanf("%c %d", &k, &row); if ( isupper(k)) { col = k - ('A'-1); } else if (islower(k)) { col = k - ('a'-1); } if (col >= 1 && col <= 10 && row >= 1 && row <= 10) { break; } printf("Sorry, illegal input!\n"); printf("\n"); } if (southNorth(row, uRow) == NULL && eastWest(col, uCol) == NULL) { printf("Well done, you sank the submarine in %d tries!\n", i); return 0; } else if (southNorth(row, uRow) == NULL && eastWest(col, uCol) != NULL) { printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n", eastWest(col, uCol)); continue; } else if (southNorth(row, uRow) != NULL && eastWest(col, uCol) == NULL) { printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n", southNorth(row, uRow)); continue; } else { printf("Miss. Sonar indicates that the submarine is located %s%s of your current position.\n", southNorth(row, uRow), eastWest(col, uCol)); continue; } } return 0; } const char* southNorth(int row, int uRow) { char *nS; if (row < uRow) { nS = "south"; } else if (row > uRow) { nS = "north"; } else { nS = NULL; } return nS; } const char* eastWest(int col, int uCol) { char *eW; if (col < uCol) { eW = "west"; } else if (col > uCol) { eW = "east"; } else { eW = NULL; } return eW; }
问题分析
- 输入缓冲区残留换行符:
scanf("%c %d", &k, &row)会读取用户输入的字符和数字,但回车产生的换行符会留在缓冲区,下一次调用scanf时会直接读取该换行符作为k的值,触发非法输入提示,导致输出异常。 - col变量未初始化:当输入的字符不是大小写字母时,
col未被赋值,此时判断col >=1 && col <=10会使用内存中的垃圾值,导致非法输入逻辑误判。 - 方位提示格式错误:同时显示南北和东西方位时,两个字符串直接拼接(如
southeast),缺少空格分隔,影响可读性。 - 拼写错误:
Try to sing the submarine!应为Try to sink the submarine!。
修复方案及代码
#include <stdio.h> #include <ctype.h> const char* southNorth(int row, int uRow); const char* eastWest(int col, int uCol); int main(void) { int col = 0, row; // 初始化col为0 char k; int uCol = 3; int uRow = 8; printf("The submarine is hiding at the ocean floor.\n"); printf("You have five depth charges. Try to sink the submarine!\n"); // 修正拼写错误 printf("\n"); for (int i = 1; i <=5; i++) { while (1) { printf("Where to try next (col row)? "); scanf(" %c %d", &k, &row); // %c前添加空格,跳过空白字符(包括换行) col = 0; // 每次输入前重置col if (isupper(k)) { col = k - ('A'-1); } else if (islower(k)) { col = k - ('a'-1); } // 明确判断col是否有效,且row在范围内 if (col >= 1 && col <= 10 && row >= 1 && row <= 10) { break; } printf("Sorry, illegal input!\n"); printf("\n"); } if (southNorth(row, uRow) == NULL && eastWest(col, uCol) == NULL) { printf("Well done, you sank the submarine in %d tries!\n", i); return 0; } else if (southNorth(row, uRow) == NULL && eastWest(col, uCol) != NULL) { printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n", eastWest(col, uCol)); } else if (southNorth(row, uRow) != NULL && eastWest(col, uCol) == NULL) { printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n", southNorth(row, uRow)); } else { // 两个方位之间添加空格 printf("Miss. Sonar indicates that the submarine is located %s %s of your current position.\n", southNorth(row, uRow), eastWest(col, uCol)); } } // 5轮未击沉的提示 printf("Game over! The submarine got away.\n"); return 0; } const char* southNorth(int row, int uRow) { if (row < uRow) { return "south"; } else if (row > uRow) { return "north"; } else { return NULL; } } const char* eastWest(int col, int uCol) { if (col < uCol) { return "west"; } else if (col > uCol) { return "east"; } else { return NULL; } }
修复说明
- 在
scanf(" %c %d", &k, &row)的%c前添加空格,自动跳过输入缓冲区中的空白字符(包括换行、空格等),解决残留换行符导致的异常。 - 初始化
col变量,并在每次输入循环前重置为0,避免垃圾值影响非法输入判断。 - 修改方位提示的输出格式,在南北和方位字符串之间添加空格,提升可读性。
- 修正原文中的拼写错误,并添加5轮未击沉的结束提示,完善游戏逻辑。
内容的提问来源于stack exchange,提问作者Dimitri Mikhalev
相关产品推荐
相关产品推荐

