You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免C语言猜数字程序重复猜测已排除的数字?

解决猜数字程序重复猜测已排除数字的问题

嘿,刚学C语言就能写出这样的程序已经很棒了!你遇到的重复猜数字问题,根源在于用随机数的方式没法精准跟踪已经排除的范围——随机数可不会记得之前猜过什么,所以很容易撞已经被排除的数。其实换个思路,用二分查找法来猜数字就完美解决这个问题了,不仅不会重复,还能最快猜到目标数,比随机高效太多!

先说说你现有代码的两个关键问题:

  • 随机数逻辑有问题:你现在的rand()+time(NULL)生成随机数的方式不对,而且每次循环都调用time(NULL)会导致同一秒内的随机数变化不大;更重要的是,随机数不会考虑已经缩小的范围,所以必然会重复猜已经被排除的数。
  • 范围更新错误:当用户说目标数字比当前猜测大(>)时,你把minimum设为numGen,但其实numGen已经被排除了,应该设为numGen + 1;同理,用户说更小(<)时,maximum应该设为numGen - 1,不然会重复猜同一个数。

修改后的代码(用二分查找替代随机)

#include <stdio.h>
// 不需要stdlib.h和time.h了,因为不用随机数啦
int main() {
    int numGen;
    int minimum = 1;
    int maximum = 0;
    char answer;
    char answer2;

    // 获取合法的数值范围
    while(minimum > maximum || minimum == 0){
        printf("Insert range 'min-max'\n");
        scanf("%d-%d", &minimum, &maximum);
        if(minimum <= maximum && minimum > 0) {
            break;
        } else {
            printf("Invalid range\n\n");
        }
    }

    printf("Okay, think of your number in %d-%d!\n", minimum, maximum);

    while(1) {
        // 用二分法取中间值,避免重复猜测
        numGen = minimum + (maximum - minimum) / 2;
        // 防止整数溢出,也可以写成 (minimum + maximum) / 2,但前者更安全
        printf("Is your number: %d? (y/n)\n", numGen);
        scanf(" %c", &answer);

        if(answer == 'y') {
            printf("\nI guessed it! 🎉\n");
            break;
        } else if(answer == 'n') {
            printf("Is it bigger (>), or smaller (<)?\n");
            scanf(" %c", &answer2);

            if(answer2 == '>') {
                // 目标数比当前大,所以当前数可以排除,minimum更新为numGen+1
                minimum = numGen + 1;
            } else if(answer2 == '<') {
                // 目标数比当前小,当前数排除,maximum更新为numGen-1
                maximum = numGen - 1;
            } else {
                printf("Invalid input! Please enter '>' or '<'\n");
                continue;
            }

            // 检查用户是否可能撒谎(范围不合理)
            if(minimum > maximum) {
                printf("Wait a minute, your answers don't add up! Are you sure you're telling the truth? 😜\n");
                break;
            }
        } else {
            printf("Invalid input! Please enter 'y' or 'n'\n");
            continue;
        }
    }
    return 0;
}

为什么这个修改能解决问题?

  1. 二分法猜中间值:每次都猜当前有效范围的中间数,绝对不会重复猜已经被排除的数——因为范围会随着用户的回答动态缩小,每次的中间值都是新的有效范围内的数。
  2. 正确更新范围:当用户说“更大”,我们把最小值设为当前猜测+1,彻底排除当前数;说“更小”则把最大值设为当前猜测-1,同样排除当前数,确保范围里的数都是未被排除的。
  3. 增加健壮性:加入了对非法输入的判断,以及用户撒谎的检测(当最小值大于最大值时,说明逻辑矛盾)。

用你给的例子测试一下:

输入范围30-40,目标数字37:

  1. 第一次猜30+(40-30)/2=35,用户回答n,然后说>,范围变成36-40
  2. 第二次猜36+(40-36)/2=38,用户回答n,然后说<,范围变成36-37
  3. 第三次猜36+(37-36)/2=36,用户回答n,然后说>,范围变成37-37
  4. 第四次猜37,用户回答y,程序猜对!

完全不会出现重复猜40的情况,而且效率超高!

内容的提问来源于stack exchange,提问作者user14356197

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 13:17:41