【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会恢复正常更新速度,更多内容,敬请期待!


相关文章
|
14天前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的循环语句
本文介绍了C语言中的三种循环语句:`while`、`do-while`和`for`,并详细解释了它们的语法格式、执行流程及应用场景。此外,还讲解了循环控制语句`break`和`continue`的使用方法。希望这些内容能帮助你在编程道路上不断进步,共同成长!
31 0
一文彻底搞清楚C语言的循环语句
|
25天前
|
定位技术 C语言
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
2月前
|
C语言
【C语言程序设计——循环程序设计】枚举法换硬币(头歌实践教学平台习题)【合集】
本文档介绍了编程任务的详细内容,旨在运用枚举法求解硬币等额 - 循环控制语句(`for`、`while`)及跳转语句(`break`、`continue`)的使用。 - 循环嵌套语句的基本概念和应用,如双重`for`循环、`while`嵌套等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台将对编写的代码进行测试,并给出预期输出结果。 5. **通关代码**:提供完整的代码示例,帮助理解并完成任务。 6. **测试结果**:展示代码运行后的实际输出,验证正确性。 文档结构清晰,逐步引导读者掌握循环结构与嵌套的应用,最终实现硬币兑换的程序设计。
55 19
|
2月前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
103 18
|
2月前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
68 18
|
2月前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
76 13
|
2月前
|
存储 C语言
【C语言程序设计——循环程序设计】利用数列的累加和求 sinx(头歌实践教学平台习题)【合集】
项的累加和,一般会使用循环结构,在每次循环中计算出当前项的值(可能基于通项公式或者递推关系),然后累加到一个用于存储累加和的变量中。在C语言中推导数列中的某一项,通常需要依据数列给定的通项公式或者前后项之间的递推关系来实现。例如,对于一个简单的等差数列,其通项公式为。的级数,其每一项之间存在特定的递推关系(后项的分子是其前项的分子乘上。,计算sinx的值,直到最后一项的绝对值小于。为项数),就可以通过代码来计算出指定项的值。对于更复杂的数列,像题目中涉及的用于近似计算。开始你的任务吧,祝你成功!
63 6
|
2月前
|
C语言
【C语言程序设计——循环程序设计】鸡兔同笼问题(头歌实践教学平台习题)【合集】
本教程介绍了循环控制和跳转语句的使用,包括 `for`、`while` 和 `do-while` 循环,以及 `break` 和 `continue` 语句。通过示例代码详细讲解了这些语句的应用场景,并展示了如何使用循环嵌套解决复杂问题,如计算最大公因数和模拟游戏关卡选择。最后,通过鸡兔同笼问题演示了穷举法编程的实际应用。文中还提供了编程要求、测试说明及通关代码,帮助读者掌握相关知识并完成任务。 任务描述:根据给定条件,编写程序计算鸡和兔的数量。鸡有1个头2只脚,兔子有1个头4只脚。
98 5
|
5月前
|
C语言
【c语言】循环语句
循环结构是C语言中用于简化重复操作的重要工具,主要包括while循环、do-while循环和for循环。while循环是最基本的形式,通过不断检查条件来决定是否继续执行循环体。do-while循环则先执行循环体,再检查条件,至少执行一次。for循环逻辑更复杂,但使用频率最高,适合初始化、条件判断和更新变量的集中管理。此外,循环中还可以使用break和continue语句来控制循环的提前终止或跳过当前迭代。最后,循环可以嵌套使用,解决更复杂的问题,如查找特定范围内的素数。
82 6
|
5月前
|
C语言 C++
【C语言】编写“猜数字“小游戏
【C语言】编写“猜数字“小游戏
129 1