目录
一,说明
简易版扫雷中,我们用坐标来代替鼠标点击的位置,并且仅仅展示该点周围雷数(大家可以通过学习自行拓展)。算是低配版。
为了代码分工明确、清晰、有条理,代码位置分为了三部分:game.h(预处理及代码的声明)、test.c(代码的调用)、game.c(代码的描述)。
大部分操作都实现为一个函数,方便随时调用,且定义都放在头文件里。
说明结束,开始发车····
二,逐层构思
下面是游戏结构分析
1,游戏菜单界面
菜单的显示仅涉及打印,代码如下:
void menu()
{
printf(">>>1.开始游戏<<<\n>>>0.退出游戏<<<\n请输入:");
}
2,游戏地图的创建
扫雷游戏有三种难度:
- 简单(9*9地图,10处雷)
- 中等(16*16地图,40处雷)
- 困难(30*16地图,99处雷)
这里我们学习简单难度的写法:
在这里,地图要分为两种:1,显示出的地图、2,分布着雷的地图。对于两种地图,我们要用两种二维数组来对应,我们将它们命名为:map1(分布雷的地图)、map2(显示的地图)。对于此类二维数组的创建,我们会想着创建一个【9】【9】的数组,但是到排雷时,我们会发现当我们要排查边缘时边缘以外的坐标就无法显示了,因此,我们选择【11】【11】数组。(注:ROWS与COLS在定义时已经赋值)
//创建地图
char map1[ROWS][COLS];
char map2[ROWS][COLS];
此时要对数组进行初始化,map1初始化为0,而map2初始化为 * ,即显示在屏幕上的图案。这里我们要利用for循环:
代码如下:
//棋盘初始化
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
map1[i][j] = '0';
map2[i][j] = '*';
}
}
3,地图的打印(显示)
地图的打印大部分涉及map2的打印,在每一次排查雷时,打印一次排查雷后的map2,如果踩到雷了,我们则打印出map1,以显示雷的分布情况。
代码如下:
//地图的打印
void DisplayBoard (char map[ROWS][COLS],int row,int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", map[i][j]);
}
printf("\n");
}
}
4,雷的分布
众所周知,扫雷中雷的分布时随机的,因此这里涉及srand与time函数,我们要用其随机生成10个雷处,然后赋值给map1这样雷的生成及分布就完成了。
代码如下:
void SetMine(char map[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;//生成横纵坐标均为1到10
int y = rand() % col + 1;
if (map[x][y] == '0')
{
map[x][y] = '1';
count--;
}
}
}
5,显示周围雷数
代码如下:
//显示周围雷数
int GetMineCount(char map1[ROWS][COLS], int x, int y)
{
return(map1[x - 1][y] + map1[x - 1][y - 1] + map1[x - 1][y + 1] +map1[x][y - 1] + map1[x][y + 1] + map1[x + 1][y] + map1[x + 1][y-1] + map1[x + 1][y + 1] - 8*'0');
}
6,雷的排查
在以上操作都完成后,便来到排查环节。排查时,当输入要排查的坐标后,我们用if函数判断该点是否为雷:
- 为雷时,游戏结束并且显示出答案
- 不为雷时,显示周围雷数并且显示出来
当我们排查到图上仅有雷时(即仅剩10个点时)游戏通关并打印答案。
代码如下:
//雷的排查
void FindMine(char map1[ROWS][COLS],char map2[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while(win<ROW*COL-EASY_COUNT)
{
printf("请选择要扫描的坐标:\n");
scanf_s("%d %d", &x, &y);
if (map1[x][y] == '1')//踩雷了
{
printf("很遗憾,游戏结束\n");
DisplayBoard(map1, ROW, COL);
break;
}
else
{
int count = GetMineCount(map1, x, y);
map2[x][y] = count+'0';
system("cls");
DisplayBoard(map2, ROW, COL);
win++;
}
}
if (win == ROW * COL - EASY_COUNT)
{
printf("恭喜通关!");
DisplayBoard(map1, ROW, COL);
}
三,代码展示
1,代码的声明(头文件)
//代码的声明
#pragma once
#include<stdlib.h>
#include<time.h>
# include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10//雷的数目
void game();
void menu();
//打印棋盘
void DisplayBoard(char map[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char map[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char map[ROWS][COLS],char map2[ROWS][COLS], int row, int col);
//显示周围雷数
int GetMineCount(char map[ROWS][COLS], int x, int y);
2,代码的调用(源文件)
//代码的调用
#include"game.h"
void menu()
{
printf(">>>1.开始游戏<<<\n>>>0.退出游戏<<<\n请输入:");
}
void game()
{
//创建地图
char map1[ROWS][COLS];
char map2[ROWS][COLS];
//棋盘初始化
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
map1[i][j] = '0';
map2[i][j] = '*';
}
}
//打印棋盘
DisplayBoard(map2, ROW, COL);
//布置雷
SetMine(map1, ROW, COL);
//扫雷
FindMine(map1, map2, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
do
{
menu();
int input = 0;
scanf_s("%d", &input);
if (input == 1)
{
printf("游戏开始\n");
game();
break;
}
else if (input == 0)
{
printf("游戏结束");
break;
}
else
{
printf("输入错误,请重新输入:");
}
} while (1);
return 0;
}
3,代码的描述(实现)(源文件)
//代码的描述
# include"game.h"
//地图的打印
void DisplayBoard (char map[ROWS][COLS],int row,int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", map[i][j]);
}
printf("\n");
}
}
//雷点的布置
void SetMine(char map[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;//生成横纵坐标均为1到10
int y = rand() % col + 1;
if (map[x][y] == '0')
{
map[x][y] = '1';
count--;
}
}
}
//雷的排查
void FindMine(char map1[ROWS][COLS],char map2[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while(win<ROW*COL-EASY_COUNT)
{
printf("请选择要扫描的坐标:\n");
scanf_s("%d %d", &x, &y);
if (map1[x][y] == '1')
{
printf("很遗憾,游戏结束\n");
DisplayBoard(map1, ROW, COL);
break;
}
else
{
int count = GetMineCount(map1, x, y);
map2[x][y] = count+'0';
system("cls");
DisplayBoard(map2, ROW, COL);
win++;
}
}
if (win == ROW * COL - EASY_COUNT)
{
printf("恭喜通关!");
DisplayBoard(map1, ROW, COL);
}
}//显示周围雷数
int GetMineCount(char map1[ROWS][COLS], int x, int y)
{
return(map1[x - 1][y] + map1[x - 1][y - 1] + map1[x - 1][y + 1] +map1[x][y - 1] + map1[x][y + 1] + map1[x + 1][y] + map1[x + 1][y-1] + map1[x + 1][y + 1] - 8*'0');
}