扫雷小游戏相信大家都玩过吧,这次我们自己用动态内存来实现一下扫雷游戏!!!
要做出来扫雷小游戏肯定要先理解它的机制和玩法。
1、方格中又若干个雷,点到雷上,游戏结束,走完没有雷的格子,游戏通关。
2、没有雷的方格的数字代表的含义:表示周围一圈的八个方格中又几个雷。
既然熟悉了游戏规则,那我们来编写每个模块的函数吧。
1、首先需要创建出来一个二维矩阵,每个元素代表游戏中的每个方格
//创建二维矩阵
char** creatMat(int row, int col)
{
//增加2行2列,便于计算每个位置雷的个数
//创建一个指针数组
char** Mat = (char**)malloc(sizeof(char*)*(row + 2));//动态开辟内存
for (int i = 0; i < row+2; i++)
{
Mat[i] = (char*)malloc(sizeof(char)*(col + 2));//动态开辟内存
}
return Mat;
}
2、将这个二维矩阵的所有元素都初始化为字符ch
//初始化二维矩阵
void initMat(char** Mat, int row, int col, char ch)
{
for (int i = 0; i < row + 2; i++)
{
for (int j = 0; j < col + 2; j++)
{
Mat[i][j] = ch;
}
}
}
3、随机在不同的格子中放入雷,用‘*’表示。
//随机埋雷
void setMine(char** Mat, int row, int col)
{
int count = MINE_NUM; //定义雷数
while (count)
{
//x:1-row y:1-col
int x = rand() % row + 1;
int y = rand() % col + 1;
//若格子不为*(雷),则在格子埋下雷,雷数减一
if (Mat[x][y] != '*')
{
Mat[x][y] = '*';
count--;
}
}
}
4、编写显示这个二维矩阵的函数
//打印二维矩阵
void showMat(char** Mat, int row, int col)
{
printf("-------------------------------------\n");
//打印列:0 1 2 3 4...col
for (int i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
//打印行:1 2 3 4 5...row
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", Mat[i][j]);
}
printf("\n");
}
printf("-------------------------------------\n");
}
5、打开格子,如果格子中没有雷,就会显示格子周围的8个格子中雷的个数。
这里我画一个图:
//返回没有雷的格子上的数字
int getMineNum(char** Mat, int row, int col, int x, int y)
{
//旋转矩阵
static int posOffset[8][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } };
int count = 0;
//依次遍历8个格子
for (int i = 0; i < 8; i++)
{
int nx = x + posOffset[i][0];
int ny = y + posOffset[i][1];
//如果有雷,则数字加一
if (Mat[nx][ny] == '*')
{
count++;
}
}
return count;
}
6、如何判断游戏输赢,输入的格子若是雷则游戏结束
每走一步记录一下步数,如果步数等于没有雷的格子数,则胜利
//游戏模块
void game(char** mineMat, char** mineInfo,int row,int col)
{
int step = 0;
while (step < row*col - MINE_NUM)
{
int x, y;
printf("请输入一个坐标:\n");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mineMat[x][y] == '*')
{
printf("game over!!\n");
showMat(mineMat, row, col);
break;
}
//获取x,y位置周围雷的个数
int num = getMineNum(mineMat, row, col, x, y);
mineInfo[x][y] = num + '0';
showMat(mineInfo, row, col);
//成功执行了一步
step++;
}
else
{
printf("位置无效,重新输入\n");
}
}
if (step == row*col - MINE_NUM)
{
printf("you are win!\n");
}
}
8、最后不要忘记free掉开辟的内存以及把指向堆的指针置为NULL
//释放动态开辟的空间
void freeMat(char** Mat, int row, int col)
{
for (int i = 0; i < row; i++)
{
//释放每一行的空间
free(Mat[i]);
}
//释放指针数组的空间
free(Mat);
}
到这里每个模块的函数就已经编写好了,接下来只需要在头文件引入每个函数以及定义一个main函数来调用每个模块就ok啦
最后附上源码
game.h文件
#ifndef __GAME_H__
#include<stdio.h>
#include<stdlib.h>
#define ROW 10
#define COL 10
#define MINE_NUM 20
char** creatMat(int row, int col);
void initMat(char** Mat, int row, int col, char ch);
void setMine(char** Mat, int row, int col);
void showMat(char** Mat, int row, int col);
int getMineNum(char** Mat, int row, int col, int x, int y);
void game(char** mineMat, char** mineInfo, int row, int col);
void freeMat(char** Mat, int row, int col);
void test();
#endif
game.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//创建二维矩阵
char** creatMat(int row, int col)
{
//增加2行2列,便于计算每个位置雷的个数
//创建一个指针数组
char** Mat = (char**)malloc(sizeof(char*)*(row + 2));//动态开辟内存
for (int i = 0; i < row+2; i++)
{
Mat[i] = (char*)malloc(sizeof(char)*(col + 2));//动态开辟内存
}
return Mat;
}
//初始化二维矩阵
void initMat(char** Mat, int row, int col, char ch)
{
for (int i = 0; i < row + 2; i++)
{
for (int j = 0; j < col + 2; j++)
{
Mat[i][j] = ch;
}
}
}
//随机埋雷
void setMine(char** Mat, int row, int col)
{
int count = MINE_NUM; //定义雷数
while (count)
{
//x:1-row y:1-col
int x = rand() % row + 1;
int y = rand() % col + 1;
//若格子不为*(雷),则在格子埋下雷,雷数减一
if (Mat[x][y] != '*')
{
Mat[x][y] = '*';
count--;
}
}
}
//打印二维矩阵
void showMat(char** Mat, int row, int col)
{
printf("-------------------------------------\n");
//打印列:0 1 2 3 4...col
for (int i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
//打印行:1 2 3 4 5...row
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", Mat[i][j]);
}
printf("\n");
}
printf("-------------------------------------\n");
}
//返回没有雷的格子上的数字
int getMineNum(char** Mat, int row, int col, int x, int y)
{
//旋转矩阵
static int posOffset[8][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } };
int count = 0;
//依次遍历8个格子
for (int i = 0; i < 8; i++)
{
int nx = x + posOffset[i][0];
int ny = y + posOffset[i][1];
//如果有雷,则数字加一
if (Mat[nx][ny] == '*')
{
count++;
}
}
return count;
}
//游戏模块
void game(char** mineMat, char** mineInfo,int row,int col)
{
int step = 0;
while (step < row*col - MINE_NUM)
{
int x, y;
printf("请输入一个坐标:\n");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mineMat[x][y] == '*')
{
printf("game over!!\n");
showMat(mineMat, row, col);
break;
}
//获取x,y位置周围雷的个数
int num = getMineNum(mineMat, row, col, x, y);
mineInfo[x][y] = num + '0';
showMat(mineInfo, row, col);
//成功执行了一步
step++;
}
else
{
printf("位置无效,重新输入\n");
}
}
if (step == row*col - MINE_NUM)
{
printf("you are win!\n");
}
}
//释放动态开辟的空间
void freeMat(char** Mat, int row, int col)
{
for (int i = 0; i < row; i++)
{
//释放每一行的空间
free(Mat[i]);
}
//释放指针数组的空间
free(Mat);
}
//测试游戏运行
void test()
{
char** mineMat = creatMat(ROW, COL); //雷位置
char** mineInfo = creatMat(ROW, COL); //用户界面:雷周围的信息
initMat(mineMat, ROW, COL, '0');
initMat(mineInfo, ROW, COL, '-');
setMine(mineMat, ROW, COL);
printf("雷:\n");
showMat(mineMat, ROW, COL);
printf("雷的信息:\n");
showMat(mineInfo, ROW, COL);
game(mineMat, mineInfo, ROW, COL);
}
main.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
int main()
{
srand((unsigned)time(NULL)); //让雷真随机
test();
return 0;
}
小伙伴们,学会了吗😜