C语言怎么通过二分查找实现猜数字游戏
本文小编为大家详细介绍“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;}
但是这个代码的效率比较低,需要循环多次,所以我们需要用一个效率较高的方法:二分查找又叫 (折半查找)
二分查找的思想
给你一个有序的序列,取中间元素和目标元素进行对比,取其中的一半,丢弃另一半,快速缩小目标元素所在的位置。主要思想还是:快速缩小目标元素所在的区间。
二分查找的条件
序列必须是有序的,升序或者降序都可以
序列必须是顺序存储元素的,顺序存储元素主要是可以快速的获取中间元素(可以通过下标来找到元素)
二分查找的实现过程
分析:假设我们要找的数字为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 9int 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 9int 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~100的的随机数
猜数字
猜大了 就告诉你:猜大了
猜小了 就告诉你:猜小了
猜对了 就告诉你:恭喜你,猜对了
猜数字游戏思想
首先要打印一个菜单,选择开始游戏还是退出游戏
其次,游戏应该可以玩完一局之后玩一局,为循环进行,利用循环语句构建框架
代码实现
打印菜单
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;}
游戏效果演示
读到这里,这篇“C语言怎么通过二分查找实现猜数字游戏”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341