前言:讲解顺序: 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');
}
希望大家能够有所收获,同时上面的确认周围雷个数的函数可以用循环来写,我不用循环写是为了让大家能够更直观的明白代码意图。