要实现扫雷游戏代码的编写,我们首先要清楚扫雷的游戏规则:
1. 有一个显示盘界面,玩家可以在上面的坐标进行点击。
2. 玩家点击坐标,如果是雷,则被炸死,如果不是雷,分两种情况,一是周围无雷,那么将无雷的区域展开;二是周围有雷,那么将周围雷的个数显示在此坐标上。
3. 判断输赢。如果玩家在玩游戏过程中点到的坐标是雷,那么被炸死。如果最后只剩下雷,那么玩家排雷成功。
那么我们用代码实现这个游戏时,当然要遵循游戏规则。在上面的游戏规则之外,我们还添加了一条:如果玩家第一次就踩到了雷,那么设置为不会被炸死。下面我们就来看看具体怎么实现:
先说下基本思想:
1. 首先我们要设定两个棋盘。一个是用于给玩家看的显示棋盘。一个是用于布雷的雷盘。实现的方法是定义两个数组,并且初始化。注意我们这里要设置比显示出来的棋盘多一圈。比如显示10*10,那么初始化为12*12。为什么呢?显示棋盘是因为我们数组的下标是从0开始的,而一般生活中的思维都是从1开始,这里是为了便于玩家玩游戏时好操作。雷盘是因为我们在统计周围雷的个数时方便一些。这里我们设定将显示盘初始化为’*’,将雷盘初始化为’0’,将有雷的坐标初始化为’1’。
2. 布雷。也就是放置雷。这里我们要用到随机数种子的函数。产生随机数,当要放置的坐标不为’1’时,将此坐标置为’1’。如果放置的坐标不能放置雷的话,要将循环变量设置回初始的值。
3. 玩家玩游戏。首先玩家输入的坐标要在显示棋盘内。其次再看有没有踩到雷,如果踩到雷,分两种情况:是否为第一次踩雷。如果第一次踩雷,那么将此颗雷移动到别的没有雷的地方;如果不是,那么玩家被炸死,游戏结束。如果没有踩到雷,那么看此坐标周围是否有雷,有雷,将统计的雷的个数显示在此坐标,如果没有雷,将此坐标周围的坐标都展开,即将此坐标周围的坐标都设置为’ ‘。
4. 判断输赢。如果玩家在玩游戏途中,被炸死,那么玩家输了。如果玩家玩到最后,剩余的坐标数和雷的数量相同,那么玩家排雷成功。
下面是具体实现代码,供大家参考:
lei.h 头文件:声明程序中所用到的函数
#ifndef __LEI_H_
#define __LEI_H_
#define ROW 10
#define COL 10
#define ROWS 12
#define COLS 12
#define MINE 10 //设置雷的个数为20个
//初始化棋盘
void init_mine(char mine[ROWS][COLS], int row, int col);//雷盘 最外面一圈要全部初始化为无雷的 这样计算的时候好计算
void init_show(char show[ROWS][COLS], int row, int col);//显示盘 也要设置为12*12 因为一般观念是从1开始的 而数组下标是从0开始的 设置为12好计算一点
//打印棋盘
void display_board(char mine[ROWS][COLS], int row, int col);
//布雷 设置雷
void set_mine(char mine[ROWS][COLS], int row, int col);//count为雷的总数
//统计雷的个数
int get_mine_count(char mine[ROWS][COLS], int i, int j);
//重新布雷
void reset_mine(char mine[ROWS][COLS], int x, int y, int row, int col);//x y为输入的坐标
//展开雷
void expand_mine(char mine[ROWS][COLS], int x, int y, char show[ROWS][COLS]);//x,y 为玩家输入周围无雷的坐标
//判断剩余未知区域的个数
int count_board(char show[ROWS][COLS], int row, int col);
#endif
main.c 主函数:用于测试各个函数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"lei.h"
//菜单函数
void menu()
{
printf("**********************\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("**********************\n");
}
//游戏函数
void game()
{
int x = 0;//玩家输入的坐标
int y = 0;//玩家输入的坐标
int tmp = 0;//判断是不是第一次踩雷
int num = 0;//统计剩余区域的雷的个数 用于判断是不是排雷成功
int count = 0;//统计周围雷的个数
char mine[ROWS][COLS] = { 0 };//定义雷数组
char show[ROWS][COLS] = { 0 };//定义显示数组
//初始化数组 规定无雷的坐标为0 有雷的坐标为1
memset(mine, '0', sizeof(mine));//将mine数组当前位置后面的sizeof(mine)个字节,用‘0’替换并返回给数组mine,即将数组初始化为‘0’
memset(show, '*', sizeof(show));//将board数组当前位置后面的sizeof(board)个字节,用‘0’替换并返回给数组board,即将数组初始化为‘*’
//布雷
srand((unsigned)time(NULL));//将随机值初始值设为当前时间
set_mine(mine, ROWS, COLS);
display_board(mine, ROWS, COLS);
printf("\n");
display_board(show, ROWS, COLS);
while (1)
{
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if (((x >= 1) && (x <= ROW)) && ((y >= 1) && (y <= COL)))//坐标在雷盘内
{
if (mine[x][y] == '1')//踩到雷
{
if (0 == tmp)//第一次踩到雷 重置雷 然后显示当前坐标周围的雷个数
{
reset_mine(mine, ROWS, COLS, x, y);
count = get_mine_count(mine, x, y);
if (count == 0)//输入坐标周围无雷
{
show[x][y] = ' ';//如果周围没有雷,那么将这个坐标置为空格
expand_mine(mine, x, y, show);//展开其周围
display_board(show, ROWS, COLS);
}
else//输入坐标周围有雷
{
show[x][y] = count + '0';//如果周围有雷,将周围雷的个数显示在此坐标处 整形数据+'0'转变成相应的字符数据
display_board(show, ROWS, COLS);
}
}
else//tmp为0时为第一次踩到雷,设置为不被炸死,重置雷。不为0时,就被炸死了
{
printf("你被炸死啦!\n");
display_board(mine, ROWS, COLS);
break;
}
}
else//没有踩到雷
{
count = get_mine_count(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';
expand_mine(mine, x, y, show);
display_board(show, ROWS, COLS);
}
else
{
show[x][y] = count + '0';
display_board(show, ROWS, COLS);
}
}
}
else
{
printf("输入坐标不合法\n");
}
if (num = count_board(show, ROWS, COLS == MINE))
{
printf("排雷成功\n");
display_board(show, ROWS, COLS);
break;
}
tmp++;
}
}
int main()
{
int choose = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &choose);
switch (choose)
{
case 1:
printf("play game\n");
game();
break;
case 0:
printf("exit game\n");
break;
return 0;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (choose);
system("pause");
return 0;
}
lei.c:用于实现各个函数
#include<stdio.h>
#include "lei.h"
//打印棋盘
void display_board(char mine[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" 1 2 3 4 5 6 7 8 9 10\n");
printf(" ---------------------\n");
for (i = 1; i < row - 1; i++)//row参数传递过来的是ROWS 所以这里循环条件为1-10 下同
{
printf("%2d|",i);
for (j = 1; j < col - 1; j++)
{
printf("%c ",mine[i][j]);
}
printf("|\n");
}
printf(" ---------------------\n");
}
//布雷 设置雷
void set_mine(char mine[ROWS][COLS], int row, int col)
{
int count = MINE;//雷的个数
int i = 0;
for (i = 0; i < count; i++)
{
int x = rand() % (row - 2) + 1;//(0-9)+1 即为1-10
int y = rand() % (col - 2) + 1;
if (mine[x][y] == '0')//如果要放置的坐标为'0',那么放置雷
{
mine[x][y] = '1';
}
else
{
i--;//如果条件不足没有放置雷,那么将i的值返回原始值,重新循环
}
}
}
//统计雷的个数
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] - '0' + mine[x - 1][y] - '0' + mine[x - 1][y + 1] - '0'
+ mine[x][y + 1] - '0' + mine[x + 1][y + 1] - '0' + mine[x + 1][y] - '0' +
mine[x + 1][y - 1] - '0' + mine[x][y - 1] - '0';//字符型数值-‘0’就是相应的int型,如果是雷的话,就返回1,
//如果不是雷,就返回0,将周围的每一个位置都统计相加,就是周围一共雷的个数
}
//重新布雷
void reset_mine(char mine[ROWS][COLS], int row, int col, int x, int y)//x y为输入的坐标
{
int count = 1;
mine[x][y] = '0';//让此时的坐标为'0' 即无雷状态
while (count)
{
int i = rand() % row + 1;//1-row
int j = rand() % col + 1;//1-col
if ((mine[i][j] != '1') && (i != x) && (j != y))//不为x y即不是这个坐标,并且不是有雷的坐标,那么把它置为有雷
{
mine[i][j] = '1';//将雷挪开,再让另一个不同的没有雷的位置设置为雷
}
count--;
}
}
//展开雷
void expand_mine(char mine[ROWS][COLS], int x, int y, char show[ROWS][COLS])//x,y 为玩家输入周围无雷的坐标
{
if (mine[x - 1][y - 1] == '0')
{
show[x - 1][y - 1] = get_mine_count(mine, x - 1, y - 1);
}
if (mine[x - 1][y] == '0')
{
show[x - 1][y] = get_mine_count(mine, x - 1, y);
}
if (mine[x - 1][y + 1] == '0')
{
show[x - 1][y + 1] = get_mine_count(mine, x - 1, y + 1);
}
if (mine[x][y + 1] == '0')
{
show[x][y + 1] = get_mine_count(mine, x, y + 1);
}
if (mine[x + 1][y + 1] == '0')
{
show[x + 1][y + 1] = get_mine_count(mine, x + 1, y + 1);
}
if (mine[x + 1][y] == '0')
{
show[x + 1][y] = get_mine_count(mine, x + 1, y);
}
if (mine[x + 1][y - 1] == '0')
{
show[x + 1][y - 1] = get_mine_count(mine, x + 1, y - 1);
}
if (mine[x][y - 1] == '0')
{
show[x][y - 1] = get_mine_count(mine, x, y - 1);
}
}
//判断剩余未知区域的个数
int count_board(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count;
}
下面是运行结果: