扫雷游戏的实现的关键是要创建好两个同样大小二维数组,一个用来随机生成雷,一个用来更新游戏界面.在创建游戏过程中应注意输入坐标和数组下标之间的关系。为了增加游戏的乐趣,本游戏将使玩家第一步不会踩到雷,并且可以显示周围坐标雷的个数,还可以让玩家是否标记出雷的位置,降低了游戏的难度.
将扫雷的代码分为三部分:头文件存放game.h (主要用来声明各种函数,以便调用) ;源文件分别存放game.c(主要用来存放各种函数实现的代码)以及test.c(主要用来实现整个游戏代码框架)。
game.h代码:
#ifndef __GAME_H__
#define __GAME_H__
#define ROWS 14 //宏定义行
#define COLS 14 //列
#define sweep 20
void Init_Interface(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols); //初始化扫雷棋盘
void display_board(int board2[ROWS][COLS], int rows, int cols); //打印扫雷棋盘
int play_move(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols); //玩家输入坐标并判断是否是雷
void pai_lei(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols); //玩家是否排雷
int win(int board2[ROWS][COLS], int rows, int cols); //判断玩家输赢
int error_sweep(int board2[ROWS][COLS], int rows, int cols); //判断玩家扫雷错误数
int check_sweep(int board2[ROWS][COLS], int rows, int cols); //判断雷阵是否填满
void sweep_board(int board1[ROWS][COLS], int rows, int cols); //打印布雷棋盘
#endif //__GAME_H__
game.c代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "game.h"
#include <string.h>
#include <stdlib.h>
#include <time.h>
void Init_Interface(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols) //初始化扫雷棋盘,以及布雷其中0代表无雷,1代表有雷
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
int count = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board1[i][j] = 0;
}
}
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board2[i][j] = '*';
}
}
srand((unsigned int)time(NULL));
while (count != sweep) //产生20个雷
{
int x = rand() % 10 + 2;
int y = rand() % 10 + 2;
if (board1[x][y] == 0)
{
count++;
board1[x][y] = 1;
}
}
//初始化雷盘
printf(" 1 2 3 4 5 6 7 8 9 10 \n");
printf(" _________________________________________\n");
for (i = 2; i < rows - 2; i++)
{
if (i > 10)
{
printf("%d | |", i - 1);
}
else if (i <= 10)
{
printf("%d | |", i - 1);
}
for (j = 3; j < cols - 2; j++)
{
printf(" |");
}
printf("\n");
printf(" | %c |", board2[i][2]);
for (j = 3; j < cols - 2; j++)
{
printf(" %c |", board2[i][j]);
}
printf("\n");
printf(" |___|");
for (j = 3; j < cols - 2; j++)
{
printf("___|");
}
printf("\n");
}
}
void display_board(int board2[ROWS][COLS], int rows, int cols) //打印扫雷棋盘
{
int i = 0;
int j = 0;
printf(" 1 2 3 4 5 6 7 8 9 10 \n");
printf(" _________________________________________\n");
for (i = 2; i < rows - 2; i++)
{
if (i > 10)
{
printf("%d | |", i - 1);
}
else if (i <= 10)
{
printf("%d | |", i - 1);
}
for (j = 3; j < cols - 2; j++)
{
printf(" |");
}
printf("\n");
if ((board2[i][2] == '*') || (board2[i][2] == 'Y') || (board2[i][2] == 'N'))
{
printf(" | %c |", board2[i][2]);
}
if ((board2[i][2] != '*') && (board2[i][2] != 'Y') && (board2[i][2] != 'N'))
{
printf(" | %d |", board2[i][2]);
}
for (j = 3; j < cols - 2; j++)
{
if ((board2[i][j] == '*') || (board2[i][j] == 'Y') || (board2[i][j] == 'N'))
printf(" %c |", board2[i][j]);
if (((board2[i][j] != '*') && (board2[i][j] != 'Y')) && (board2[i][j] != 'N'))
printf(" %d |", board2[i][j]);
}
printf("\n");
printf(" |___|");
for (j = 3; j < cols - 2; j++)
{
printf("___|");
}
printf("\n");
}
}
int play_move(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols) //玩家输入坐标
{
int x = 0;
int y = 0;
int i = 0;
int j = 0;
int static first_move = 0; //定义一个静态变量,判断first_move是不是第一步棋子
int count = 0;
printf("请输入坐标:");
while (1)
{
scanf("%d%d", &x, &y);
x++;
y++;
if ((x >= 2) && (x <= rows - 3) && (y >= 2) && (y <= cols - 3))
{
first_move++;
if (1 == first_move)
{
if (board1[x][y] == 1) //第一步是雷,并转移
{
for (i = 2; i < rows - 2; i++)
{
for (j = 2; j < cols - 2; j++)
{
if (board1[i][j] == 0)
{
board1[i][j] = 1;
board1[x][y] = 0;
break;
}
}
break;
}
}
//统计第一步周围雷的情况
count = board1[x - 1][y] + board1[x - 1][y + 1] + board1[x - 1][y - 1]
+ board1[x + 1][y] + board1[x + 1][y + 1] + board1[x + 1][y - 1]
+ board1[x][y + 1] + board1[x][y - 1];
board2[x][y] = count;
if (board1[x][y - 1] != 1)
{
count = 0;
count = board1[x - 1][y - 1] + board1[x - 1][y] + board1[x - 1][y - 2]
+ board1[x + 1][y - 1] + board1[x + 1][y] + board1[x + 1][y - 2]
+ board1[x][y] + board1[x][y - 2];
board2[x][y - 1] = count;
}
if (board1[x][y + 1] != 1)
{
count = 0;
count = board1[x - 1][y + 1] + board1[x - 1][y + 2] + board1[x - 1][y]
+ board1[x + 1][y + 1] + board1[x + 1][y + 2] + board1[x + 1][y]
+ board1[x][y + 2] + board1[x][y];
board2[x][y + 1] = count;
}
if (board1[x + 1][y] != 1)
{
count = 0;
count = board1[x][y] + board1[x][y + 1] + board1[x][y - 1]
+ board1[x + 2][y] + board1[x + 2][y + 1] + board1[x + 2][y - 1]
+ board1[x + 1][y + 1] + board1[x + 1][y - 1];
board2[x + 1][y] = count;
}
if (board1[x - 1][y] != 1)
{
count = 0;
count = board1[x - 2][y] + board1[x - 2][y + 1] + board1[x - 2][y - 1]
+ board1[x][y] + board1[x][y + 1] + board1[x][y - 1]
+ board1[x - 1][y + 1] + board1[x - 1][y - 1];
board2[x - 1][y] = count;
}
if (board1[x + 1][y - 1] != 1)
{
count = 0;
count = board1[x][y - 1] + board1[x][y] + board1[x][y - 2]
+ board1[x + 2][y - 1] + board1[x + 2][y] + board1[x + 2][y - 2]
+ board1[x + 1][y] + board1[x + 1][y - 2];
board2[x + 1][y - 1] = count;
}
if (board1[x - 1][y - 1] != 1)
{
count = 0;
count = board1[x - 2][y - 1] + board1[x - 2][y] + board1[x - 2][y - 2]
+ board1[x][y - 1] + board1[x][y] + board1[x][y - 2]
+ board1[x - 1][y] + board1[x - 1][y - 2];
board2[x - 1][y - 1] = count;
}
if (board1[x - 1][y + 1] != 1)
{
count = 0;
count = board1[x - 2][y + 1] + board1[x - 2][y + 2] + board1[x - 2][y]
+ board1[x][y + 1] + board1[x][y + 2] + board1[x - 2][y]
+ board1[x - 1][y + 2] + board1[x - 1][y];
board2[x - 1][y + 1] = count;
}
if (board1[x + 1][y + 1] != 1)
{
count = 0;
count = board1[x][y + 1] + board1[x][y + 2] + board1[x][y]
+ board1[x + 2][y + 1] + board1[x + 2][y + 2] + board1[x + 2][y]
+ board1[x + 1][y + 2] + board1[x + 1][y];
board2[x + 1][y + 1] = count;
}
return -2;
}
if (board2[x][y] == '*')
{
board2[x][y] = 1;
if (board1[x][y] == board2[x][y])
{
return -1; //证明踩到雷了
}
else
{
int count = 0;
count = board1[x - 1][y] + board1[x - 1][y + 1] + board1[x - 1][y - 1]
+ board1[x + 1][y] + board1[x + 1][y + 1] + board1[x + 1][y - 1]
+ board1[x][y + 1] + board1[x][y - 1];
board2[x][y] = count;
return count;
}
}
}
printf("\n输入错误,请重新输入坐标:");
}
}
void sweep_board(int board1[ROWS][COLS], int rows, int cols) //打印布好雷的图
{
int i = 0;
int j = 0;
printf(" 1 2 3 4 5 6 7 8 9 10 \n");
printf(" _________________________________________\n");
for (i = 2; i < rows - 2; i++)
{
if (i > 10)
{
printf("%d | |", i - 1);
}
else if (i <= 10)
{
printf("%d | |", i - 1);
}
for (j = 3; j < cols - 2; j++)
{
printf(" |");
}
printf("\n");
printf(" | %d |", board1[i][2]);
for (j = 3; j < cols - 2; j++)
{
printf(" %d |", board1[i][j]);
}
printf("\n");
printf(" |___|");
for (j = 3; j < cols - 2; j++)
{
printf("___|");
}
printf("\n");
}
}
int win(int board2[ROWS][COLS], int rows, int cols) //判断玩家是否扫雷成功
{
int i = 0;
int j = 0;
int count = 0;
for (i = 2; i <= rows - 3; i++)
{
for (j = 2; j <= cols - 3; j++)
{
if (board2[i][j] == 'Y')
count++;
}
}
return count;
}
void pai_lei(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols) //玩家是否排雷
{
int x = 0;
int y = 0;
printf("请输入要排雷的坐标:");
while (1)
{
scanf("%d%d", &x, &y);
x++;
y++;
if ((x >= 2) && (x <= rows - 3) && (y >= 2) && (y <= cols - 3))
{
if ((board1[x][y] == 1) && (board2[x][y] == '*'))
{
board2[x][y] = 'Y';
break;
}
else if ((board1[x][y] == 0) && (board2[x][y] == '*'))
{
board2[x][y] = 'N';
break;
}
}
printf("\n输入错误,请重新输入坐标:");
}
}
int error_sweep(int board2[ROWS][COLS], int rows, int cols)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 2; i <= rows - 3; i++)
{
for (j = 2; j <= cols - 3; j++)
{
if (board2[i][j] == 'N')
count++;
}
}
return count;
}
int check_sweep(int board2[ROWS][COLS], int rows, int cols)
{
int i = 0;
int j = 0;
for (i = 2; i <= rows - 3; i++)
{
for (j = 2; j <= cols - 3; j++)
{
if (board2[i][j] == '*')
return 0;
}
}
return 1;
}
test.c代码:
#include <stdio.h>
#include "game.h"
enum
{
EXIT, /*枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2…。EXIT的值为0,PLAY的值为1*/
PLAY
};
void menu()
{
printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");
printf("☆☆☆☆☆ 1.PLAY ☆☆☆☆☆\n");
printf("☆☆☆☆☆ 0.EXIT ☆☆☆☆☆\n");
printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");
}
void game()
{
int ret = 0;
int k = 0; //用来判断玩家是否输入雷的坐标
int board1[ROWS][COLS] = { 0 }; //第一张棋盘作为埋好雷的棋盘
int board2[ROWS][COLS] = { 0 }; //第二张棋盘作为统计雷的棋盘
Init_Interface(board1, board2, ROWS, COLS); //初始化扫雷棋盘
while (1)
{
int ret1 = play_move(board1, board2, ROWS, COLS); //玩家输入坐标
{
if (ret1 == -1)
{
printf("\n踩雷成功,光荣牺牲.\n");
sweep_board(board1, ROWS, COLS); //打印布雷棋盘
break;
}
display_board(board2, ROWS, COLS);
//排雷过程
k = 0;
printf("☆☆☆☆☆☆☆☆☆☆☆☆☆\n");
printf("☆☆☆ 输入0: 排雷 ☆☆☆\n");
printf("☆☆☆ 输入1: 不排雷☆☆☆\n");
printf("☆☆☆☆☆☆☆☆☆☆☆☆☆\n");
printf("请选择:\n");
while (k == 0)
{
scanf("%d", &k);
switch (k) //判断是否需要排雷
{
case 0:
pai_lei(board1, board2, ROWS, COLS);
break;
case 1:
break;
default:
k = 0;
printf("输入错误\n");
break;
}
if (k == 0)
{
printf("请选择是否继续排雷:");
}
}
//结束
int ret2 = win(board2, ROWS, COLS);
{
if (ret2 == sweep) //返回的值为雷的个数则成功
{
printf("恭喜扫雷成功.\n");
sweep_board(board1, ROWS, COLS); //打印布雷棋盘
break;
}
else
{
printf("您已经成功的扫出%d颗雷\n", ret2);
}
}
int ret3 = error_sweep(board2, ROWS, COLS); //判断扫错雷的个数
{
printf("您已经错误的扫出%d颗雷\n", ret3);
}
int ret4 = check_sweep(board2, ROWS, COLS); //检查雷阵是否填满
if (ret4 == 1)
{
printf("没能成功找出所有的雷,很遗憾");
break;
}
}
display_board(board2, ROWS, COLS);
}
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input); //
switch (input)
{
case PLAY:
game();
break;
case EXIT:
break;
default:
printf("您的输入有误,请重新输入.\n");
break;
}
} while (input);
return 0;
}
部分游戏运行界面: