猜数字游戏

思路:要知道程序只要能运行,那么电脑会生成一个随机数;然后我们来猜数字,猜错了,就提示;猜对了,就结束游戏。

那如何用代码实现呢?

且我们不可能玩一把,就结束游戏,还会可能会反复去玩,那要怎么做?

这里可能会有人提出用二分法,这种想法是对的,但这只是在思路上用的是二分法,但实际代码上并不是用二分法。

这里每一把玩都是一次游戏执行,当我们想要玩多次的时候,其实就是把游戏执行放在循环里面,而我们知道是游戏的话,第一次还是要进来的,也就是说这游戏至少进行一次。

所以,这里用到do...while语句do...while语句就是游戏至少要进行一次。

而我们打开游戏,首先,是要有菜单栏,选择1就是进入游戏,选择0就是退出游戏。

这里就用到menu函数——菜单函数——打印菜单的形式

如何实现呢?

void menu(){

                         printf("**********************\n");

                         printf("**1、play    0、exit**\n");

                         printf("**********************\n");

}

而菜单一旦被打印就要做一件事情——

printf("请选择>:");

让用户进行选择。

让用户选择的话,其实就是让用户选择数字,这里就需要用到scanf函数了,而输入数字,就需要存起来,这里就需要一个变量,也就是——

int input=0;

scanf("%d",&input);——表示我要把取进来的值放在这地址处。

而用户除了选择1或0以外,可能会选择其他值,但这里还没有进行处理,所以无法给出结果;因此,这里就要用到多分支的情况。

而这里除1或0的选项以外,其他值的选项就是错的;所以这里用default来处理;

所以这里用到switch语句——

switch(input){

               case 1:

                              game();//猜数字游戏

                             break;

               case 2:

                             printf("退出游戏\n");

                             break;

               default:

                             printf("选择错误\n")

                             break;

}

而如果你选择1的话,就是要进入游戏,因此这里我们用到game函数

如果你选择2,那么就是要退出游戏了,这里就用到printf函数进行打印,并结束程序;

而如果你输入其他数字,那么这里就需要进行提示

当我们选择2或选择错误的时候,就跳出循环了,就来到判断部分——

这时如果我们猜数字成功的话,还想再进行一次,就是循环判断成功,再返回菜单,再进行一把;

如果你选择错误的话,就是要给你一次机会进行选择;

选择0的话就退出游戏了。

所以do...while语句中while()括号里的判断部分就用input,即——

while(input);

input若为1的话,1为真,就进入循环;

若为0的话,0为假就是不进入循环;为其他数字的时候,也是为真,就会返回到菜单在重新进行一次选择。

总体为:

void menu(){

                         printf("**********************\n");

                         printf("**1、play    0、exit**\n");

                         printf("**********************\n");

}

int main(){

                  int input=0;

                 do{

                   menu();

                   printf("请选择>:");

                   scanf("%d",&input);                

             switch(input){

               case 1:

                              game();//猜数字游戏

                             break;

               case 2:

                             printf("退出游戏\n");

                             break;

               default:

                             printf("选择错误\n")

                             break;

                              }

                    }while(input);  

                   return0;

}

写到这里的时候,基本上的do...while语句switch case语句写完了,而接下来就是要写game函数来进行游戏了。

而如何编写game函数里的内容呢?

思路:1、生成一个随机数       2、猜数字

生成一个随即数要怎么做呢?

C语言提供一个生成随机数的函数——rand函数

这个函数要怎么用呢?

如果你不是特别了解的话,也不必担心,可以去查看文档

这里介绍一个工具——MSDN(微软提供的一个工具)

注:电脑本身就有,搜索后下载即可。

步骤:点索引之后输入想要查询的函数即可。

 【注:页面内容为英文,如果英语基础好的同学应该看得懂大概意思,看不懂的同学可以用翻译工具进行翻译理解。】

通过msdn了解rand函数,没有参数,返回类型是一个整形,返回一个随机整数

这里有一个细节,就是返回的随即整数有一个范围——0~RAND_MAX。

而这RAND_MAX是多少呢?

