程序触发Run-Time Check Failure #2,请求错误排查与代码审查
嘿,作为C++新手能写出这样的游戏框架已经超棒啦!咱们先搞定你遇到的栈损坏问题,再聊聊代码里的其他小细节~
问题根源:数组越界访问破坏栈内存
你碰到的Run-Time Check Failure #2 - Stack around the variable 'userInput' was corrupted,本质是数组越界访问破坏了栈上的其他变量内存:
- 你定义的游戏棋盘是
int gameBoard[4][19],这意味着行索引范围是0~3(共4行),列索引范围是0~18(共19列); - 但在
showGrid和setupGame函数里,你用了for (int y = 0; y <= 4; y++)和for (int x = 0; x <= 19; x++),这会访问到不属于gameBoard的内存(比如gameBoard[4][...]、gameBoard[...][19]); - 栈内存是连续分配的,这些越界访问刚好覆盖了
userInput的栈空间,所以错误提示指向了userInput,但问题根源在棋盘数组的循环边界错误。
修复步骤
1. 修正数组循环边界
把所有循环里的y <= 4改成y < 4,x <= 19改成x < 19,确保只访问数组的合法索引范围。
2. 修正出口位置和陷阱判断逻辑
- 你原来设置出口的代码
gameBoard[4][19] = 2是越界的,改成合法的gameBoard[3][18] = 2(对应棋盘右下角); - 陷阱生成的判断条件里,把
(trapX == 19 && trapY == 4)改成(trapX == 18 && trapY == 3),避免覆盖出口位置。
3. 修复用户输入的逻辑错误
你注释掉的输入判断逻辑有问题:原来的if (userInput != "w" || userInput != "a" || ...)永远为真,应该用&&判断输入是否不在合法列表里。
修正后的完整代码
#include "stdafx.h" #include <cstdlib> #include <string> #include <iostream> #include <time.h> // 用常量定义棋盘尺寸,方便后续修改 const int BOARD_ROWS = 4; const int BOARD_COLS = 19; // START FUNCTION DECLARATION void setupGame(int gameBoard[BOARD_ROWS][BOARD_COLS]); void showGrid(int gameBoard[BOARD_ROWS][BOARD_COLS]); void calculateGame(std::string userInput, int gameBoard[BOARD_ROWS][BOARD_COLS], bool& bGameLoop); // END FUNCTION DECLARATION int main(int argc, char** argv) { std::string userInput = ""; bool bGameLoop = true; int gameBoard[BOARD_ROWS][BOARD_COLS]; setupGame(gameBoard); do { // Windows清屏用cls,Linux/macOS用clear system("cls"); showGrid(gameBoard); // 读取用户输入 userInput = ""; std::cin >> userInput; // 判断输入合法性 if (userInput != "w" && userInput != "a" && userInput != "s" && userInput != "d") { std::cout << "\nPlease use [W][A][S][D] to move <3\n"; system("pause"); // 让用户看到提示后继续 } else { calculateGame(userInput, gameBoard, bGameLoop); } } while (bGameLoop); return 0; } // START FUNCTION /** * 处理游戏核心逻辑(移动、胜负判断等) * @param userInput 用户输入的方向 * @param gameBoard 游戏棋盘数组 * @param bGameLoop 游戏循环标志,用于结束游戏 */ void calculateGame(std::string userInput, int gameBoard[BOARD_ROWS][BOARD_COLS], bool& bGameLoop) { // 先找到玩家当前位置 int playerX = -1, playerY = -1; for (int y = 0; y < BOARD_ROWS; y++) { for (int x = 0; x < BOARD_COLS; x++) { if (gameBoard[y][x] == 1) { playerX = x; playerY = y; break; } } if (playerX != -1) break; } // 计算新位置 int newX = playerX, newY = playerY; if (userInput == "w") newY--; else if (userInput == "s") newY++; else if (userInput == "a") newX--; else if (userInput == "d") newX++; // 检查新位置是否在棋盘内 if (newX < 0 || newX >= BOARD_COLS || newY < 0 || newY >= BOARD_ROWS) { std::cout << "\nYou can't move there!\n"; system("pause"); return; } // 根据新位置内容处理逻辑 switch (gameBoard[newY][newX]) { case 0: // 空位置,移动玩家 gameBoard[playerY][playerX] = 0; gameBoard[newY][newX] = 1; break; case 2: // 到达出口,游戏胜利 gameBoard[playerY][playerX] = 0; gameBoard[newY][newX] = 1; system("cls"); showGrid(gameBoard); std::cout << "\nCongratulations! You escaped the dungeon!\n"; bGameLoop = false; break; case 3: // 踩到陷阱,游戏失败 gameBoard[playerY][playerX] = 0; gameBoard[newY][newX] = 1; system("cls"); showGrid(gameBoard); std::cout << "\nOh no! You stepped on a trap! Game over!\n"; bGameLoop = false; break; } } /** * 打印游戏棋盘 */ void showGrid(int gameBoard[BOARD_ROWS][BOARD_COLS]) { std::cout << "DUNGEON CRAWL V1\n\n"; std::cout << "#--------------------#\n"; std::string cToOut; for (int y = 0; y < BOARD_ROWS; y++) { std::cout << "|"; for (int x = 0; x < BOARD_COLS; x++) { switch (gameBoard[y][x]) { case 0: cToOut = " "; break; case 1: cToOut = "@"; break; case 2: cToOut = "X"; break; case 3: cToOut = "O"; break; default: cToOut = " "; break; }; std::cout << cToOut; } std::cout << "|\n"; } std::cout << "#--------------------#\n"; } /** * 初始化游戏棋盘(玩家、出口、陷阱) */ void setupGame(int gameBoard[BOARD_ROWS][BOARD_COLS]) { // 0 = 空区域,1 = 玩家,2 = 出口,3 = 陷阱 // 初始化棋盘为全空 for (int y = 0; y < BOARD_ROWS; y++) { for (int x = 0; x < BOARD_COLS; x++) { gameBoard[y][x] = 0; } } // 设置玩家初始位置和出口 gameBoard[0][0] = 1; gameBoard[BOARD_ROWS-1][BOARD_COLS-1] = 2; // 生成随机陷阱 int trapX, trapY; bool bAlreadyUse = false; srand(time(NULL)); for (int t = 1; t <= 5; t++) { do { trapX = rand() % BOARD_COLS; trapY = rand() % BOARD_ROWS; bAlreadyUse = (gameBoard[trapY][trapX] == 3); // 避免覆盖玩家初始位置和出口 } while ((trapX == 0 && trapY == 0) || (trapX == BOARD_COLS-1 && trapY == BOARD_ROWS-1) || bAlreadyUse); gameBoard[trapY][trapX] = 3; } } // END FUNCTION
额外小建议
- 用
const定义棋盘尺寸常量(比如代码里的BOARD_ROWS和BOARD_COLS),后续修改棋盘大小更方便,也能避免手动写数字出错; system("cls")和system("pause")是Windows平台特有的,如果要跨平台,可以用读取换行符的方式等待输入,用ANSI转义序列清屏;- 你原来的函数名
calulateGame拼写错误,已经修正为calculateGame啦~
内容的提问来源于stack exchange,提问作者Snow
相关产品推荐
相关产品推荐

