C语言——二分查找与猜数字游戏

简介: C语言——二分查找与猜数字游戏

二分查找

题目: 在一个有序数组中查找具体的某个数字n。

首先我们先定义一个1···10的数组 ,如果7为我们要查找的数字,编写代码如下

#include <stdio.h>
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  //  下标          0 1 2 3 4 5 6 7 8 9
  int k = 7;//k是要查找的数字
  int i = 0;
  int sz = sizeof(arr) / sizeof(arr[0]);
     //sz为数组元素个数
  int flag = 0;//
  for (i = 0; i < sz; i++)
  {
    if (k == arr[i])
    {
      flag = 1;
      printf("找到了,下标是:%d\n", i);
      break;
    }
  }
  if (flag == 0)
    printf("找不到\n");
  return 0;
}


但是这个代码的效率比较低,需要循环多次,所以我们需要用一个效率较高的方法:二分查找又叫 (折半查找)

二分查找的思想

给你一个有序的序列,取中间元素和目标元素进行对比,取其中的一半,丢弃另一半,快速缩小目标元素所在的位置。主要思想还是:快速缩小目标元素所在的区间。


二分查找的条件

1.序列必须是有序的,升序或者降序都可以

2. 序列必须是顺序存储元素的,顺序存储元素主要是可以快速的获取中间元素(可以通过下标来找到元素)


二分查找的实现过程

分析:假设我们要找的数字为7,在查找过程中要用下标进行查找,此时我们定义左下标为left,右下标为right,中间元素下标为mid,(left+right)/2=mid。当第一次查找没有找到时,从中间下标向左或向右缩短查找范围继续查找,直到找到为止。


以数字7为例:第一次查找(left+right)/2=(0+9)/2=4,下标为4找到的数字为5,此时并没有找到;第二次查找,因为数字5小于数字7,所以mid+1=left,right不变,向右查找,此时(left+right)/2=(5+9)/2=7,下标为7,找到的数字为8,并没有找到;第三次查找,因为数字8大于数字7,所以mid-1=right,左下标不变,向左查找,此时(left+right)/2=(5+6)/2=5,下标为5,找到的数字为6,第四次查找,因为6小于7,所以向右查找,(left+right)/2=(6+6)/2=6,下标为6,找到的数字为7。


代码举例

#include <stdio.h>
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  // 下标       0 1 2 3 4 5 6 7 8 9
  int k = 7;//k是要查找的数字
  int i = 0;
  int sz = sizeof(arr) / sizeof(arr[0]);
  //折半查找(二分查找),前提是数组有序
  int left = 0;
  int right = sz - 1;
  int flag = 0;
  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);
      flag = 1;
      break;
    }
  }
  if (flag == 0)
    printf("找不到\n");
  return 0;
}


如果left是一个很大的数,right也是一个很大的数,left+right超出整形能表达的最大值,数据溢出,此时(left+right)/2所求的就不是最大值了这时要怎么办呢?

我们让多出的部分除以二在平分,如图所示


代码修改

#include <stdio.h>
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  //            0 1 2 3 4 5 6 7 8 9
  int k = 7;//k是要查找的数字
  int i = 0;
  int sz = sizeof(arr) / sizeof(arr[0]);
  //折半查找(二分查找),前提是数组有序
  int left = 0;
  int right = sz - 1;
  int flag = 0;
  while (left<=right)
  {
    int mid = left + (right - left) / 2;
    if (arr[mid] < k)
    {
      left = mid + 1;
    }
    else if (arr[mid] > k)
    {
      right = mid - 1;
    }
    else
    {
      printf("找到了,下标是:%d\n", mid);
      flag = 1;
      break;
    }
  }
  if (flag == 0)
    printf("找不到\n");
  return 0;
}


猜数字游戏

游戏说明

1.电脑生成一个1~100的的随机数

2.猜数字

猜大了 就告诉你:猜大了

猜小了 就告诉你:猜小了

猜对了 就告诉你:恭喜你,猜对了


猜数字游戏思想

  • 首先要打印一个菜单,选择开始游戏还是退出游戏
  • 其次,游戏应该可以玩完一局之后玩一局,为循环进行,利用循环语句构建框架


代码实现

打印菜单

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:
      printf("猜数字\n");
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误\n");
      break;
    }
  } while (input);
  return 0;
}


此时游戏过于简单,选择1要开始游戏,所以我们定义一个游戏函数game()

打印游戏函数

游戏第一步:生成随机数

rand()函数为生成随机数函数,头文件为<stdlib.h>

rand会返回一个0~327637之间的数

使用rand()要搭配srand() 一起使用,srand()是设置随机数生成器,一般用时间戳作为时间的种子,所以使用time函数来获取时间,然后将time函数转换为(unsigned)类型在传给srand函数