可以将RAND_MAX在vs编译器中,选中并右击转到定义(记得引头文件#include <stdlib.h>)——

可发现RAND_MAX的值是0x7fff(这里以0x为开头的数字,为十六进制数字),而7fff对应的十进制数字是32767(可以用计算器)

所以,rand函数生成的随机数是——0到32767之间。

1、生成随机数的代码编写为:

int ret=rand();

printf("%d\n",ret); 

但这并不是说这样就完成了生成随机数的部分了,细心的同学会发现——当我们退出游戏的时候,再重新进入的时候,会发现生成的随机数会和上一次的一样。(这把玩完之后,再开一把随机数还是和上一次一样,这样玩一把就永远通关了,那也就没意思了。)

所以,这种写法就是有问题的。

这里要注意,看文档要看全,在Remarks后面的部分,有写到在调用rand之前,请使用srand函数,去设置随机数的一个生成器。

也就是说在调用rand之前要先调用srand函数

点开srand函数,会了解——

srand函数的作用是——设置一个随即起点。

参数部分是给一个无符号整形

这时——

srand(1); 

int ret=rand();

printf("%d\n",ret); 

这样写会报错,一个典型的报错例子(前面有讲过)

变量要定义在代码块最前面(旧版本的vs编译器会报错,新的可能不会)。

但最好还是统一下——前面定义,后面使用

【注:如果报错无法打开什么什么exe文件的话,就是前你调试的窗口未关闭】

再去调整之后——

int ret=0;

srand(1); 

ret=rand();

printf("%d\n",ret); 

这时再去调试窗口之后,会发现每次生成的随机数都被固定了。

这是因为srand();括号中要给一个变化的数字,但这里srand要一个整数的参数,且这个整数是要变化的,那我要给它传进一个随机值,这样就能解决问题。

可是问题来了,我们是为了生成随机数,而scand这里也需要随机数,这样不就陷入死循环了吗?所以这里给一个随即数是不现实的。

所以,这里我们要给出一个时刻在发生变化的数值,就可以了,那怎么办呢?怎么给呢?

提示——什么数字是时刻在发生变化的呢?时间

也就明白如果scand参数部分如果给出一个跟时间有关的值,而这个值总在发生变化的话,那就解决了。

所以,这里就提出一个概念——叫作时间戳

时间戳可以转换时间:

这个时间会和1970年1月1日这个时间的差值,换算成秒之后的数字。

当前计算机的时间-计算机的起始时间(1970.1.1.0:0:0)=(xxxx)秒

注:计算机有一个起始时间。

当我们的时间在每一分每一秒在发生变化的时候,这个时间戳也是在发生变化的。

所以,这里我们拿时间戳来设置随即数的生成起始点。

C语言如何来获得时间戳?

查看文档会发现——

 srand( (unsigned)time( NULL ) );

这里用到了time函数

time函数——获取系统时间 。

time_t time( time_t *timer );

返回的类型是time_t,参数部分是一个time_t*(指针)

在vs中查看time_t的定义,会发现time_t是对typedef __time32(或64)_t进行重命名;

在查看__time32_t的定义,发现它是一个long类型,对long进行重命名。

总结一句话——time_t其实本质上就是一个长整形

而原本srand函数的参数部分要的就是一个整数,所以——

srand((unsigned int)time(NULL));

调用time函数,调用之后,返回的值给强制类型转换成unsigned int.

【注:time()这里的括号是我们调用函数的时候设置的。】

这里不要time()参数部分,但又因为它需要的是一个指针,所以这里我们给一个空指针NULL;实际上我们不想要它产生实际的效果,所以这样写。

注:time函数需要对应的头文件#include<time.h>

void game(){

           int ret=0;

           srand((unsigned int)time(NULL));

           ret=rand();

           printf("%d\n",ret); 

}

如果你去试着运行的话,会发现生成的随机数并不随机,就是说你连续输入两个数字1(继续游戏),会发现生成的随机数很接近。

这是因为我们代码放的位置有问题——

srand函数生成随机数的起点,我们只要在整个代码里面设置一次即可。(不要频繁去设置生成起点,只要设置一次即可。)

也就是说要把srand((unsigned int)time(NULL));放到主函数里面即可,在工程里面只用调用一次就行;放到game函数里面就是每玩一次游戏就设置一次,就频繁生成了。

以上,便是随即数的生成方式。

但这时我们发现生成随机数的范围如果在0~32767之间的话,范围太大了,不好猜;如果这里我们生成的随即数在1~100之间的话,就比较好猜了。

那怎么做呢?

可以让我们这个随机数模上100得到的余数无非就是0~99的数字,而在加上1之后,就是0~100了

ret=rand()%100+1;

这样,生成随即数的部分就完成了,接下来就是猜数字部分了。

但这里我们要先去掉打印随机数的语句,不然这样就是照抄了,所以——

猜数字是一个循环的方式

int guess=0;

while(1){

             printf("请猜数字:>")

              scanf("%d",&guess);

             if(guess>ret){

                                      printf("猜大了\n");

                                  }

             else if(guess<ret){

                                            printf("猜小了\n");

                                          }

              else{

                         printf("恭喜你,猜对了\n");

                         break;

                       }

}

而猜的数字我们要放到guess里面去了,然后比较。

总——

#include<stdio.h>
#include <time.h>
#include<stdlib.h>
void game(){
           int guess=0;
           int ret=0;         
           ret=rand()%100+1;
           while(1){
             printf("请猜数字:>");
             scanf("%d",&guess);
             if(guess>ret){
                           printf("猜大了\n");

                            }

             else if(guess<ret){
                                 printf("猜小了\n");

                              }

              else{
                         printf("恭喜你,猜对了\n");
                         break;
                   }

             }
}
void menu(){
                         printf("**********************\n");
                         printf("**1、play    0、exit**\n");
                         printf("**********************\n");
}

int main(){
                  int input=0;
                  srand((unsigned int)time(NULL));
                 do{
                   menu();
                   printf("请选择>:");
                   scanf("%d",&input);                
              switch(input){
                       case 1:
                              game();//猜数字游戏
                             break;
                       case 2:
                             printf("退出游戏\n");
                            break;

                       default:
                             printf("选择错误\n");
                             break;
                           }
                    }while(input);  
                   return 0;

}

避坑——

1、是否可以将ret=rand()%100+1;放到while循环内部?

不可以,如果放进去,会导致永远猜不到这个数字。

因为每次进入循环都会重新生成随机数。

​​​​​​​

2、还有就是我们不能把猜大和猜小的顺序搞错了,也就是打印函数printf内搞反,这样也会导致猜不到数字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值