二分查找、猜数字游戏思路详解、选择语句与循环句练习

目录:

           1、二分查找

           2、猜数字游戏思路详解

           3、选择语句与循环语句练习


一、二分查找\折半查找

 1、算法是想:

二分查找又称折半查找,适合对有序的数据集合进行查找,时间复杂度为O(log2n),效率高。对一升序的数据集合,先找出升序数据集合最中间的元素,将数据划分为两个子集,将最中间的元素和关键字进行比较,如果相等则返回,如果大于关键字,则在前边数据子集中查找,如果小于反之,直至找到。

2、查找步骤

(1)、首先确定查找区间的中间位置(假定是一个升序的数组),那么mid = left+(right-left)/2;

(2)、为了防止越界用待查找值与中间位置值进行比较。

             <1>、若相等,则找到,输出。

             <2>、若大于、则在后半区域中继续进行折半查找

             <3>、若小于、则在前半区域中继续进行折半查找

 (3)、查找成功,则返回关键字的数组下标。

3、图解

二分查找、猜数字游戏思路详解、选择语句与循环句练习_第1张图片分析:一共尽力三次查找,第三次查找,7比中间值大,left=mid+1,使right=left,查找结束。第一次mid=4,5<7,则left=mid+1=5,继续在右侧折半查找,第二次mid=7,8>7,则right=mid-1=6,继续在左边侧折半查找。第三次mid=5,6<7,left=mid+1;left=right,找到7,下标为6。

4、代码演示: 

#include
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int a = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = a - 1;	int k = 0;
	scanf("%d", &k);
	while (left <= right)
	{
		//int mid = (left + right) / 2; //这句代码放在这里,每次循环后改变mid的值
        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);
			break;
		}
	}
	if (left > right)
		printf("找不到\n");
	return 0;
}

 补充:上边红字部分

我们都知道二分查找在最坏的情况下依次是n/2,n/4,n/8....... 一直到1为止。在这种情况下,要循环多少次才能找到目标数呢,我们假设是x次。我们可以看到每次都乘以1/2,所以可以根据题意列出下面等式:

二分查找、猜数字游戏思路详解、选择语句与循环句练习_第2张图片

 通过计算:

最后就是:

              


 二、猜数字游戏思路详解

 1、整体思路:

  1、 通过电脑生成1~100之间的数字

  2、 猜数字  
  3、如果你猜小了,告知你猜小了
  4、 如果你猜大了,告知你猜大了
  5、如果你猜大了,告知你猜大了
  6、 如果你猜对了,告知你猜对了 

2、实现过程:

<1>、打印菜单 

输入1开始游戏,输入2退出游戏。

void menu()
{
    printf("******************************\n");
    printf("**********  1.play  **********\n");
    printf("**********  0.exit  **********\n");
    printf("******************************\n");
}

 2、游戏逻辑

void game()//游戏逻辑:
                                  
{
    int guess = 0;
            //1、生成随机数
    int ret = rand()%100+1 ;
    
            //2、猜数字
    while (1)
    {
        printf("请猜数字:>");
        scanf("%d", &guess);
        if (guess < ret)
        {
            printf("猜小了\n");
        }
        else if (guess > ret)
        {
            printf("猜大了\n");
        }
        else
        {
            printf("恭喜你,猜对了\n");
            break;
        }
    }
}
int main()
{
                                    
    srand((unsigned int)time(NULL)); //srand只需要调用一次
    int input = 0;
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            printf("猜数字\n");
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误,重新选择!\n");
            break;
        }
    } while(input);
    return 0;
}

注释: C语言中,生成随机数需要函数rand和srand一起使用

          1、rand函数

              函数原型:void rand(void),rand(void)表示rand函数没有参数

              属于头文件

              rand()会返回一个范围在0~RAND_MAX(32767)之间的随机数(整数)。

                                                                                                    

2、srand函数 

函数原型:void srand (usigned int seed)

属于头文件

函数srand()用来设置函数rand()产生随机数时的随机数种子,参数seed是函数rand()种子, 用来初始rand()的起始值。

 3、可以认为rand()在每次被调用的时候,它会查看:

 <1>、 如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用   

             srand(seed)一次来初始化它的起始值。
 <2>、 如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。


                          3的原文链接:https://blog.csdn.net/boatalways/article/details/27681119


 根据以上:rand里面的种子没有设定,或者设定成一个定值,那么每次产生随机数是一样的。那么下面就给出时间戳的概念,在c语言中time函数可以生成c语言当前时间的时间戳。                        

