目录
一、描述
尝试用C语言实现扫雷游戏
二、思路
将游戏分为几个模块,分别实实现:
1 游戏开始与退出的选择
2 初始化棋盘
3 打印棋盘
4 在随机坐标生成n个地雷并埋在棋盘上
5 判断输入的坐标有无地雷,有则游戏结束,无则统计该坐标附近的地雷个数并输出
6 联系以上模块实现游戏函数game()
三、实现
1 游戏的开始与退出
1)打印菜单
定义一个函数,专门用来打印菜单
//打印菜单
void Dycd()
{
printf("==============================\n");
printf("---------1.开始游戏-----------\n");
printf("---------0.退出游戏-----------\n");
printf("==============================\n");
}
2)选择
对输入的数字进行判断,,如果是数字 1 就开始游戏,数字 0 就退出游戏,如果两个数字都不是,即重新选择 ,由于程序至少运行一次,这里使用do while循环
int n = 0;
do
{
Dycd();
printf("请选择:");
scanf("%d", &n);
switch (n)
{
case 0:
printf("退出游戏!!!\n");
break;
case 1:
printf("游戏开始!!!\n");
game();
break;
default:
printf("输入错误,请重新选择!!!\n");
break;
}
} while (n);
2 初始化棋盘
1)定义棋盘框架
假设游戏的棋盘框架是n*n的,但由于在后面统计输入的坐标附近的地雷个数时,是统计以该坐标为中心形成的九宫格的地雷个数,而位于边界的坐标不方便统计,所以这里设置内置棋盘是框架(n+2)*(n+2),而真正游戏中操作并输出的棋盘框架为n*n
所以这里定义棋盘的内置行、内置列、输出行和输出列,棋盘设置为9*9的
#define Hang 9//输出行
#define Lie 9//输出列
#define Nhang Hang+2//内置行
#define Nlie Lie+2//内置列
2)定义初始函数
专门用来初始化棋盘,将想要的字符布置在棋盘里
//初始化棋盘
void Csh(char Sz[Nhang][Nlie],int nhang,int nlie, char zf)
{
for (int x = 0; x < nhang; x++)
{
for (int y = 0; y < nlie; y++)
{
Sz[x][y] = zf;
}
}
}
3)初始化棋盘
创建两个字符类型的二维数组,一个作为内置棋盘来存放无地雷信息的"0"和有地雷信息的"1",另一个则作为输出棋盘用“X”将地雷信息隐藏,且可以在输入的坐标输出坐标附近的地雷个数
//内置棋盘
char Nqp[Nhang][Nlie] = { 0 };
//存放内置棋盘信息并输出的棋盘
char Sqp[Nhang][Nlie] = { 0 };
//初始化棋盘
Csh(Nqp, Nhang, Nlie, '0');
Csh(Sqp, Nhang, Nlie, ' X');
3 打印棋盘
定义一个函数,可以在需要的时候调用打印输出棋盘,同时可以在棋盘的上和左打印相应的X轴和Y轴,便于游戏时辨认坐标
//打印棋盘
void print(char Sz[Nhang][Nlie])
{
printf("========扫雷========\n");
for (int i = 0; i <= Hang; i++)
{
printf("%d ", i);
}
printf("\n");
for (int x = 1; x <= Hang; x++)
{
printf("%d ", x);
for (int y = 1; y <= Lie;y++)
{
printf("%c ", Sz[x][y]);
}
printf("\n");
}
}
4 随机生成地雷
这里定义生成地雷的地雷个数为10个
#define DL 10//存放地雷的个数
这里利用rand()函数随机生成坐标,但由于rang()生成的坐标并不完全随机,所以还要利用srand()和time()函数初始化rand()函数(由于初始化只需要一次所以放置在game()函数里)
//随机存放地雷
void Cfdl(char Sz[Nhang][Nlie])
{
int n = DL;
while (n)
{
//生成地雷的随机坐标
int x = rand() % Hang + 1;
int y = rand() % Lie + 1;
//将地雷存放在内置棋盘里,并判断生成的随机坐标是否重合
if (Sz[x][y] != '1')
{
Sz[x][y] = '1';
n--;
}
}
}
5 判断
判断输入的坐标有无地雷,有则游戏结束,无则统计以该坐标为中心形成的九宫格的地雷个数并输出,这里通过数字 1 和数字 0 的asll码值来相加相减来统计地雷个数
/*判断输入的坐标有没有地雷,
无地雷就在输入的坐标输出该坐标附近有多少个地雷,
有地雷就结束游戏*/
int Pd(char Nsz[Nhang][Nlie],char Sz[Nhang][Nlie], int x, int y)
{
int n = 0;//存放该坐标附近地雷个数
if (Nsz[x][y] == '1')
{
return 0;//返回0结束游戏
}
else
{
//计算该坐标附近地雷个数
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
n += (Nsz[x + i][y + j] - '0');
}
}
//将地雷数量存放在输出棋盘里
Sz[x][y] = n + '0';
return 1;//返回1则继续游戏
}
}
6 game()
联系以上模块实现游戏函数game()
//扫雷游戏
void game()
{
//初始化随机数生成器
srand((unsigned int)time(NULL));
//内置棋盘
char Nqp[Nhang][Nlie] = { 0 };
//存放内置棋盘信息并输出的棋盘
char Sqp[Nhang][Nlie] = { 0 };
//初始化棋盘
Csh(Nqp, Nhang, Nlie, '0');
Csh(Sqp, Nhang, Nlie, ' X');
//打印初始化棋盘
//print(Nqp);
print(Sqp);
//存放地雷
Cfdl(Nqp);
//print(Nqp);
//输入坐标、判断并输出
int x = 0, y = 0, n = Hang*Lie-DL;
while (n)
{
printf("请输入坐标(x,y):");
scanf("%d %d", &x, &y);
if (((x > 0 && x <= Hang) && (y > 0 && y <= Lie)) && (Pd(Nqp, Sqp, x, y)))
{
print(Sqp);
n--;
}
else if(((x > 0 && x <= Hang) && (y > 0 && y <= Lie)) && (Pd(Nqp, Sqp, x, y)) == 0)
{
printf("你死了。。。。。。\n游戏结束!!!\n");
return;
}
else
{
printf("输入错误,请重新输入!!!\n");
}
}
printf("排雷成功!!!\n游戏结束\n");
}
四、总代码
这里分别创建三个文件来实现游戏
1 game.h:声明函数
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#define Hang 9//输出行
#define Lie 9//输出列
#define Nhang Hang+2//内置行
#define Nlie Lie+2//内置列
#define DL 10//存放地雷的个数
#include<stdlib.h>
#include<time.h>
#include<stdio.h>
//打印菜单
void Dycd(void);
//初始化数组
void Csh(char Nsz[Nhang][Nlie], int nhang, int nlie, char zf);
//打印棋盘
void print(char Sz[Nhang][Nlie]);
//随机存放地雷
void Cfdl(char Sz[Nhang][Nlie]);
/*判断输入的坐标有没有地雷,
无地雷就在输入的坐标输出该坐标附近有多少个地雷,
有地雷就结束游戏*/
int Pd(char Nsz[Nhang][Nlie], char Sz[Nhang][Nlie], int x, int y);
2 game.cpp:存放自定义函数
#include"game.h"
//打印菜单
void Dycd()
{
printf("==============================\n");
printf("---------1.开始游戏-----------\n");
printf("---------0.退出游戏-----------\n");
printf("==============================\n");
}
//初始化棋盘
void Csh(char Sz[Nhang][Nlie],int nhang,int nlie, char zf)
{
for (int x = 0; x < nhang; x++)
{
for (int y = 0; y < nlie; y++)
{
Sz[x][y] = zf;
}
}
}
//打印棋盘
void print(char Sz[Nhang][Nlie])
{
printf("========扫雷========\n");
for (int i = 0; i <= Hang; i++)
{
printf("%d ", i);
}
printf("\n");
for (int x = 1; x <= Hang; x++)
{
printf("%d ", x);
for (int y = 1; y <= Lie;y++)
{
printf("%c ", Sz[x][y]);
}
printf("\n");
}
printf("——————————\n");
}
//随机存放地雷
void Cfdl(char Sz[Nhang][Nlie])
{
int n = DL;
while (n)
{
//生成地雷的随机坐标
int x = rand() % Hang + 1;
int y = rand() % Lie + 1;
//将地雷存放在内置棋盘里,并判断生成的随机坐标是否重合
if (Sz[x][y] != '1')
{
Sz[x][y] = '1';
n--;
}
}
}
/*判断输入的坐标有没有地雷,
无地雷就在输入的坐标输出该坐标附近有多少个地雷,
有地雷就结束游戏*/
int Pd(char Nsz[Nhang][Nlie],char Sz[Nhang][Nlie], int x, int y)
{
int n = 0;//存放该坐标附近地雷个数
if (Nsz[x][y] == '1')
{
return 0;
}
else
{
//计算该坐标附近地雷个数
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
n += (Nsz[x + i][y + j] - '0');
}
}
//将地雷数量存放在输出棋盘里
Sz[x][y] = n + '0';
return 1;
}
}
3 扫雷.cpp:实现游戏
#include"game.h"
//扫雷游戏
void game()
{
//初始化随机数生成器
srand((unsigned int)time(NULL));
//内置棋盘
char Nqp[Nhang][Nlie] = { 0 };
//存放内置棋盘信息并输出的棋盘
char Sqp[Nhang][Nlie] = { 0 };
//初始化棋盘
Csh(Nqp, Nhang, Nlie, '0');
Csh(Sqp, Nhang, Nlie, ' X');
//打印初始化棋盘
//print(Nqp);
print(Sqp);
//存放地雷
Cfdl(Nqp);
//print(Nqp);
//输入坐标、判断并输出
int x = 0, y = 0, n = Hang*Lie-DL;
while (n)
{
printf("请输入坐标(x,y):");
scanf("%d %d", &x, &y);
if (((x > 0 && x <= Hang) && (y > 0 && y <= Lie)) && (Pd(Nqp, Sqp, x, y)))
{
print(Sqp);
n--;
}
else if(((x > 0 && x <= Hang) && (y > 0 && y <= Lie)) && (Pd(Nqp, Sqp, x, y)) == 0)
{
printf("你死了。。。。。。\n游戏结束!!!\n");
return;
}
else
{
printf("输入错误,请重新输入!!!\n");
}
}
printf("排雷成功!!!\n游戏结束\n");
}
int main()
{
int n = 0;
do
{
Dycd();
printf("请选择:");
scanf("%d", &n);
switch (n)
{
case 0:
printf("退出游戏!!!\n");
break;
case 1:
printf("游戏开始!!!\n");
game();
break;
default:
printf("输入错误,请重新选择!!!\n");
break;
}
} while (n);
return 0;
}