0


【C语言】循环练习和猜数字小游戏

“我的肩上是风,风上是闪烁的星群.”

在上篇文章中,我们学习了分支与循环语句,今天我们将基于这些知识点,进行一些题目的练习,以及一个简单猜数字游戏的实现。话不多说,我们这就开始。

文章目录

1.计算n的阶乘

思路:利用循环得到数字,在对其进行累乘。

#include<stdio.h>intmain(){int n =0;scanf("%d",&n);int i =0;int ret =1;//不能为0for(i =1; i<=n; i++){
        ret*=i;}printf("%d\n", i);}

2.计算1-10的阶乘和

思路1:两层循环,一个控制阶乘另一个控制阶乘和,但是在每一次计算阶乘前需要把ret重新初始化为1,因为每次循环后ret的值是被改变的。

intmain(){int i =0;int n =1;int ret =1;int sum =0;while(n <=10){
        ret =1;//重新赋值为1for(i =1; i <= n; i++){
            ret *= i;//ret的值总被改变}
        sum += ret;
        n++;}printf("%d\n", sum);}

优化:每个数的阶乘无非是前一个数的阶乘×这个数,对此进行优化。原先的循环次数是100次,进行优化后循环次数仅为10次。

#include<stdio.h>intmain(){int i =0;int n =1;int ret =1;int sum =0;while(n <=10){
        ret *= n;
        sum += ret;
        n++;}printf("%d\n", sum);}

3.有序数组中查找具体的某个数字

思路:二分查找

我们先了解一下

二分查找

。例如当我们对一件商品进行估价时,往往会对其价格的区间进行折半猜测,例如商家告诉你这件商品价格区间是1-100,我们绝不会从1-100依次猜测,通常是从50,也就是区间的中点猜起,再通过商家的范围进行不断折半猜测,这就是

二分查找

的基本思路。
其流程大约表现为这种形式:

1.第一次查找

image-20220702153904289

区间:left = 0 right = 9
中间元素下标mid = ( 0 + 9 ) / 2 = 4
mid < 6(7的下标) 说明要查找的元素比5要大,查找区间在5的右边
左下标:left -> mid + 1 = 5
更改查找范围

2.第二次查找

image-20220702153934413

区间:left = 5 right = 9
中间元素下标mid = ( 5 + 9 ) / 2 = 7
mid > 6(7的下标) 说明要超找的元素比8要小,查找区间在8的左边
右下标:right -> mid - 1 = 6
更改查找范围

3.第三次查找

image-20220702154640045

区间:left = 5 right = 6
中间元素下标mid = ( 5 + 6 )/ 2 = 5
mid < 6(7的下标) 说明要查找的元素比7要小,查找区间在6的右边
左下标:left-> mid + 1 = 6
更改查找范围

4.第四次查找

image-20220702155029156

区间:left = 6 right = 6
中间元素下标mid = ( 6 + 6 ) / 2 = 6
mid = 6(7的下标)
mid所对应的元素和要查找的元素相等,为7,故元素找到
查找完毕

整个查找过程一共四次,相比于遍历所有元素的10次,二分查找显得更具有效率。

但是它仍然存在缺点,就是只能用与有序数组的查找。

根据题目,实现代码:

#include<stdio.h>intmain(){int arr[]={1,2,3,4,5,6,7,8,9,10};int sz =sizeof(arr)/sizeof(arr[0]);int k =7;int left =0;//左下标int right = sz -1;//右下标while(left <= right)//注意等于号{int mid =(left + right)/2;//中间元素下标if(arr[mid]< k){
            left = mid +1;}elseif(arr[mid]> k){
            right = mid -1;}else{printf("找到了,下标是%d\n", mid);break;}}//注意break,避免低级错误if(left > right)printf("找不到\n");return0;}
注意点

:

  • 起始left,right下标要写正确
  • while循环的判断条件
  • 中间元素下标要放在循环中,要计算多次
  • 循环中有break,不能盲目打印结果
计算平均值的优化

:

int mid  = left +(right - left)/2;

4. 编写代码,演示多个字符从两端移动,向中间汇聚

题目大意

: hello-0w0-anduin!
例如上方的字符串,要求从全被#覆盖的形式,慢慢向中间汇聚显示整个字符串
#################
h###############!
he#############n!

hello-0w0-anduin!

思路:将两个字符串分别存储起来,使用while循环来进行字符串汇聚的操作,每次都把最左边和最右边的字符放到全是#的字符串中,直到汇聚完成。

#include<stdio.h>#include<string.h>intmain(){char str1[]="hello-0w0-anduin!";char str2[]="#################";int len =strlen(str1);int left =0;int right = len -1;while(left <= right){
        str2[left]= str1[left];
        str2[right]= str1[right];printf("%s\n",str2);
        left++;
        right--;}return0;}

image-20220702191323230

5. 模拟用户登录,输入限制三次

思路:通过strcmp进行字符串比较,判断密码是否正确,正确提示输入正确,若三次均错误则提示并退出程序。
本题密码定义为:“exploreranduin”

#include<stdio.h>#include<string.h>intmain(){int i =0;char password[50]={0};for(i =0; i <3; i++){printf("请输入密码:>");scanf("%s", password);if(strcmp(password,"exploreranduin")==0){printf("输入正确!\n");break;}else{printf("密码错误,请重新输入!\n");}}//正确 or 错误if(i==3){printf("三次密码均错误,退出程序!\n");}return0;}

image-20220702193121006

6. 猜数字小游戏

题目概述

:

  1. 电脑随机生成一个数字(1~100);
  2. 玩家猜数字,玩家猜小了,就告知猜小了;玩家猜大了,就告知猜大了,知道猜对为止;
  3. 游戏可以一直玩。