4、time函数 

           

函数原型:time_t time (time_t* timer);(time_t是针对时间的返回值类型,也是整型)

属于头文件

在这里用来给srand函数做参数,给srand时刻都改变的参数。

     

 5、用时间戳做srand的参数  srand((unsigned int)time(NULL));
 在这里不想使用time的参数,给time传一个空指针(NULL);
 time函数的返回类型是 time_t,srand需要的参数是unsigend int型,这里需要将 

 time的返回类型(time_t)强转成(unsigned int)
 这样就可以调用time函数给srand函数设参;time_t类型本质上是整型。 

                  这样rand里面的种子就随着系统时间的改变而改变。


 三、循环语句与选择语句的练习

 1、 判断一个数是否为奇数                 

#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
	int a = 0;      //给变量在内存中申请空间
	scanf("%d", &a);//在这里"%d ",%d不能加空格,这样导致在输入变量a的值后,按enter键后不能跳出 
                    //判断结果。
	if (0=a%2)      //0==a%2这样写更规范,防止出现漏写=,出现给a%2=0(赋值)的情况,出现0=a%2的 
                    //情况,编译器调试不会通过,有利于及时找到错误。
	{
		printf("是偶数\n");
	}
	else
	{
		printf("是奇数\n");
	}
	return 0;
}

 2、输出1-100之间的奇数,并写出其个数。

方法一:
#include
int main()
{
	int i = 0;
	int a = 0;
	for (i = 1; i < 100; i++)
	{
		if (1 == i % 2)//用来判断是否为奇数
		{
			a++;             //用来判断奇数的个数。
			printf("%d ", i);//用{}将a++和printf括起来,放在一个代码块中,if就可以控制这两条 
                             //语句,若果不加{}那么printf会将每次的结果都输出
		}
		//if(1 == i % 2)
		//	printf("%d ", i);
		//a++;               //如果将a++放在这里并且没加{},那么他的意义就不是计算技术的个 
                             //数,而是计算循环次数。
	}
	
	printf("奇数的个数为%d\n", a);//这个printf放在if语句外面,不然每循环一次输出一个a,达不到 
                                 //数个数的目的

	return 0;
}

方法二:
#include
int main()
{	
    int a = 0;
	int i = 0;
	while (i<100)        //这里i<100而不是i<=100;是为了确保是100以内的数字,
	{
	      a++;
		if (1 == i % 2)  //判断是否为奇数
		  printf("%d\n", i);
          i=i+2;	
	}
    printf("共输出了%d个数",a);
	return 0;
}

第二种while循环方式相比第一种,循环次数减少,代码效率更高

3、计算n的阶乘


#include
int main()
{
	int i = 0;
	int a = 0;
	int sum = 1;
	scanf("%d", &a);
	for (i = 1; i <= a; i++)//这里将用户输入值当作判断量
	{
		sum = sum * i;
		
	}
	printf("%d", sum);      //放在for循环外边,是将循环最终停止sum的最终结果输出。
	                        //若放在for循环中,每次循环sum的结果都会输出
	return 0;
}

 4、计算1!+2!+3!+.....+n!

      方法一:


#include
int main()
{
	int i = 0;
	int a = 0;
	int sum = 1;
	int cpp = 0;
	scanf("%d", &a);
	for (i = 1; i <= a; i++)
	{
		sum = sum * i;
		cpp = cpp + sum;//将cpp变量写在这里,是将每次循环sum的值进行相加,sum=sum*i计算的就是 
                        //阶乘

	}
	printf("%d", cpp);
	return 0;
}

   方法二: 

#include
int main()
{
	int i = 0;
	int j = 0;
	int sum = 1;
	int cpp = 0;
	for (j = 1; j <= 3; j++)       //当j++是几就求的是几的阶乘
	{
		sum = 1;                   //这里确保每次进入循环sum都是1
		for (i = 1; i <= j; i++)   //这个循环会算出i的阶乘
		{
			sum = sum * i;         //每次循环sum都会被赋值,出这个for循环时sum都会保有上一次循 
                                   //环的值
		}
		cpp = cpp + sum;
	}
	printf("%d ", cpp);
	return 0;
}

方法二思路: 外部for循环,如果j++等于3,外部for循环实际让循环体循环3次,
                      外部循环3次,那么内部for循环要循环6次,分别求1!,2!,3!
                      根据外部for循环的循环体可以计算出1到3的阶乘和。
 

你可能感兴趣的:(C语言,游戏,java,servlet)