番外篇之扫雷,冒泡排序,找鞍点问题-->详解

前言:讲解顺序: 1  我们先把上次留下的练习题先讲解一遍

                              2  冒泡排序和鞍点问题

                              3  扫雷游戏

1 上次的习题

输入a-b之间的素数:

法一:

//试除法,一个一个排查
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	int count = 0;//计算素数个数
	scanf("%d%d", &a, &b);//a<b
	int i = 0;
	int j = 0;
	for (i = a; i <= b; i++)
	{
		for (j=2; j < i; j++)
		{
			if (i % j == 0)
				break;
		}
		if (j >=i)
		{
			printf("%d ", i);
			count++;
		}
	}
	printf("\n");
	printf("%d", count);
	return 0;
}

法二:

//这里我们效率提高了,如果开平方的数中有一个数能被整除就证明它不是素数
//比如16=4*4 15=3*5 
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
int main()
{
	int a = 0;
	int b = 0;
	int count = 0;//计算素数个数
	scanf("%d%d", &a, &b);//a<b
	int i = 0;
	int j = 0;
	for (i = a; i <=b; i++)
	{
		for (j=2; j < sqrt(i); j++)
		{
			if (i % j == 0)
				break;
		}
		if (j ==i)
		{
			printf("%d ", i);
			count++;
		}
	}
	printf("\n");
	printf("%d", count);
	return 0;
}

2 冒泡排序

上面九组数需要比较8次才能把最大的数排在后面,当最大的数排在后面的时候,我们就不用管最后一个最大的数了,紧接着只需要比较前8组数,也就是比较7次,以此类推

代码演示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
//我们这里就讲升序排列,降序的方法是一样的。
int main()
{
	int i = 0;
	int j = 0;
	int n = 0;
	scanf("%d", &n);//这里输入你想要几个数进行升序或者降序排列
	int arr[100] = { 0 };//这里把数组的长度弄大一点,可以让你输入更多的数,以免溢出
	for (; i < n; i++)
	{
		scanf("%d",&arr[i]);//将数存进数组
	}
	for (i = 0; i < n; i++)//这里对每个数进行比较
	{
		for (j = 0; j < n - i- 1; j++)//这里是比较的趟数
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	for (i=0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

这里我随便列举了几个数来展示运行的结果:

2-2 能力提升

二元数组找鞍点

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int n = 0;
	int i = 0;//行
	int j = 0;//列
	int min = 0;
	int max = 0;
	int x = 0;
	int y = 0;
	int m = 0;
	int count = 0;
	scanf("%d", &n);//n阶矩阵
	//用二元数组来先接收这些数
	//由于VS编译器不支持变长数组,所以我们将数组的长度拉大一点
	int arr[10][10] = { 0 };
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
	//下面的步骤开始找是否存在行最大,列最小的数
	//先找行最大,再找列最大
	for (i = 0; i < n; i++)
	{
		int max = arr[i][0];
		for (j = 0; j < n; j++)
		{
			if (max <= arr[i][j])
			{
				max = arr[i][j];
				x = i;
				y = j;
			}

		}
		int min = max;
		for (m = 0; m < n; m++)
		{
			if (min > arr[m][y])//如果发现min一旦大于这列某个数之间跳出,说明这个数不是的
				break;
		}
		if (m == n)
		{
			printf("找到了\n行是:%d\n列是:%d", x, y);
			count = 1;//这里是卡点,需要设置一个数count,来确定是否存在鞍点,如果count=1,就存在,如果不是1就不存在
		}
	}
	if (count != 1)
		printf("NONE");
	return 0;
}

但是这种代码无法解决两个相同的数的如果都是鞍点的问题

缺陷也很明显,但是根据题目要求至多存在一个鞍点,也就是要么只有一个,要么不存在

这里不过多延申,重点还是回到今天的内容讲解。

3 扫雷游戏初阶(如果你弄懂了我前面讲的三子棋,这个简直就是so easy,如果没有弄懂的话,希望大家能够熟悉每一个步骤然后自己花点时间写一下)

步骤:

1跟猜数字游戏和三子棋一样先设置进入游戏的设置

2进入游戏后初始化棋盘

3打印棋盘

4布置雷区

5扫雷函数

(重要提醒:我的坐标输入是先输入纵坐标,然后再输入横坐标,大家可以适当改一改。)

//头文件里面 game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE 10
void Printboard(char arr[ROWS][COLS],int row,int col);
void Initboard(char arr[ROWS][COLS],int row,int col,char ret);
void Setmine(char arr[ROWS][COLS]);
void Judgemine(char arr[ROWS][COLS],char board[ROWS][COLS], int row, int col);
//源文件test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
	printf("**********************************************\n");
	printf("***********         1 play         ***********\n");
	printf("***********         0 exit         ***********\n");
	printf("**********************************************\n");
}
void game()
{
	//先初始化棋盘
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS,'0');
	Initboard(show, ROWS, COLS,'*');
	//Printboard(mine,ROW,COL);//隐藏区,取决于你自己到底看不看
	Printboard(show, ROW, COL);//展示区
	//布置雷区
	Setmine(mine);
	//输入坐标判断是否为雷
	Judgemine(mine,show, ROW, COL);
	//判断是否赢了
}
int main()
{
	srand((unsigned)time(NULL));
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏");
			break;
		default:
			printf("请重新输入:");
		}
	} while (input);
	return 0;
}
//源文件,启动游戏代码game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void Initboard(char arr[ROWS][COLS],int rows,int cols,char ret)//棋盘初始化
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = ret;
		}
	}
}

void Printboard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}
void Setmine(char arr[ROWS][COLS])
{
	
	int count = MINE;
	while (count)
	{
		int x = rand() % 9 + 1;//这里的坐标必须放在循环里面,不然放在外面随机坐标只有一个
		int y = rand() % 9 + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
	//Printboard(arr, ROW, COL);//雷区展示,取决你自己是否想看
}
void Judgemine(char arr[ROWS][COLS], char board[ROWS][COLS],int row, int col)
{
	int x = 0;
	int y = 0;
	int i = 0;
	int j = 0;
	int win = 0;
	char sum = '0';
	while (1)
	{
		printf("扫雷\n");
		printf("输入你要下的坐标:");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//卡壳点:如何让棋盘露出展现区,并且翻出坐标后
		{

			if (arr[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Printboard(arr, ROW, COL);//看雷区
				break;
			}
			else
			{
				int count = getmine(arr,x,y);
				board[x][y] = count+48;
				Printboard(board, ROW, COL);//展示区
				win++;//这里计算排雷的次数,如果达到71次就算成功
			}
			if (win == col * row - MINE)
			{
				printf("排雷成功");
				Printboard(arr, ROW, COL);
			}
		}
		else
			printf("你输入的坐标不合法请重新输入:");
	}

}
int getmine(char arr[ROWS][COLS], int x, int y)
{
	return (arr[x - 1][y - 1] + arr[x - 1][y] + arr[x - 1][y + 1]
		+ arr[x][y - 1] + arr[x][y + 1]
		+ arr[x + 1][y - 1] + arr[x + 1][y] + arr[x + 1][y + 1]-8*'0');
}

希望大家能够有所收获,同时上面的确认周围雷个数的函数可以用循环来写,我不用循环写是为了让大家能够更直观的明白代码意图。

猜你喜欢

转载自blog.csdn.net/2301_79811170/article/details/134129980
今日推荐