C++扫雷游戏改造问题:已选坐标重复判定错误求解
扫雷游戏逻辑修正方案
背景与问题
我正在学习C++,参考了一个基于多维数组的战舰游戏示例(代码如下),尝试将其改造成扫雷游戏。目前代码可运行,但存在逻辑问题:选中安全坐标(值为true)后,代码会将其设为false,若再次选择该坐标,会被判定为踩雷导致游戏结束。
原战舰游戏示例代码
#include <iostream> using namespace std; int main() { // 用"1"表示有战舰 bool ships[4][4] = { { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 } }; // 记录击中次数和回合数 int hits = 0; int numberOfTurns = 0; // 击中所有4艘战舰前持续游戏 while (hits < 4) { int row, column; cout << "Selecting coordinates\n"; // 输入行号 cout << "Choose a row number between 0 and 3: "; cin >> row; // 输入列号 cout << "Choose a column number between 0 and 3: "; cin >> column; // 检查坐标是否有战舰 if (ships[row][column]) { // 击中后移除战舰(设为0) ships[row][column] = 0; // 增加击中计数 hits++; // 提示击中信息和剩余战舰数 cout << "Hit! " << (4-hits) << " left.\n\n"; } else { // 提示未击中 cout << "Miss\n\n"; } // 统计回合数 numberOfTurns++; } cout << "Victory!\n"; cout << "You won in " << numberOfTurns << " turns"; return 0; }
我编写的扫雷游戏代码
#include <iostream> using namespace std; int main() { // 这里用"1"表示安全区域,"0"表示炸弹 bool bombs[4][4] = { { 0, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 } }; // 记录相关统计值 int hits = 0; int misses = 15; int numberOfTurns = 0; while (hits < 1 || misses > 0 ) { int row, column; cout << "Selecting coordinates\n"; cout << "Choose a row number between 0 and 3: "; cin >> row; cout << "Choose a column number between 0 and 3: "; cin >> column; if (bombs[row][column]) { // 选中安全区域后设为0 bombs[row][column] = 0; cout << "Good Job!" << (misses-1) << " left.\n\n" ; if (misses-1==0) { cout<< "Victory!"; break; } } else { cout << "Ooops! You found a bomb! \n\n" ; break; } misses--; numberOfTurns++; } cout << "You survived " << numberOfTurns << " turns"; return 0; }
问题分析与解决
问题核心在于用同一个数组同时存储炸弹位置和已访问状态,导致安全区域被点击后被标记为false,再次点击时会被误判为炸弹。
解决办法是新增一个独立的visited二维数组,专门记录哪些格子已经被点击过,不修改原炸弹数组的状态:
修正后的扫雷代码
#include <iostream> using namespace std; int main() { // 炸弹数组:0表示炸弹,1表示安全区域 bool bombs[4][4] = { { 0, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 } }; // 新增已访问数组:初始全为false,标记格子是否被点击过 bool visited[4][4] = {false}; int safeCells = 15; // 总安全区域数量 int numberOfTurns = 0; // 所有安全区域都被选中则胜利 while (safeCells > 0) { int row, column; cout << "Selecting coordinates\n"; cout << "Choose a row number between 0 and 3: "; cin >> row; cout << "Choose a column number between 0 and 3: "; cin >> column; // 先判断是否已访问过该格子 if (visited[row][column]) { cout << "You already clicked this cell! Try another one.\n\n"; continue; // 跳过本次循环,重新输入 } // 标记为已访问 visited[row][column] = true; numberOfTurns++; // 判断是否踩中炸弹 if (!bombs[row][column]) { cout << "Ooops! You found a bomb! Game over.\n\n"; break; } // 选中安全区域 safeCells--; cout << "Good Job! " << safeCells << " safe cells left.\n\n"; // 所有安全区域都已选中,胜利 if (safeCells == 0) { cout << "Victory! You cleared all safe cells.\n"; } } cout << "You survived " << numberOfTurns << " turns"; return 0; }
关键修改点
- 新增
visited[4][4]数组,独立记录已点击的格子,避免修改炸弹数组的原始状态 - 每次输入坐标后先检查是否已访问,若已访问则提示并重新输入
- 炸弹数组仅用于判断是否为炸弹,不再被修改,彻底区分了"炸弹位置"和"已访问状态"两个逻辑
内容的提问来源于stack exchange,提问作者G S Gekkosera
相关产品推荐
相关产品推荐

