【深基4,例5】猜数字游戏

小洛机器人和你玩猜数游戏!小洛随机选择并默默记下一个1~100的整数,你需要不断猜测这个数字是什么并输入验证。如果你输入的数字比小洛选择的数字小,小洛会输出“Too small”;如果比小洛选择的数字大,小洛输出“TOO large”;如果刚好猜对,小洛输出“You are right!!”。如果一次没有猜中,则继续猜,直到猜中为止。

这个猜数游戏是一个经典的二分查找算法的应用实例,其中小洛机器人代表程序中的算法部分,而你代表与程序交互的用户。

程序的基本逻辑流程:

1、初始化阶段:小洛机器人在1到100之间随机选择一个整数作为答案。

2、用户输入:用户输入一个猜测的数字。

3、比较阶段:

  • 如果用户猜的数字小于小洛机器人选择的数字,小洛机器人输出 "Too small"。
  • 如果用户猜的数字大于小洛机器人选择的数字,小洛机器人输出 "TOO large"。
  • 如果用户猜的数字正好等于小洛机器人选择的数字,小洛机器人输出 "You are right!!"。
  • 循环判断:如果用户没有猜中数字,程序会返回到用户输入阶段,让用户继续猜测,直到猜中为止。

4、结束条件:当用户猜中数字时,程序结束。

这个程序可以用伪代码表示如下: 

function play_guessing_game
    secret_number = random_number_between(1, 100) // 小洛随机选择数字
    while true
        guess = get_user_input() // 用户输入猜测数字
        if guess < secret_number
            print "Too small"
        else if guess > secret_number
            print "TOO large"
        else
            print "You are right!!"
            break // 猜中数字,退出循环
        end if
    end while
end function

在这个猜数游戏中,通常选择 do-while 循环而不是其他类型的循环(如 while 循环或 for 循环)的原因是:

  • 保证至少执行一次:do-while 循环至少会执行一次循环体内的代码块,无论条件是否为真。这对于猜数游戏来说是必要的,因为玩家至少需要一次猜测的机会。
  • 在循环结束后检查条件:do-while 循环会在执行循环体的代码之后检查条件。这意味着即使在第一次猜测后玩家就猜对了数字,循环依然会进行一次猜测,然后检查条件并退出。

如何让计算机产生一个随机数呢?

可以使用rand()函数来产生一个0~RAND_MAX的整数,其中RAND_MAX是一个常量,其值与编译系统有关,而且别忘了加上头文件cstdlib

可以使用rand()%a产生一个0~a-1的随机数。如果想产生一个ab的随机数,可以使用rand()%(b-a+1)+a

rand()生成的是“伪随机数”,因此每次执行前都要“喂给它”不同的初始值(srand()函数作为随机数种子,这样才能生成不同的随机数)。喂给它当前时间就是一个比较好的选择。

#include <iostream> 
#include <cstdlib>
#include <ctime>
using namespace std;
int main(){
	int ans,guess;
	srand(time(0));
	ans=rand()%100+1;
	do{
		cin>>guess;
		if(guess<ans) 
		    cout<<"Too small"<<endl;
		else if(guess>ans) 
		    cout<<"Too large"<<endl;
	}while(guess!=ans);
	cout<<"You are right!!"<<endl;
}

rand()%a看起来可以生成一个0到a-1的随机数,但是每个数字并不是等可能的。假设RNAD_MAX是32767,取0~99的随机数时,抽到0~67的可能要比剩下的数字大一点(想一想,为什么)。如果RAND_MAX远大于a时,影响并不大。请考虑一种等可能的生成区间随机数方式(可能需要多次抽取)

rand() % a 这种生成随机数的方法确实可以生成一个 0 到 a-1 范围内的整数,但是它可能不会是完全等概率的。这主要是因为 rand() 函数生成的随机数分布可能不是完全均匀的,特别是在模运算中,某些数字可能比其他数字出现的概率稍高。

当使用 rand() % a 时,如果 RAND_MAX 和 a 之间存在一定的数学关系,比如 a 是 100,而 RAND_MAX 是 32767,那么理论上每个数字出现的概率应该是相等的。但实际上,由于 rand() 函数生成的随机数可能存在轻微的偏差,以及模运算本身的数学特性,某些数字可能会比其他数字出现得更频繁。

具体来说,如果 RAND_MAX 除以 a 有余数,那么在取模运算中,0 到 (RAND_MAX % a - 1) 范围内的数字出现的概率会略高于其他数字。这是因为当 RAND_MAX 被 a 除尽时,余数范围内的数字会多出一些可能的随机数映射。例如,如果 RAND_MAX 是 32767,当 a 是 100 时,RAND_MAX % 100 的结果是 67,这意味着在 0 到 67 之间的数字有更多的机会映射到 rand() % 100 的结果中。

为了获得更均匀分布的随机数,可以采取以下方法之一:

1、使用更好的随机数生成器:C++11 中的 <random> 库提供了多种高质量的随机数生成器,例如 std::mt19937,它是基于 Mersenne Twister 算法。

2、调整随机数生成策略:使用不同的方法来生成随机数,例如先生成一个更大的范围内的随机数,然后通过适当的缩放和偏移来得到所需的范围。

3、后处理随机数序列:对生成的随机数序列进行后处理,例如通过随机打乱序列来减少任何可能的偏差。

4、使用舍入:如果需要更均匀的分布,可以先生成一个更大的范围的随机数,然后通过舍入到最近的整数来获得所需范围内的随机数。

使用 C++11 的 <random> 库可以很容易地实现这些改进,从而获得更高质量的随机数。

  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hl026

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值