今天我们来实现一个简单的算法——二分查找,以及一个猜数字小游戏的实现。
目录
1.二分查找
我们就以猜数字小游戏为例,如果让大家猜一个1~100之间的数,大家认为怎样猜才是最快的呀?
没错,就是折半猜,1~100,我们就猜50,50小了,我们就将范围缩小到50~100了,这时候我们再猜75,如果75太大了,范围就进一步缩小到50~75了,一直折半猜,可以最大限度的缩小最终结果的范围,二分查找就是这个原理。
在用代码实现这个算法之前,我们需要补充一点点关于数组的知识:
首先是数组该如何定义:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int是数组的类型,arr是数组的名字,[10]表示我们定义数组的大小为10个整型。
等号后面是数组的内容,即我们把1~10存放到数组arr中。
现在我们来看一下如何访问数组的元素,数组元素是通过下标访问的,C语言规定,数组的下标是从0开始的,用Excel模拟了一下,大概如下:
因此,当我们想要访问arr数组第5个元素时,也就是5,我们应该找到下标为4的那个数组元素,即arr[4] = 5。
(add:关于数组更详细的内容,会在以后的文章提到哦,这里我们先大致理解就行)
OK,完成数组知识的小小补充,我们就正式开始二分查找的代码实现啦。
我们先理清一下思路,首先,我们还是定义一个长度为10并存放1~10的整型数组,还要定义一个变量来存储我们想要找的数(就定为7吧),我们将这个变量命名为key,此外我们还需要定义三个变量来存放数组第一个元素的下标(即0)、数组最后一个元素的下标(由数组长度而定)、我们要找的数的下标,我们分别将其命名为left、right和mid。
代码如下:
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;
// 数组总长度 / 单个数组元素的长度=数组的个数,数组个数-1=数组最后一个元素的下标
int key = 7;
int mid = 0;
因为我们并不能通过一次查找就能找到我们想要的数,因此我们需要一个循环,帮助我们不断进行查找,直到找到这个数为止,所以我们可以使用while循环,设定进入循环的条件为left<=right,进入循环后,因为是二分查找,所以我们需要找到中间那个元素,访问数组中间的元素需要通过数组下标来访问,因此我们要先得到中间元素的下标,即mid = (left+right)/2;此时我们就得到了数组中间元素的下标,那么中间元素就是arr[mid];再用if语句判断中间元素是不是我们要找的key,判断部分如下:
mid = (left + right) / 2;//得到中间元素的下标
if (arr[mid] > key)//若中间值比我们要猜的值大
{
right = mid - 1;//将中间值的下标减1赋给right,此时查找范围是left到mid-1
}
else if (arr[mid] < key)若中间值比我们要猜的值小
{
left = mid + 1;//将中间值下标加1赋给left,此时查找范围是mid+1到right
}
else//这里是arr[mid] = key,找到了,执行break跳出循环
break;
通过不断缩小范围,最终可以把范围锁定到我们要找的元素上,最后我们再进行输出,完整代码如下:
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;
int key = 7;
int mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] > key)
{
right = mid - 1;
}
else if (arr[mid] < key)
{
left = mid + 1;
}
else
break;
}
if (left <= right)
{
printf("找到了,下标是%d\n", mid);
}
else
printf("没找到\n");
return 0;
}
二分查找就讲到这里啦,感觉讲的还是有点不够清晰,看不懂的uu们可以在评论区提问哦,一定有问必答!
2.猜数字小游戏的实现
在讲这个小游戏前,要补充一下关于函数的一些小知识:
在C语言中,函数有库函数和自定义函数,库函数就是我们经常用的main函数、printf、scanf以及strlen之类,是C语言在设定时已经定义好的函数,自定义函数则是我们用户根据个人需求,自定义满足需求的函数。
那么,函数要如何定义呢?
返回类型 函数名(形参类型 形参名字)
{
函数体;
}
定义了函数,我们又要如何调用呢?
很简单,即 函数名(实参类型 实参名);
因为这个游戏需要用到的函数都是空类型,即void,且不需要传参,所以这个游戏中函数的调用就是函数名();
注意,函数需要先声明或先定义后再调用!
接下来就让我们开始游戏的编写吧!
首先我们需要一个游戏菜单,我们可以定义一个名字为menu的函数,让它打印出游戏菜单,后续我们只需要在main函数中调用menu函数就可以打印出菜单。代码实现如下:
void menu()
{
printf("*******************************\n");
printf("******* 1. play ************\n");
printf("******* 0. exit ************\n");
printf("*******************************\n");
}
现在我们要测试游戏逻辑,首先定义一个变量来接收我们的输入值,就命名为input,我们需要输入1的时候开始游戏,输入0的时候退出游戏,输入其他数字的时候就提示错误并返回游戏(这里要用到do while语句)。这时候大家有没有想到之前学过的某个语句呀?没错!就是switch语句,现在我们将代码实现一下:
int main()
{
int input = 0;
srand((unsigned)time(NULL));//生成随机数,有点复杂,后续再细讲
do
{
menu();//调用menu函数,打印菜单
printf("请选择:>");//提示输入
scanf("%d", &input);
switch (input)
{
case 1:
game();//调用game函数,函数内是游戏的具体代码实现
break;
case 0:
break;//输入0直接退出游戏
default:
printf("输入有误,请重新输入!");
break;//跳出switch语句,又因为输入的数非0,重新进入do while循环
}
} while (input);
return 0;
}
具体的游戏逻辑就是这样啦,现在就差猜数字的具体代码实现啦,也就是game函数的定义。
在game函数中,我们需要定义一个变量来接收生成的随机数,命名为random_num,并且对随机数的范围进行调整,我们要猜的数区间是1到100,那么我们只需要将生成的随机数%100,就可以使随机数的范围落在0到99之间,再加上1,就是1到100了,然后还是定义一个名为input的变量接收我们的输入值,再将我们输入的值(即input)同random_num进行比较,在这个过程中,显然我们并不能做到一次就猜中结果,因此我们需要一个循环,让我们能够多次进行猜数字,程序进行多次比较,直到猜中结果,game函数代码如下:
void game()
{
int random_num = rand() % 100 + 1;
int input = 0;
while (1)
{
printf("请输入你想猜的数字>:");
scanf("%d", &input);//输入值
if (input > random_num)//大于要猜的数
{
printf("猜大了\n");//提示猜大了
}
else if (input < random_num)//小于要猜的数
{
printf("猜小了\n");//提示猜小了
}
else
{
printf("恭喜你,猜中了!\n");
break;//猜中了,跳出循环,执行game()后面的break语句,开始下一局游戏
}
}
}
OK,猜数字小游戏就这样完成啦,下面是完整的代码:
#include<stdio.h>
#include<stdlib.h>//使用srand函数需要包含的头文件
#include<time.h>//生成随机数需要包含的头文件
void menu()
{
printf("*******************************\n");
printf("******* 1. play ************\n");
printf("******* 0. exit ************\n");
printf("*******************************\n");
}
void game()
{
int random_num = rand() % 100 + 1;
int input = 0;
while (1)
{
printf("请输入你想猜的数字>:");
scanf("%d", &input);
if (input > random_num)
{
printf("猜大了\n");
}
else if (input < random_num)
{
printf("猜小了\n");
}
else
{
printf("恭喜你,猜中了!\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入有误,请重新输入!");
break;
}
} while (input);
return 0;
}
我们来运行一下看看:
游戏界面:
输入1开始游戏 :
游戏过程:
哈哈,猜的过程有点困难QAQ
可以看到当我猜中之后,它就返回游戏菜单开始下一轮游戏了
uu们回头也可以自己去玩一下哦,玩自己做出来的游戏还是有点小小的成就感的!
3.for循环打印九九乘法表
相信看完前面两个,大家都有点累了,再坚持一会儿,已经来到这篇文章的最终部分啦,也是最简单的部分。
利用for循环打印九九乘法表,实际上就是for循环的嵌套使用。
我们直接通过代码来分析:
#include<stdio.h>
int main()
{
int i = 0;//定义i变量来控制行数
for (i = 1; i <= 9; i++)//依次打印1到9行
{
int j = 0;//定义j变量来控制列数
for (j = 1; j <= i; j++)//j<=i,即有几行就打印几列
{
printf("%d*%d=%-2d ", i, j, i * j);//%-2d的意思是打印两位靠左对齐,如果是%2d则是靠右对齐,这是占位符的使用,为了美观
}
printf("\n");//打印完一行后换行,继续打印
}
return 0;
}
运行结果:
今天的内容就到这里啦,下期不出意外应该是会介绍C语言函数的内容,这部分内容会比较多,且有难度,要一起坚持下去哦
uu们要是有哪里看不懂可以在评论区留下问题哦,我看到了一定会及时回复的。
如果觉得我的文章对你们有帮助的话,麻烦动动小手点个赞哦
你们的喜欢就是我创作的动力o V o