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

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

1.计算n的阶乘


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

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



2.计算1-10的阶乘和


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

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

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

#include<stdio.h>
int main()
{
  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.第一次查找

314999e210068c10987f0f0f78798ed3.png

区间:left = 0 right = 9

中间元素下标mid = ( 0 + 9 ) / 2 = 4

mid < 6(7的下标) 说明要查找的元素比5要大,查找区间在5的右边

左下标:left -> mid + 1 = 5

更改查找范围



2.第二次查找

d7f8200bb96cc4d41036ef9251223847.png

区间:left = 5 right = 9

中间元素下标mid = ( 5 + 9 ) / 2 = 7

mid > 6(7的下标) 说明要超找的元素比8要小,查找区间在8的左边

右下标:right -> mid - 1 = 6

更改查找范围


3.第三次查找


e206ddd1d1fff83ab8377445c59760af.png

区间:left = 5 right = 6

中间元素下标mid = ( 5 + 6 )/ 2 = 5

mid < 6(7的下标) 说明要查找的元素比7要小,查找区间在6的右边

左下标:left-> mid + 1 = 6

更改查找范围


4.第四次查找


a428ddf0de4494b5a4c81baf7853da64.png


   区间:left = 6 right = 6

   中间元素下标mid = ( 6 + 6 ) / 2 = 6

   mid = 6(7的下标)

   mid所对应的元素和要查找的元素相等,为7,故元素找到


   查找完毕


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

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


根据题目,实现代码:

#include<stdio.h>
int main()
{
  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;
    }
    else if (arr[mid] > k)
    {
      right = mid - 1;
    }
    else
    {
      printf("找到了,下标是%d\n", mid);
      break;
    }
  }
  //注意break,避免低级错误
  if (left > right)
    printf("找不到\n");
  return 0;
}


注意点:


  • 起始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>
int main()
{
  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--;
  }
  return 0;
}

0694f04b222e9f8578661a3f0bfc77f9.png


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


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

本题密码定义为:“exploreranduin”


#include<stdio.h>
#include<string.h>
int main()
{
  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");
  }
  return 0;
}

4d203c95510fc957b7d4f5af5a524171.png



6. 猜数字小游戏


题目概述:


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


思路:

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



布置菜单


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


表现形式:

#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("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      {
        game();//未设置,仅有进入游戏的意思
        break;
      }
    case 0:
      {
        printf("退出游戏\n");
        break;
      }
    default:
      printf("无选项,请重新输入!\n");
      break;
    }
  } while (input);
  return 0;
}

随机数的设置


所需工具 : randsrand时间戳time

rand - 随机数的生成


8ded7dfcc3937ae08071520831845369.png

转到定义观察RAND_MAX的值:32767

rand返回值范围:0~32767

2a971e2bd2a23ee154996c33818d27b4.png


定义区域 - game函数内


表现形式:

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


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

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


21ef90fa20570edf397a3d778160c302.png



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


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


8f1b2b093be63190011770a8026b15e5.png


表现形式:

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


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

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

srand(100):

5984bf1096fff619bff36620e0016ebd.png


srand(200):


e09167f29c74e89f13788aa8366583eb.png


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


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


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

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

time - 接收时间戳


表现形式:


1aac573348815c5f14b07e3a9b7f4ad3.png


观察返回值time_t的类型:


ab9dc9e5050c6a1c97defe569503b1e7.png


注意点:


   time返回的就是整数,而srand所需的值是无符号整数,这时只需要强制类型转化一下就可以了。由于srand不需要频繁调用,所以我们只需要将其在main函数中定义一次即可。

   rand的返回值范围是0 ~ 32767,对于游戏而言,这无疑加大了难度,所以我们可以将数据约束到1 ~ 100范围内,使游戏更加人性化。而如何达到就只需要ret接收的数据%100再+1就可以了(因为任何数%100的值的范围为0~99).



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

#include<time.h>
#include<stdio.h>
#include<stdlib.h>
void game()
{
    int ret = rand()%100 + 1;
    printf("%d\n", ret);
}
int main()
{
    srand((unsigned int)time(NULL));
  return 0;
}

结合其余代码运行结果:

2e39af2f3aae4099c41bba5c8359b17a.png


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


游戏过程


要点:

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

表现形式:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//游戏实现
void game()
{
  int guess = 0;//输出猜测值
  int 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;//注意游戏结束
    }
  }


完整游戏展示:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
  printf("**********************************\n");
  printf("*********** 1.play ***************\n");
  printf("*********** 0.exit ***************\n");
  printf("**********************************\n");
}
void game()
{
  int guess = 0;
  int 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;
    }
  }
}
int main()
{
  int input = 0;
  srand((unsigned int)time(NULL));
  do
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      game();
      break;
    case 0:
      break;
    default:
      printf("选择错误,请重新输入!\n");
      break;
    }
  } while (input);
  return 0;
}

运行结果:

7bddff80b4fa230a7661db6828c64848.png


7. 结语

以上就是循环练习和猜数字小游戏的全部内容,对于分支与循环这章我们到此为止了,接下来anduin会恢复正常更新速度,更多内容,敬请期待!


相关文章
|
1月前
|
C语言
初识C语言2——分支语句和循环语句
初识C语言2——分支语句和循环语句
67 5
|
26天前
|
C语言
【c语言】循环语句
循环结构是C语言中用于简化重复操作的重要工具,主要包括while循环、do-while循环和for循环。while循环是最基本的形式,通过不断检查条件来决定是否继续执行循环体。do-while循环则先执行循环体,再检查条件,至少执行一次。for循环逻辑更复杂,但使用频率最高,适合初始化、条件判断和更新变量的集中管理。此外,循环中还可以使用break和continue语句来控制循环的提前终止或跳过当前迭代。最后,循环可以嵌套使用,解决更复杂的问题,如查找特定范围内的素数。
34 6
|
1月前
|
C语言 C++
【C语言】编写“猜数字“小游戏
【C语言】编写“猜数字“小游戏
|
1月前
|
编译器 C语言
猜数字游戏实现#C语言
猜数字游戏实现#C语言
79 1
|
1月前
|
存储 C语言
揭秘C语言:泊舟的猜数字游戏
揭秘C语言:泊舟的猜数字游戏
|
1月前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
1月前
|
C语言 开发者
C语言实现猜数字小游戏(详细教程)
C语言实现猜数字小游戏(详细教程)
|
1月前
|
Serverless C语言
C语言控制语句:分支、循环和转向
C语言控制语句:分支、循环和转向
|
1月前
|
C语言
教你快速理解学习C语言的循环与分支
教你快速理解学习C语言的循环与分支
15 0
|
1月前
|
小程序 C语言
初识C语言:走近循环
初识C语言:走近循环