扫雷是个老幼皆宜的游戏
它的玩法是 在一个9×9(初级)、16×16(中级)、16×30(高级)或自定义大小的方块矩阵中随机布置一定量的地雷(初级为10个,中级为40个,高级为99个),再由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束。
了解了它的玩法后,让我们想想如何用C语言实现它呢?(以9*9为例)
1.制作menu菜单
2.定义2个char类型的数组mine[ ] 和show[ ],
mine数组用来存储雷的位置信息,show数组用来存储非雷位置周围雷的个数的信息
3.对mine和show数组进行初始化
mine数组全部初始化为字符0,show数组全部初始化为字符*,
4.布置雷并将信息存储在mine数组中,雷的位置由字符0改为字符1
5.排雷
6.打印数组
菜单界面就像餐厅里服务员递给你的菜单,根据菜单里的内容进行选择
选择1,开始游戏;选择0,结束游戏
void menu()
{
printf("**********************\n");
printf("****** 1. play *****\n");
printf("****** 0. exit *****\n");
printf("**********************\n");
}
首先,我们会创建2个char类型的数组mine[ ] 和show[ ],
mine数组用来存储雷的位置信息,show数组用来存储非雷位置周围雷的个数的信息
char mine[9][9] = { 0 };
char show[9][9] = { 0 };
但由于我们想实现多行多列扫雷,也为了以后修改行数、列数和雷的个数的方便,
不妨使用#define宏定义
#define ROW 9//行
#define COL 9//列
#define LANDMINE 10//雷的个数
又为了后面搜索非雷位置周围的信息的方便(如9*9数组的最外边的两行两列因四周不足8个位置,所以在后面搜索非雷位置周围的信息同时,还要判断周围位置是否越界),不妨在原有数组的基础上,再加两行两列,它们在mine数组中全部初始化为字符0(这样就不用判断某个位置的周围位置是否越界)
#define ROWS ROW+2
#define COLS COL+2
定义两个数组后,接着将它们初始化
mine数组全初始化为字符0,show数组全部初始化为字符*,用set接收字符0和 *
Initiate_board(mine, ROWS, COLS, '0');
Initiate_board(show, ROWS, COLS, '*');
void Initiate_board(char mine[ROWS][COLS], int rows, int cols, char set)
{
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
mine[i][j] = set;
}
Set_mine(mine, ROW, COL);
1.注意,布置雷只用在上图浅蓝色的9*9区域,深蓝色的区域不用使用,所以传参时传的是原本的行和列row和col,而非是加了两行两列的rows和cols
2.布置n个雷即要生成n个不同的符合要求的随机坐标,所以要使用rand()函数,而使用的前提是使用了srand()函数,所以为了实现能生成n个随机坐标,则要在主函数里调用一次srand((unsigned int)time(NULL));
void Set_mine(char mine[ROWS][COLS], int row, int col)
{
int i = 0;
while (i < LANDMINE)
{
int x = rand() % row + 1;//使得x的范围在1--row
int y = rand() % col + 1;//使得y的范围在1--col
if (mine[x][y] == '0')
{
mine[x][y] = '1';
i++;
}
}
}
Display_board(mine, ROW, COL);
打印数组时,只用打印上图的浅蓝色区域,深蓝色区域不用打印,所以传参时传的是原本的行和列row和col,而非是加了两行两列的rows和cols
为了使我们能快速知道某个位置是第几行第几列,可以采用如下代码
void Display_board(char mine[ROWS][COLS], int row, int col)
{
int i, j;
printf("\n----------扫雷----------\n");
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 ", mine[i][j]);//打印数组
printf("\n");
}
printf("----------扫雷----------\n");
printf("\n");
}
先输入一个坐标,在mine数组里判断该位置是否是雷(即该位置是否为字符1),如果是,则提示“很遗憾,您被炸死了”;若不是,则查找周围位置有几个雷,并将雷的个数传到show数组的对应位置
Search_mine(mine, show, ROW, COL);
int Search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y;
int i = 0;
while (i < ROW * COL - LANDMINE)//ROW * COL - LANDMINE表示非雷的个数
{
printf("请输入想要查找的位置:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')//踩到炸弹后,直接退出循环
{
printf("\n很遗憾,您被炸死了\n");
Display_board(mine, ROW, COL);
break;
}
else if (show[x][y] != '*')
{
printf("该位置已排雷,请重新输入:\n");
}
else
{
int count = landmine_count(mine, x, y);//landmine_count()函数在下面介绍
show[x][y] = count + '0';//使得该位置的数字几变成字符几
Display_board(show, ROW, COL);
i++;
}
}
else
{
printf("输入错误,请重新输入\n");
}
}
if (i == ROW * COL - LANDMINE)//当数组中的非雷位置全都排出,即为排雷成功
{
printf("\n恭喜你,扫雷成功\n");
Display_board(mine, ROW, COL);
}
}
因为mine数组中全为字符0或1,又字符n减去字符0=数字n,所以雷的个数为该位置周围8个位置的字符之和减去8*字符0
int landmine_count(char mine[ROWS][COLS], int x,int y)
{
return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1]
+ mine[x][y - 1] + mine[x][y + 1]
+ mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0';
}
#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 };
//初始化
Initiate_board(mine, ROWS, COLS, '0');
Initiate_board(show, ROWS, COLS, '*');
//Display_board(mine, ROW, COL);
Display_board(show, ROW, COL);
//布置雷
Set_mine(mine, ROW, COL);
Display_board(mine, ROW, COL);
//扫雷
Search_mine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define LANDMINE 10
#include
#include
#include
//初始化
void Initiate_board(char mine[ROWS][COLS], int rows, int cols, char set);
//打印
void Display_board(char mine[ROWS][COLS], int row, int col);
//布置雷
void Set_mine(char mine[ROWS][COLS], int row, int col);
//扫雷
int Search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void Initiate_board(char mine[ROWS][COLS], int rows, int cols, char set)
{
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
mine[i][j] = set;
}
void Display_board(char mine[ROWS][COLS], int row, int col)
{
int i, j;
printf("\n----------扫雷----------\n");
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 ", mine[i][j]);
printf("\n");
}
printf("----------扫雷----------\n");
printf("\n");
}
void Set_mine(char mine[ROWS][COLS], int row, int col)
{
int i = 0;
while (i < LANDMINE)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
i++;
}
}
}
int landmine_count(char mine[ROWS][COLS], int x,int y)
{
return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1]
+ mine[x][y - 1] + mine[x][y + 1]
+ mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0';
}
int Search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y;
int i = 0;
while (i < ROW * COL - LANDMINE)
{
printf("请输入想要查找的位置:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("\n很遗憾,您被炸死了\n");
Display_board(mine, ROW, COL);
break;
}
else if (show[x][y] != '*')
{
printf("该位置已排雷,请重新输入:\n");
}
else
{
int count = landmine_count(mine, x, y);
show[x][y] = count + '0';
Display_board(show, ROW, COL);
i++;
}
}
else
{
printf("输入错误,请重新输入\n");
}
}
if (i == ROW * COL - LANDMINE)
{
printf("\n恭喜你,扫雷成功\n");
Display_board(mine, ROW, COL);
}
}