1.约瑟夫生死者小游戏
(题目来自菜鸟教程)
30 个人在一条船上,超载,需要 15 人下船。
于是人们排成一队,排队的位置即为他们的编号。
报数,从 1 开始,数到 9 的人下船。
如此循环,直到船上仅剩 15 人为止,问都有哪些编号的人下船了呢?
2. 写BUG
2020年3月25日
今天在学C的时候,绞尽脑汁想到了这方法,然后又把脑汁发酵,也没查出来这BUG出在哪里,一上午就这样过去了
#include<stdio.h> //by 银河MIKU
/*30 个人在一条船上,超载,需要 15 人下船。
于是人们排成一队,排队的位置即为他们的编号。
报数,从 1 开始,数到 9 的人下船。
如此循环,直到船上仅剩 15 人为止,问都有哪些编号的人下船了呢?
*/
int main() {
int Number[30], n, m=0, count=1;
//给这30个排队的人设置初始编号
for(n=0;n<30;n++){ //从Number[0]到Number[29]一共30个编号
Number[n] = n+1; //这些人的编号: 从1到30
}
printf("上船的人分别是:\n");
n = 0; //用n来限制数组Number[]标号的溢出
while (1) {
if (count % 9 == 0){ //count为下船标志数,标志数为9的倍数则
if (n < 30) { //对数组的循环,使之被限制在0~29之间
if (Number[n] != 0) { //检测数组值是否为零
printf("编号%d\n", Number[n]);//打印数组值,即为下船的人
Number[n] = 0; //将 已下船的数组 值置零
m++; //人数标志m,随下船人数自增
if (m == 15) {//判断上船是否足够15人
break; //跳出循环
}
}
else //若数组值为零,说明此人已下船,则多记数一次
n++;//目的是去除已下船的人对count计数的影响
}
else //若数组标号n超过范围,则n-=30使其回到循环
n = n - 30;
}
else;
count++; //下船标志数自增,无限递增
n++; //数组标号递增,随count增加
}
return 0;
}
运行结果
很明显,只有9,18,27 是对的,到第四个输出编号就直接异常了。
3.朋友帮忙改过后的
#include<stdio.h> // by银河miku
/*30 个人在一条船上,超载,需要 15 人下船。
于是人们排成一队,排队的位置即为他们的编号。
报数,从 1 开始,数到 9 的人下船。
如此循环,直到船上仅剩 15 人为止,问都有哪些编号的人下船了呢?
*/
int main() {
int Number[30], n, m = 0, count = 1;
//给这30个排队的人设置初始编号
for (n = 0; n < 30; n++) {
Number[n] = n + 1;
// printf("%d\n", Number[n]);
}
printf("上船的人分别是:\n");
n = 0;
while (1) {
if (n < 30) {//------------------改--------------------------if嵌套对调
if (count % 9 == 0) {//-----------------改---------------------------if嵌套对调
if (Number[n] != 0) {
printf("编号%d\n", Number[n]);
Number[n] = 0;
m++; //判断是否足够15人
if (m == 15) {
break;
}
}
else
n++;
}
}
else {
n = n - 30;
}
count++;
n++;
}
return 0;
}
运行结果:
正确 。
有空补上图解
此解法也是错误的。(2023年10月28日)
4.今日总结反思
- if的嵌套
- 不要再忘记写头文件了
- 标志数很好用
- 多画图,空想太难了
- break可以跳出循环
时隔三年半,收到后台消息,看到评论说我写错了,才回起来还有这么一回事,想想当年的脑子就像是一团浆糊,现在努力不变成浆糊吧。
上面的第二种算法也是错的,评论给到的算法是正确的,考虑到了报数时跳过0值(下船的人留下的位置)的问题,感谢朋友的评论指正~
在此附上CSDN网友2301_80451186
修改后的代码
#include<stdio.h>
int main()
{
int Number[30] = { 0 };
for (int i = 0; i < 30; i++) //给这30个排队的人设置初始编号
{
Number[i] = i + 1;
}
int n = 0,m = 0, count = 1;//定义循环中的变量
while (1)
{
if (n < 30)
{
if (count % 9 == 0)
{
if (Number[n] != 0)//防止巧合
{
printf("下船的人是%d\n", Number[n]);
Number[n] = 0;//剔除下船的人
m++; //判断是否足够15人
if (m == 15)
{
break;
}
}
}
}
else
{
n = n - 30;//构成闭环
}
count++;
n++;
if (Number[n] == 0)//跳过下船的人
{
count--;
}
}
return 0;
}
正确输出:
下船的人是18
下船的人是27
下船的人是6
下船的人是16
下船的人是26
下船的人是7
下船的人是19
下船的人是30
下船的人是12
下船的人是24
下船的人是8
下船的人是22
下船的人是5
下船的人是23```