小游戏流程概述
(三子棋) 完成扫雷游戏,我们要考虑的就和前面写的三子棋流程差不多.那我们就从流程开始入手,我们同样使用game();函数来实现基本流程.
- 首先要完成游戏菜单.我们同样使用menu()函数来展示基本菜单功能.
- 第二呢我们就需要创建我们的页面并初始化.
- 棋盘初始化之后我们将页面打印出来.并在每次扫雷之后重新打印页面.
- 拥有基本条件后,我们还需要在玩家每一步之后判定游戏是否结束.
- 当游戏结束后,我们就需要重新展示菜单.询问玩家下一步流程.
模块介绍
我们创建两个源文件和一个头文件.
名称 | 使用 |
---|---|
test.c | 使用test.c来实现游戏的基本流程 |
game.h | 使用game.h来声明我们需要的函数和头文件 |
game.c | 使用game.c来书写游戏具体实现 |
test.c
接下来我们就在test.c中写入main()函数.
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("exit!");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
main()函数的流程千篇一律,我们也不用过多介绍.需要注意的就是我们后面会使用到随机数,srand((unsigned int)time(NULL)); 必不可少.当然,后面发现了再回来添加也不是不可以.
void menu()
{
printf(" 1.play\n");
printf(" 0.exit\n");
}
用menu()函数打印菜单让玩家选择游戏下一步.
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
dispaly_board(show, ROW, COL);
set_mine(mine,ROW,COL);
find_mine(mine, show, ROW, COL);
}
当玩家选择了进行游戏模块,就进入了游戏模块.这里我们使用了两个二维数组来充当我们的雷区.为什么是两个呢.因为经过多方考虑,我发现用两个数组,一个用来存放雷区,另一个用来展示给玩家.应用起来更方便.
函数名 | 函数作用 |
---|---|
init_board() | 用来初始化两个数组 |
dispaly_board() | 用来展示数组给玩家 |
set_mine() | 用来初始化雷区 |
find_mine() | 用来进行扫雷 |
以上就是test.c的全部模块.下来我们展示test.c的完整代码.(VS2019)
//#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf(" 1.play\n");
printf(" 0.exit\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
//dispaly_board(mine, ROW, COL);
dispaly_board(show, ROW, COL);
set_mine(mine,ROW,COL);
//dispaly_board(mine, ROW, COL);
find_mine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("exit!");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
因为我们game.h中包含了所需的头文件和函数,所以引入game.h就足够.
game.c
首先我们要完成的是初始化函数
void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int x = 0; x < rows; x++)
{
for (int y = 0; y < cols; y++)
{
board[x][y] = set;
}
}
}
参数介绍:
参数名 | 参数作用 |
---|---|
char board[ROWS][COLS] | 接受需要初始化的数组 |
int rows | 数组的行数 |
int cols | 数组的列数 |
char set | 用来指定初始化数组的字符 |
这里需要注意的是rows和cols是比实际雷区的row和col大两个范围,因此实际数组比雷区大了一圈.这里主要有两个原因.
- 第一个原因就是因为数组的下标是从0开始的,而我们空过了行列为0的数组范围,就可以直接使用玩家输入的行和列来进行游戏.
- 另一个原因就是给雷区多了一圈的位置赋值为0,可以更好的进行是否有雷,有几个雷的函数判断.
打印函数.
void dispaly_board(char board[ROWS][COLS], int row, int col)
{
for (int j = 0; j <= col; j++)
{
printf("%d ",j);
}
printf("\n");
for (int x = 1; x <= row; x++)
{
printf("%d ", x);
for (int y = 1; y <= col; y++)
{
printf("%c ",board[x][y]);
}
printf("\n");
}
}
参数介绍:
参数名 | 参数作用 |
---|---|
int row | 雷区实际的行数 |
int col | 雷区实际的列数 |
布雷函数
void set_mine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if(mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
参数介绍:
参数名 | 参数作用 |
---|---|
char mine[ROWS][COLS] | 接受实际雷区的数组 |
EASY_COUNT | 雷区中雷的个数 |
因为这里布雷需要使用随机数函数rand(),所以test.c中.main()需要添加配套代码.(前面我们已经提到了.)
进行游戏.
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int z = 0;
for (z = 0; z < row*col- EASY_COUNT; z++) {
printf("请输入要排查的雷的坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
dispaly_board(mine, ROW, COL);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
dispaly_board(show, ROW, COL);
}
}
else
{
printf("该位置已经排查过\n");
z--;
}
}
else
{
printf("输入坐标有误,请重新输入\n");
}
}
if (z == row * col - EASY_COUNT)
{
printf("恭喜你\n");
}
}
参数介绍:
参数名 | 参数作用 |
---|---|
char show[ROWS][COLS] | 接受展示给玩家的数组 |
上述函数中还包含了get_mine_count();函数,用来计算不是雷是此块地周围的雷的个数.
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y] +
mine[x - 1][y-1] +
mine[x][y-1] +
mine[x + 1][y-1] +
mine[x + 1][y] +
mine[x + 1][y+1] +
mine[x][y+1] +
mine[x - 1][y+1] - );
}
这里减去(8 * '0')是因为雷区中存放的是字符'1',要计算个数就要减去字符'0'.
以上就是game.c的全部模块.下来我们展示game.c的完整代码.(VS2019)
#pragma once
#include "game.h"
void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int x = 0; x < rows; x++)
{
for (int y = 0; y < cols; y++)
{
board[x][y] = set;
}
}
}
void dispaly_board(char board[ROWS][COLS], int row, int col)
{
for (int j = 0; j <= col; j++)
{
printf("%d ",j);
}
printf("\n");
for (int x = 1; x <= row; x++)
{
printf("%d ", x);
for (int y = 1; y <= col; y++)
{
printf("%c ",board[x][y]);
}
printf("\n");
}
}
void set_mine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if(mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y] +
mine[x - 1][y-1] +
mine[x][y-1] +
mine[x + 1][y-1] +
mine[x + 1][y] +
mine[x + 1][y+1] +
mine[x][y+1] +
mine[x - 1][y+1] - 8 * '0');
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int z = 0;
for (z = 0; z < row*col- EASY_COUNT; z++) {
printf("请输入要排查的雷的坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
dispaly_board(mine, ROW, COL);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
dispaly_board(show, ROW, COL);
}
}
else
{
printf("该位置已经排查过\n");
z--;
}
}
else
{
printf("输入坐标有误,请重新输入\n");
}
}
if (z == row * col - EASY_COUNT)
{
printf("恭喜你\n");
}
}
同test.c相同,只需引入game.h即可.
game.h
最后我们展示game.h所需的的完整代码.(VS2019)
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
void init_board(char board[ROWS][COLS],int rows,int cols,char set);
void dispaly_board(char board[ROWS][COLS], int row, int col);
void set_mine(char mine[ROWS][COLS], int row, int col);
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
完结
以上就是简易版扫雷的全部实现.如果有意向,可以尝试递归产生扫雷的代码,这样会更接近经典.