目录
代码实现
#include <stdio.h>
#include <string.h>
#include <time.h>
void menu()
{
printf("*************************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("*************************\n");
}
void game()
{
int guess = 0;
int r = rand()%100+1;
while (1)
{
printf("猜数字:>");
scanf("%d", &guess);
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
思路讲解
猜数字游戏:
算法思路:
1、电脑随机生成一个1~ 100之间的数字
2、猜数字
3、比较
(判断所猜的数字和电脑随机生成的数字是否一样)
- )玩家猜小了, 电脑会告诉 : 猜小了
- )玩家猜大了,电脑会告诉 : 猜大了
- )玩家猜对了,电脑会告诉 : 恭喜你,猜对了
4、退出游戏或继续玩
(猜对后还想玩游戏)
1.步骤:do while结构
#include <stdio.h>
int main()
{
do
{
menu();//此时menu()函数就是一个简易的菜单
}while()
return 0;
}
选择用do while结构;
因为游戏一运行起来就要看到菜单,即什么都不判断时就要先看到菜单;
所以do while一上来(进入)就可以首先打印菜单;
如果是while或for循环一上来就需要判断才能进入。
2.步骤:定义菜单
定义menu()函数——定义菜单;
#include <stdio.h>
void menu()//menu返回类型是void,因为不需要返回
{
printf("*************************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("*************************\n");
}
int main()
{
do
{
menu();//代码走到这就会调用上面的menu()函数打印菜单
} while ();
return 0;
}
菜单的功能:
- 1——表示开始玩
- 0——表示退出游戏
3.步骤:完善主函数
完善——主函数
(用户如何根据菜单选择开始玩还是退出,是否继续玩(进入循环)还是退出游戏)
#include <stdio.h>
void menu()
{
printf("*************************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("*************************\n");
}
int main()
{
int input = 0;
do
{
menu();
//屏幕上出现菜单后,接下来提示用户选择
printf("请选择\n");
//用户输入数字
scanf("%d",&input);
//判断用户输入的数字是1还是0
//即判断的是要开始玩游戏还是退出游戏
switch (input)//判断的是input的值
{
case 1://如果输入的是1,那就走case 1
printf("猜数字\n");
break;
case 0://如果输入的是0,那就走case 0
printf("退出游戏\n");
break;
default://如果输入的既不是1也不是0则走default语句
printf("选择错误\n");//提示用户选择的不是菜单上的功能
break;
}
//break从这跳出来,此时do做完了,来到了while
} while (input);//这里有分号,在do……while循环中while()圆括号后面有分号
//如果选择0,即input里放的是0,那就退出游戏,while中判断是0,0为假循环就停下来了;
//如果选择1,input里放的是1,while中判断是1即进入循环再上去玩,又有一次选择的机会……
//如果选错了,即选择的是其他非0的数字,非0为真也会进入循环。
return 0;
}
注意:
在do……while循环中while()圆括号后面有分号;
int input = 0;在do之前创建,不能在do之后创建;
否则编译器会报警告:“input”: 未声明的标识符。
(注意定义标识符的顺序)
上述1-3步编完成后编译器可以进行正常运行;
但是当用户输入1的时候应该就进入游戏了而不是进行打印“猜数字”这句话
4.步骤:编辑游戏实现模式
具体编辑游戏
(猜数字这个游戏过程是怎么样的?怎么实现?——即定义案例 (case 1:) 中 “ 猜数字 ” 游戏)
即:
case 1:
printf("猜数字\n");
game();
break;game()函数是一个简易的函数,这个函数里面是玩游戏的整个逻辑。
bug 1:预想生成随机数
#include <stdio.h>
#include <stdlib.h>
void menu()
{
printf("*************************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("*************************\n");
}
void game()//圆括号里面没有参数,返回类型是void, 因为不需要返回
{
//猜数字游戏的过程:
//1.电脑生成随机数
//C语言中生成随机数的方法是:——rand()函数,生成随机数的范围是:0-RAND_MAX;
RAND_MAX;
//RAND_MAX是多大呢?RAND_MAX选中,转到定义,得到:0x7fff是十六进制(32767是它的十进制),所以它的范围是0-32767
//(取消转到定义界面点击项目上面的黄标“test.c*"即可)
//即返回的是0-32767之间的数字
//rand是库函数,需要引头文件<stdlib.h>
int r = rand();
//把随机数打印在电脑上,这里临时用于检查随机数是否正确生成
printf("%d\n", r);
//2.用户进行猜数字
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
输出:每次编译器运行的结果都是一样的随机数;
即输出的随机数有规律;这次玩游戏的随机数和下次、下下次……一样。
所以:rand确实可以帮电脑生成随机数,但只用rand会使游戏产生bug。
(生成随机数的方法有问题)
注解:
"Use the srand function to seed the pseudorandom-number generator before calling rand."
即在调用rand函数之前需要先调用srand()函数,需要srand()函数设置随机数的生成器。
bug 2:设置随机数生成器
void srand( unsigned int seed );
意思是:srand 接收的是整数int,返回的是void。
#include <stdio.h>
#include <stdlib.h>
void menu()
{
printf("**************************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("**************************\n");
}
void game()
{
//1.生成随机数
srand(10);
int r = rand();
//把随机数打印在电脑上,这里临时用于检查随机数是否正确生成
printf("%d\n", r);
//2.猜数字
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
输出:生成的随机数在发生变化,但是是在srand(10)中的随机数变化的前提下变化的;
即修改一次srand( )括号里的数字随机数变化一次;
产生bug:为了产生一个随机数又需要输入一个随机数。
若是这样用:(错误)
srand(1);
int r = rand();
printf("%d\n", r);srand圆括号里的值发生变化,rand生成的随机数就在发生变化。
所以:
需要给srand传一个在经常发生变化的值;
有些值是经常发生变化的,比如电脑上的时间。所以就可以把时间传给它,每一秒的时间都会产生一个数字,即把时间传给srand。
这里用到时间戳:任意一个时间都可以转换成一个秒数,这个秒数就称为时间戳。
这样一个时间戳就可以转换成一个时间,所以时间在不断发生变化时,时间戳也在不断发生变化。任何一个时间都可以转换成一个时间戳。
时间戳是怎么获取的呢?
——是当前时间和计算机起始时间的差值转化成秒的这样一个数字。
在C语言中获取时间戳要用到time()函数;
time()函数是C语言的库函数(需要引头文件:<time.h>),它能获取时间戳。
所以:srand(time()) (大致形式)
time_t time( time_t *timer );
time()函数的参数: time_t *timer
time_t *是一种指针,如果不想用这个参数,就传一个空指针:NULL
time()函数返回的值是:time_t
大致形式变为:srand(time(NULL));
而srand()函数:void srand( unsigned int seed );
需要的是unsigned int,这能匹配吗?
——可以。
选中 time_t 转到定义是typedef __time64 _t ,那么typedef __time64 _t 是什么呢?
选中 __time64 _t,转到定义发现它是typedef _int64,是整型值;
发现:
time_t 是 typedef __int64,time_t也是一种整型,是typedef来定义的一种整型值;
即time_t本质上是64位的整型。
所以:
就可以把time()函数的返回值作为srand的参数,即可以写成srand(time(NULL))形式;
但是需要强制类型转换一下,强制(把time_t类型或说成是int类型)转化为unsiged int 类型。
(因为srand函数需要的是unsiged int 类型的参数)
即是:
srand(time(NULL));——>强制类型转换后:srand((unsigned int)time(NULL));
这里用到的是单目操作符:(类型) ——强制类型转换
bug 3:正确生成随机数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("**************************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("**************************\n");
}
time_t;
void game()
{
//1.生成随机数
srand((unsigned int)time(NULL));
int r = rand();
//把随机数打印在电脑上,这里临时用于检查随机数是否正确生成
printf("%d\n", r);
//2.猜数字
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
输出:当按的太快时,两次的随机值生成的一样;
产生bug:生成的不够随机。
srand((unsigned int)time(NULL));
这行代码的作用是在设置随机数的生成器;但是在整个程序中只要设置一次就可以了。
若这行代码放在:
void game()
{
srand((unsigned int)time(NULL));
int r = rand();
printf("%d\n", r);
}
设置在这里(game玩游戏的过程中),就会玩一次游戏就设置一次,没有必要频繁设置。
因为:
主函数只用调用一次,do while中是玩游戏;
所以:
把“srand((unsigned int)time(NULL));”放到主函数中,这时无论多快生成的数字都是随机的。
(bug 3)总结:
- srand用来设置随机数生成器,设置好rand才能生成随机数,
- 整个程序只需要设置一次随机数生成器就可以了,没必要重复设置
bug 4:缩小随机数生成范围
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("**************************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("**************************\n");
}
time_t;
void game()
{
//1.生成随机数
int r = rand();
//把随机数打印在电脑上,这里临时用于检查随机数是否正确生成
printf("%d\n", r);
//2.猜数字
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//生成随机数的生成器
do
{
menu();
printf("请选择\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
输出:现在生成的数字是0—32767;
需求:生成0—100的数字。
即是:把int r = rand();——>变成:int r = rand()%100;
把生成的数字模上100,(一个大于100的数字%100,它的余数范围是0-99);
即此时生成的数字是0~99,再加1,int r = rand()+1;即范围变成了1~100。
即是:把int r = rand()%100;——>变成:int r = rand()%100+1;
这时就绝对不可能随机出现大于100的数字了,因为已经设置好算法了。
bug 5:
上述步骤已确定随机数字可以正确生成,不打印随机数字,而是开始猜数字。
即是
void game()
{int r = rand()%100+1;
printf("%d\n", r);}
进行2.猜数字:编写这部分代码为:
void game()
{
int guess = 0;
int r = rand()%100+1;
//printf("%d\n", r);
//提示用户猜数字:
printf("猜数字:>");
//用户输入猜的数字:
scanf("%d", &guess);
//比较用户猜的数字和电脑随机生成的数字
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
}
注意:这个if分支结构是循环体,因为需要反复猜,所以改为循环是:
void game()
{
int guess = 0;
int r = rand()%100+1;
//printf("%d\n", r);
//提示用户猜数字:
while (1)
{
printf("猜数字:>");
//用户输入猜的数字:
scanf("%d", &guess);
//比较用户猜的数字和电脑随机生成的数字
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;//循环停下的条件就是break
}
}
}
所以:
书写正确整体代码:
#include <stdio.h>
#include <string.h>
#include <time.h>
void menu()
{
printf("*************************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("*************************\n");
}
void game()
{
int guess = 0;
int r = rand()%100+1;
while (1)
{
printf("猜数字:>");
scanf("%d", &guess);
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
梳理逻辑:
1.菜单的打印;
打印游戏的主逻辑(选择1就玩游戏,选择0就退出游戏,选择其他就是选择错误)
——用do……while循环结构实现。
2.玩游戏;
——用game()函数实现。
- 首先,生成随机数,用rand;
- rand在使用之前必须用srand设置随机数的生成器;生成器设置好后,rand才会安安稳稳地生成随机数。
- 它生成随机数的范围是0-32767,而想要的数字是1-100,所以%100+1得到想要的数字
3.然后就是不断的猜。
注:
在自然界中通过算法实现的随机数都是伪随机数。
真正的随机数是无规律的,而写的代码是有规律的。