分享好友 编程语言首页 频道列表

C语言通过二分查找实现猜数字游戏

C/C++教程  2023-02-09 05:010

二分查找

题目: 在一个有序数组中查找具体的某个数字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。

C语言通过二分查找实现猜数字游戏

代码举例

#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所求的就不是最大值了这时要怎么办呢?

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

C语言通过二分查找实现猜数字游戏

代码修改

#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");
}

打印结果

C语言通过二分查找实现猜数字游戏

打印主函数

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函数

C语言通过二分查找实现猜数字游戏

C语言通过二分查找实现猜数字游戏

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;
}

游戏效果演示

C语言通过二分查找实现猜数字游戏

以上就是C语言通过二分查找实现猜数字游戏的详细内容,更多关于C语言猜数字的资料请关注其它相关文章!

原文地址:https://blog.csdn.net/2201_75366661/article/details/128838309

查看更多关于【C/C++教程】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
Rust应用调用C语言动态库的操作方法
目录外部功能接口FFIUDP套接字的读超时Rust调用C语言动态库中的函数避免重复造***,使用Rust官方C语言库外部功能接口FFI虽然高级(脚本)编程语言的功能丰富,表达能力强,但对底层的一些特殊操作的支持并不完善,就需要以其他编程语言来实现。调用其他编程语

0评论2023-02-09585

Delphi中获取Unix时间戳及注意事项(c语言中time()是按格林威治时间计算的,比北京时间多了8小时)
uses DateUtils;DateTimeToUnix(Now) 可以转换到unix时间,但是注意的是,它得到的时间比c语言中time()得到的时间大了8*60*60这是因为Now是当前时区的时间,c语言中time()是按格林威治时间计算的,北京时间比格林威治时间多了8小时DateTimeToUnix(Now)-8*60*

0评论2023-02-09876

Unicode与UTF-8互转(c语言和lua语言) python utf-8转unicode
1. 基础1.1 ASCII码我们知道, 在计算机内部, 全部的信息终于都表示为一个二进制的字符串. 每个二进制位(bit)有0和1两种状态, 因此八个二进制位就能够组合出 256种状态, 这被称为一个字节(byte). 也就是说, 一个字节一共能够用来表示256种不同的状态, 每个状态

0评论2023-02-09468

R语言之merge详解 c语言merge函数代码
merge是R语言中用来合并数据框的函数merge函数的声明:?1234merge(x, y, by = intersect(names(x), names(y)),      by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all,      sort = TRUE, suffixes = c(".x"

0评论2023-02-09489

R语言调用的C语言源代码查询 R语言 c
R语言使用时可以调用自己写的C代码,但是有些C函数是软件包自带的,怎么查询在使用软件包 kerfdr 时,涉及到一个函数y = .C("massdist", x = as.double(xtrunc), xmass = as.double(tau[trunc]/sum(tau[trunc])), nx = nx, xlo = as.double(lo), xhi = as.dou

0评论2023-02-09487

centos安装与配置R语言 centos配置c语言环境
Linux下安装R语言一、编译安装      由于采用编译安装,所以需要用到gcc编译环境,在编译前check文件时还会用到libXt-devel和readline-devel两个依赖,所以在编译R语言源码时先将这些工具和依赖包准备好。readline-devel 也可以不安装,不安装此包R语言编

0评论2023-02-09905

C语言利用链表实现学生成绩管理系统
链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示

0评论2023-02-09722

C语言通过三种方法实现属于你的通讯录
目录一、基础版本1.1 通讯录的个人信息(结构体来实现)1.2通讯录名单1.3人员初始化1.4菜单1.5主函数二、功能的实现2.1、增加人数2.2、删除人数2.3、查找2.4、展示2.5、排序(这里我是通过名字)三、通讯录进阶(设置动态存储)3.1通讯录从静态改为动态3.2通

0评论2023-02-09881

C++集体数据交换实现示例讲解 c语言两个数据交换
目录一、说明二、示例和代码一、说明到目前为止介绍的功能共享一对一的关系:即一个进程发送和一个进程接收。链接是通过标签建立的。本节介绍在多个进程中调用相同参数但执行不同操作的函数。对于一个进程,函数可能会发送数据,对于另一个进程,它可能会接收

0评论2023-02-09687

C语言中#if的使用 c语言中%c
目录#if定义#if使用#if的后面接的是表达式#if defined的使用ifdef的使用结尾#if定义#if和#endif是一组同时使用的,叫做条件编译指令。#if与#define、#include等指令一样是由预处理器这个强大的工具处理的,预处理器可以在编译前处理c程序。#if使用#if的后面接

0评论2023-02-09343

更多推荐