void game()
{
  //1. 生成随机数
  int ret = rand() % 100 + 1;//0~99+1-->1~100
  //2. 猜数字
  int guess = 0;
  while (1)
  {
    printf("请猜数字:>");
    scanf("%d", &guess);
    if (guess < ret)
    {
      printf("猜小了\n");
    }
    else if (guess > ret)
    {
      printf("猜大了\n");
    }
    else
    {
      printf("恭喜你,猜对了\n");
      break;
    }
  }
}


整体代码演示

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void menu()
{
  printf("*****************************\n");
  printf("*********   1. play  *******\n");
  printf("*********   0. exit  ********\n");
  printf("*****************************\n");
}
//
//rand函数会返回一个0~32767之间的随机数
//
//时间戳
void game()
{
  //1. 生成随机数
  int ret = rand() % 100 + 1;//0~99+1-->1~100
  //2. 猜数字
  int guess = 0;
  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));
    //给srand传一个时间戳,是生成的数字足够随机
  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;
}


游戏效果演示

目录
相关文章
|
15天前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
29 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
1月前
|
存储 C语言 开发者
C语言实战 | Flappy Bird游戏
【7月更文挑战第4天】Flappy Bird是由越南开发者制作的简单却极具挑战性的游戏,玩家需控制小鸟穿越水管障碍。游戏涉及角色初始化、显示和更新。小鸟和水管结构体存储数据,使用变量和数组。初始化小鸟和水管,显示背景、小鸟和水管,更新小鸟位置及碰撞检测。代码示例展示了小鸟和水管的状态管理,当小鸟与管道碰撞或触地时,游戏结束。游戏的成功在于其独特的虐心体验。
40 0
C语言实战 | Flappy Bird游戏
|
1天前
|
算法 编译器 C语言
【C语言篇】猜数字游戏(赋源码)
rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的⼤⼩是依赖编译器上实现的,但是⼤部分编译器上是32767。
|
1月前
|
存储 C语言
【C语言】猜数字小游戏
C语言实现猜数字小游戏
24 2
【C语言】猜数字小游戏
|
1月前
|
存储 编译器 C语言
C语言实战 | “贪吃蛇”游戏
【7月更文挑战第5天】在C语言实战中,本文档介绍了如何构建一个简单的“贪吃蛇”游戏。游戏的核心是控制蛇移动并增长,当吃掉食物时,蛇的身体变长。数据结构使用固定大小的数组表示蛇的位置,变量存储食物位置和蛇的长度。初始化后,利用非阻塞式`getKey()`函数实现WASD键盘控制蛇的运动方向。虽然蛇的边界检测和吃食物后的增长尚未详细说明,但提到了这些问题作为练习留给读者解决,并预告将在后续章节讨论模块化编程以简化复杂代码。
64 0
C语言实战 | “贪吃蛇”游戏
|
1月前
|
存储 数据管理 C语言
C语言实战 | 使用链表完成“贪吃蛇”游戏
【7月更文挑战第1天】整体思维,即系统思维,强调以整体视角理解事物。在编程中,结构体体现这种思想,将相关变量打包处理。示例展示了如何用链表而非数组实现“贪吃蛇”游戏,链表提供了更灵活的动态数据管理。一系列代码图片详细描绘了链表结构体在游戏中的应用,包括节点定义、移动、碰撞检测等,凸显了使用链表的优势和代码的清晰组织。
24 0
C语言实战 | 使用链表完成“贪吃蛇”游戏
|
2月前
|
程序员 C语言
C语言小游戏之猜数字
C语言小游戏之猜数字
26 5
|
2月前
|
存储 算法 C语言
二分查找算法的概念、原理、效率以及使用C语言循环和数组的简单实现
二分查找算法的概念、原理、效率以及使用C语言循环和数组的简单实现
|
2月前
|
算法 编译器 C语言
猜数字游戏C语言代码实现
猜数字游戏C语言代码实现
|
2月前
|
存储 C语言
C语言实战 | “贪吃蛇”游戏重构
在程序设计中,模块化思维至关重要,尤其对于复杂项目,它帮助分解任务,便于团队协作。以“贪吃蛇”游戏为例,游戏涉及两个角色:蛇和食物。使用数组存储蛇的位置,变量存储食物位置。游戏流程分为初始化、显示和更新数据。初始化时,食物位置随机,蛇的位置根据数组设定。显示数据则根据这些信息在屏幕上呈现角色。更新数据时,处理蛇的移动和增长以及食物的生成和消失。类似地,通过模块化方法可开发“打砖块”游戏,涉及球、球拍和砖墙,每个角色都有相应数据结构和更新逻辑。通过这种方式,游戏开发就像搭建积木,遵循框架逐步实现。
39 0
C语言实战 | “贪吃蛇”游戏重构