?前言:
扫雷的基本原理是系统会随机生成几个雷,当你点开盲区的时候,如果不是雷,他会显示周围一圈雷的个数,下面是一个9*9范围的c语言实现的扫雷的代码(由于后面会对输入的坐标一圈进行扫面,以最左边为例,如果数组是9*9的,会越界访问,所以要将数组的大小放大一圈为11*11的)
目录
1.游戏的菜单
?2:扫雷的雏形之数组初始化
3:扫雷的雏形之展示数组以及一些细节
?4:扫雷之放置雷
?5:扫雷之排除雷
6:全部代码
1.游戏的菜单
这个很基础
do? while循环停止的条件是输入0即while(0)停止循环,而输入0正好是退出,这样就符合逻辑了
void menu() {
printf("************************\n");
printf("******* 1 .play ******\n");
printf("******* 0 .exit ******\n");
printf("************************\n");
}
int main() {
int input;
do {
menu();
printf("亲选择\n");
scanf("%d", &input);
switch (input) {
case 1:
printf("开始游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
defaule :
printf("请重新输入\n");
break;
}
} while (input);
}
?2:扫雷的雏形之数组初始化
在这里我们需要创建两个字符类型的二维数组,以及对其初始化,一个用来存放后面随机生成的雷,一个用来存放排查雷。
由于会多次用到IntiBoard这个函数,所以将不同的字符传进去便于对两个数组的初始化
void game() {
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷的个数
//初始化
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
}
//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols,char temp) {
int i = 0;
for (i = 0; i < rows; i++) {
int j = 0;
for (j = 0; j < cols; j++) {
board[i][j] = temp;
}
}
}
3:扫雷的雏形之展示数组以及一些细节
//展示
DisplayBoard(mine, ROW, COL);
printf("\n");
DisplayBoard(show, ROW, COL);
?展示数组这个函数里面有一些细节需要注意
细节一:由于数组是11*11的,但是我们只要中间的9*9部分的内容,所以,我们要对已经初始化的数组进行范围性打印,即打印下标为1到ROW 行以及下标为1到COL列的数组元素
细节二: 为了玩家方便输入坐标,我们要标出元素所在的第几行和第几列
行很好办,只需在打印每行的时候把i打印出来
而列需要在打印数组的时候单独打印
代码如下:
//展示
//想打印中间的9*9内容,只需要对11*11的二维数组选择性打印即可
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
for (int i = 0; i <= col; i++) {//打印是第几列
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);//通过每次for循环,打印出是第几行
for (int j = 1; j <= col; j++) {
printf("%c ",board[i][j]);
}
printf("\n");
}
}
?后面我们只会展示排雷的数组,放置雷的数组不会被展示出来
?4:扫雷之放置雷
这里我们之前创建的mine[ROW][COL]这个数组就用上了,它用来存放随机生成的雷
注意:现在展示这个函数要放在放置雷这个函数之后
我们用宏定义 EASY_COUNT 10定义了雷 的数量为10
void game() {
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷的个数
//初始化
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//展示
/*DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);*/
//放置雷
InSet(mine, ROW, COL);
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
}
?这里又用到了rand函数,rand()%9代表他会随机生成0~8的数字
但是要调用srand函数才能做到真正的随机数,别忘了引用相关的头文件
#include<stdlib.h>
#include<time.h>
srand((unsigned int)time(NULL));//每个项目只需要引用一次就可以。
#define EASY_COUNT 10
?这个同三子棋的道理相同,首先要判断下放置雷的位置有没有雷,然后再放置,循环的条件为count也就是雷的数量,当count=0时,循环终止,放置了10个雷
//放置雷
void InSet(char board[ROWS][COLS], int row, int col) {
int x;
int y;
int count = EASY_COUNT;
while(count){
x = rand() % row + 1;//rand()%row的范围是0-row-1,而最后一行的数组下标是board[9],所以要加一
y = rand() % col + 1;
if (board[x][y] != '1') {
board[x][y] = '1';
count--;
}
}
}
?5:扫雷之排除雷
这步很关键,可以说时整个扫雷游戏的核心
//排除雷
FindMine(mine, show, ROW, COL);
首先我们需要将这两个数组都传进来
我们通过输入的坐标在mine这个数组中确定该坐标周围的雷的数量,并将雷的数量放到show这个数组所对应在mine数组中的位置
注意:1 这个函数的参数分别时mine,x,y 代表着把该点周围雷的数量返回去
? ? ? ? ? ?2 由于数组是char 类型的,所以通过count+'0'把整形count变成字符型的‘count’,代码的注释中有解释,这里不过多介绍
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
int count = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j<= y + 1; j++) {
if (mine[i][j] =='1') {
count++;
}
}
}
return count;
}
//排除雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x;
int y;
while (1) {
printf("请输入坐标;\n");
scanf("%d%d", &x, &y);
//判断坐标是否存在
if (x >= 1 && x <= row && y >= 1 && y <= col) {
//判断是否是雷
if (mine[x][y] == '1') {
printf("很遗憾,你被炸死了!!!\n");
DisplayBoard(mine, ROW, COL);
break;
}
else {//这点很重要!!!
//这个函数的功能时找出x,y坐标周围有几个雷
int count = GetMineCount(mine, x, y);
//将雷的个数赋值给show这个数组
//元素在mine数组和show数组中的位置相同
show[x][y] = count + '0';//在ASCLLII中'3'-'0'=3,所以count+'0'代表着’count'
DisplayBoard(show, ROW, COL);
}
}
else {
printf("请重新输入;\n");
}
}
}
?
?
?
6:全部代码
0 game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10
//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols,char temp);
//展示
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//放置雷
void InSet(char board[ROWS][COLS], int row, int col);
//排除雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
1 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];//存放雷
char show[ROWS][COLS];//排查雷的个数
//初始化
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//展示
/*DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);*/
//放置雷
InSet(mine, ROW, COL);
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//排除雷
FindMine(mine, show, ROW, COL);
}
int main() {
srand((unsigned int)time(NULL));//每个项目只需要引用一次就可以。
int input;
do {
menu();
printf("亲选择\n");
scanf("%d", &input);
switch (input) {
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("请重新输入\n");
break;
}
} while (input);
}
2 game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols,char temp) {
int i = 0;
for (i = 0; i < rows; i++) {
int j = 0;
for (j = 0; j < cols; j++) {
board[i][j] = temp;
}
}
}
//展示
//想打印中间的9*9内容,只需要对11*11的二维数组选择性打印即可
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
printf("-------------------------------\n");
for (int i = 0; i <= col; i++) {//打印是第几列
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);//通过每次for循环,打印出是第几行
for (int j = 1; j <= col; j++) {
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("-------------------------------\n");
}
//放置雷
void InSet(char board[ROWS][COLS], int row, int col) {
int x;
int y;
int count = EASY_COUNT;
while(count){
x = rand() % row + 1;//rand()%row的范围是0-row-1,而最后一行的数组下标是board[9],所以要加一
y = rand() % col + 1;
if (board[x][y] != '1') {
board[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
int count = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j<= y + 1; j++) {
if (mine[i][j] =='1') {
count++;
}
}
}
return count;
}
//排除雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x;
int y;
while (1) {
printf("请输入坐标;\n");
scanf("%d%d", &x, &y);
//判断坐标是否存在
if (x >= 1 && x <= row && y >= 1 && y <= col) {
//判断是否是雷
if (mine[x][y] == '1') {
printf("很遗憾,你被炸死了!!!\n");
DisplayBoard(mine, ROW, COL);
break;
}
else {//这点很重要!!!
//这个函数的功能时找出x,y坐标周围有几个雷
int count = GetMineCount(mine, x, y);
//将雷的个数赋值给show这个数组
//元素在mine数组和show数组中的位置相同
show[x][y] = count + '0';//在ASCLLII中'3'-'0'=3,所以count+'0'代表着’count'
DisplayBoard(show, ROW, COL);
}
}
else {
printf("请重新输入;\n");
}
}
}
|