思路:

  • 布置菜单
  • 随机数的设置
  • 游戏过程

布置菜单

函数形式让用户选择1/0,并在main函数中设置对应的选项,根据题意可以发现这个游戏至少进行一次,使用do…while循环来实现。

表现形式:

#include<stdio.h>//菜单函数voidmenu(){printf("**********************************\n");printf("*********** 1.play ***************\n");printf("*********** 0.exit ***************\n");printf("**********************************\n");}intmain(){int input =0;//选择输入do{menu();//调用菜单界面printf("请选择:>");scanf("%d",&input);switch(input){case1:{game();//未设置,仅有进入游戏的意思break;}case0:{printf("退出游戏\n");break;}default:printf("无选项,请重新输入!\n");break;}}while(input);return0;}

随机数的设置

所需工具 :

rand

srand

时间戳

time
rand
  • 随机数的生成

image-20220702200343473

转到定义观察RAND_MAX的值:32767

rand

返回值范围:0~32767
image-20220702200613115

定义区域 - game函数内

表现形式:

#include<stdlib.h>voidgame(){int ret =rand();printf("%d\n", ret);}

结合菜单部分代码并运行查看效果:

运行2次(由于结果相同,只贴第一次结果):

问题:仅仅用rand函数每次运行结果都是相同的,当每次结果相同,玩家找到规律后,这个游戏的意义就不存在了,那么该如何解决这个问题呢?

观察一下rand函数的一段描述:

image-20220703092512238

上面说到srand函数可以帮忙设置真正的随机数,让我们再了解一下这个函数。

srand 
  • 结合rand生成不固定的随机数

image-20220702201506096

表现形式:

#include<stdlib.h>voidgame(){srand(100);//srand(200);int ret =rand();printf("%d\n",ret);}

当srand所接收的数据不同时,所生成的随机数也会发生改变,在同一段代码内,由于每次传的数据都相同,所以数据也想同

结合菜单部分代码运行查看效果:

srand(100)

:

image-20220703101136447

srand(200)

:

image-20220703101212496

srand

需要接收一个无符号整型才能返回一个随机数,但我们的初衷是它自动生成,并且在游戏过程结束后,每次生成的随机数不同,为了达到效果,我们需要一个随时变化的随机值。

我们知道,时间是每时每刻发生变化的,那么可不可以用时间来充当这个随机值呢,答案是可以的,这个随机值的名字叫做

时间戳

.

时间戳
  • srand
    
    提供随时变化的随机值

概念:当前时间和计算机起始时间(1970年1月1日0时0分0秒)之间的差值

time
  • 接收时间戳

表现形式:

image-20220703102211144

观察返回值

time_t

的类型:

image-20220703102425684

注意点:

  1. time返回的就是整数,而srand所需的值是无符号整数,这时只需要强制类型转化一下就可以了。由于srand不需要频繁调用,所以我们只需要将其在main函数中定义一次即可。
  2. rand的返回值范围是0 ~ 32767,对于游戏而言,这无疑加大了难度,所以我们可以将数据约束到1 ~ 100范围内,使游戏更加人性化。而如何达到就只需要ret接收的数据%100再+1就可以了(因为任何数%100的值的范围为0~99).

结合以上两点,核心代码表现形式为:

#include<time.h>#include<stdio.h>#include<stdlib.h>voidgame(){int ret =rand()%100+1;printf("%d\n", ret);}intmain(){srand((unsignedint)time(NULL));return0;}

结合其余代码运行结果:

image-20220703104419071

到此,随机数的生成问题就解决了。

游戏过程

要点:

  • 游戏有连续性,循环一直都要进行
  • 多分支判断
  • 猜对了要设置出口,不能猜对了一直猜

表现形式:

#include<stdio.h>#include<stdlib.h>#include<time.h>//游戏实现voidgame(){int guess =0;//输出猜测值int ret =rand()%100+1;//生成一个随机数//猜数字while(1){printf("请输入数字:>");scanf("%d",&guess);if(guess > ret){printf("猜大了\n");}elseif(guess < ret){printf("猜小了\n");}else{printf("恭喜你,猜对了!\n");break;//注意游戏结束}}

完整游戏展示:

#include<stdio.h>#include<stdlib.h>#include<time.h>voidmenu(){printf("**********************************\n");printf("*********** 1.play ***************\n");printf("*********** 0.exit ***************\n");printf("**********************************\n");}voidgame(){int guess =0;int ret =rand()%100+1;while(1){printf("请输入你猜测的数字:>");scanf("%d",&guess);if(guess > ret){printf("猜大了\n");}elseif(guess < ret){printf("猜小了\n");}else{printf("恭喜你,猜对了!\n");break;}}}intmain(){int input =0;srand((unsignedint)time(NULL));do{menu();printf("请选择:>");scanf("%d",&input);switch(input){case1:game();break;case0:break;default:printf("选择错误,请重新输入!\n");break;}}while(input);return0;}

运行结果:

image-20220703114110418

7. 结语

以上就是循环练习和猜数字小游戏的全部内容,对于分支与循环这章我们到此为止了,接下来anduin会恢复正常更新速度,更多内容,敬请期待!
如果觉得anduin写的还不错的话,还请点赞 + 评论 + 收藏哦!
希望我的文章能对你有帮助!

标签: c语言 开发语言

本文转载自: https://blog.csdn.net/m0_67867172/article/details/125920669
版权归原作者 进击的安度因 所有, 如有侵权,请联系我们删除。

“【C语言】循环练习和猜数字小游戏”的评论:

还没有评论