C语言实现100囚徒谜题代码运行异常排查
10个盒子版本囚徒谜题模拟程序错误排查
若你已了解100囚徒谜题的规则,可直接跳过规则说明查看问题内容
谜题规则说明
100囚徒谜题核心规则:
- 所有囚徒依次单独进入房间,房间内按顺序摆放编号1到100的盒子,盒内随机放置印着1到100数字的纸条
- 每名囚徒对应1到100的唯一编号,最多有50次开盒机会,需要找到印着自身编号的纸条
- 所有囚徒都找到对应纸条则全部获释,任意一人失败则全体受罚
该谜题有基于环遍历的最优策略,能把成功率提升到30%以上,但本次问题和策略验证无关:提问者写了一个简化版模拟(10个盒子,每名囚徒最多5次开盒机会),运行后输出逻辑完全混乱,无法定位问题。
问题代码
#include <stdio.h> #include <stdlib.h> int main() { int i, j = 0, k = 0, counter = 0; int boxes[10]; int boxEntered; for (i = 0; i <= 10; i++) \ numbering the array boxes[i] = i; for (i = 0; i <= 10; i++) { int temp = boxes[i]; int randomIndex = (rand() % 10); \ shuffling the boxes to put random numbers boxes[i] = boxes[randomIndex]; boxes[randomIndex] = temp; } for (i = 0; i <= 10; i++) { printf("%d : (%d)\n", boxes[i], i); \ print the boxes randomized and their index ordered } printf("You only have 5 tries!\n"); while (k != 5) { while (j < 10) { printf("Pick a box number between 0 and 10 (You are number %d)\n",counter); scanf("%d",&boxEntered); if (boxes[boxEntered] == boxes[counter]) { printf("\nYou succeded, PROCEED TO NEXT PRISONER\n"); j++; \ go to the next iteration k = 0; \ set tries back to 0 counter++; } else printf("Try again\nThe box you entered had number %d\n",boxes[boxEntered]); k++; if (k == 5) { \ if player prisoner fails 5 times you break the loop break; } } } if (counter == 10) { \ if last prisoner was reached successfully then game is won printf("You are freed!"); } else { printf("You are going back heheheheheh!\n") } return 0; }
运行异常截图

错误点逐一说明
- 数组越界:定义的
boxes[10]合法下标范围是0~9,但所有遍历循环都写了i <= 10,会访问不属于数组的boxes[10]内存,属于未定义行为,这是输出混乱的核心原因。 - 注释语法错误:C语言单行注释必须用
//,代码里全部用了反斜杠\,反斜杠是行接续符不是注释,会直接导致编译异常或逻辑错乱。 - 随机数逻辑缺失:没有调用
srand()设置随机数种子,每次运行程序生成的盒子排列完全一致;现有洗牌逻辑遍历范围越界,且交换逻辑无法生成均匀随机的排列。 - 成功判断逻辑错误:囚徒需要找的是和自身编号相等的纸条,正确判断条件应该是
boxes[boxEntered] == counter,原代码写的boxes[boxEntered] == boxes[counter]逻辑完全错误。 - 计数逻辑混乱:
j变量完全多余,counter本身就是当前囚徒编号;尝试次数k的重置、循环跳出逻辑错误,囚徒失败后没有直接终止整个游戏,会出现无效循环。 - 基础语法错误:最后一个
printf语句末尾缺少分号,会直接导致编译失败。 - 缺少输入校验:没有判断用户输入的盒子编号是否在0~9的合法范围内,输入非法值会直接触发数组越界。
修正后可运行代码
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int i, k, counter = 0; int boxes[10]; int boxEntered; int success = 1; // 初始化数组 for (i = 0; i < 10; i++) boxes[i] = i; // 设置随机数种子,费雪耶茨洗牌保证随机均匀 srand((unsigned int)time(NULL)); for (i = 9; i > 0; i--) { int randomIndex = rand() % (i+1); int temp = boxes[i]; boxes[i] = boxes[randomIndex]; boxes[randomIndex] = temp; } // 打印盒子排列(测试用,正式批量模拟可以注释掉) for (i = 0; i < 10; i++) { printf("盒子%d 内的数字:%d\n", i, boxes[i]); } printf("每名囚徒最多有5次开盒机会\n"); // 逐个囚徒入场尝试 for (counter = 0; counter < 10; counter++) { k = 0; int found = 0; printf("\n===== 现在是编号%d的囚徒入场 =====\n", counter); while (k < 5) { printf("请输入要打开的盒子编号(0-9):"); scanf("%d", &boxEntered); // 输入合法性校验 if (boxEntered <0 || boxEntered >=10) { printf("输入非法,请输入0到9之间的数字\n"); continue; } k++; if (boxes[boxEntered] == counter) { printf("恭喜找到自己的编号,剩余尝试次数:%d\n", 5 -k); found = 1; break; } else { printf("未找到,该盒子内数字为%d,已尝试次数:%d\n", boxes[boxEntered], k); } } if (!found) { printf("编号%d的囚徒用完5次机会未找到编号,全体失败!\n", counter); success = 0; break; } } if (success) { printf("\n所有囚徒都找到自己的编号,全部获释!\n"); } else { printf("\n有囚徒失败,全体受罚!\n"); } return 0; }
内容的提问来源于stack exchange,提问作者Younis
相关产品推荐
相关产品推荐

