游戏逻辑
1.游戏菜单
? ?打印菜单来让玩家来开始或结束游戏。
2.打印两个棋盘,也就是两个变量名分别为mine和show的二维字符型数组。
? ?mine二维数组用来存放地雷信息。show二维数组用来展示玩家的游戏进程。
3.实现玩家一步一步的排雷过程,若没有踩到雷则继续排雷,若踩到雷则游戏结束——玩家失败,若玩家未踩到雷并且? ? ?只剩下10格雷未排,则游戏结束——玩家通关。
一、程序框架
我们将游戏的源文件和头文件分为三个部分,分别是:game.h 、test.c 、game.c
1. game.h????????
在game.h中为所有需要用到的库函数的头文件的声明,以及要在test.c源文件中使用需要在game.h中定义的自定义函数的声明。
2.test.c
test.c为游戏的整体逻辑部分,并引用头文件"game.h"。
3.game.c
game.c为游戏的实现部分,也要引用头文件"game.h"。
二、游戏的实现
1.在源文件test.c中编辑游戏的整体逻辑
1-1.创建主函数
为了让主函数简洁,通过在主函数中调用test(),在test()中实现整体逻辑。
int main()
{
test();
return 0;
}
1-2.定义test()函数
1.随机数的生成
2.调用menu自定义函数生成菜单
3.运用do...while语句和switch语句实现开始界面
4.在switch语句中调用game()自定义函数开始游戏进程
void test()
{
srand((unsigned int)time(NULL)); //生成随机数的库函数调用
int input = 0;
do
{
menu();
printf("请输入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏 \n");
break;
default:
printf("输入错误!!!(请重新输入1 or 0)");
break;
}
} while (input);
}
1-3.定义menu()函数
void menu()
{
printf("******************************\n");
printf("**** 1. play ****\n");
printf("**** 0. exit ****\n");
printf("******************************\n");
}
1-4.定义game()函数
以下为test.c源文件的整体逻辑
#include "game.h"
void menu()
{
printf("******************************\n");
printf("**** 1. play ****\n");
printf("**** 0. exit ****\n");
printf("******************************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//DisplayBoard(mine, ROWS, COLS);
DisplayBoard(show, ROWS, COLS);
SetMines(mine, ROW, COL);
//DisplayBoard(mine, ROWS, COLS);
SweepMines(mine, show, ROWS, COLS);
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏 \n");
break;
default:
printf("输入错误!!!(请重新输入1 or 0)");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
2.game.h头文件部分的内容
头文件中包含对库函数、自定义函数的声明。
//库函数的声明
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定义宏常量,便于后期增加雷的数量、棋盘的大小,来增加游戏难度
#define ROW 9
#define COL 9
//这里定义COWS COLS为11行是为了方便后续对周围8个位置的雷的数量的计算
//要注意 COW COL 和 COWS COLS 使用情况的区别
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10
//自定义函数的声明
InitBoard(char board[ROWS][COLS], int row, int col, char set);
DisplayBoard(char board[ROWS][COLS], int row, int col);
SetMines(char board[ROWS][COLS], int row, int col);
SweepMines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
3.game.c 游戏逻辑的实现
game.c是对test.c中game()函数中所使用的函数的定义。
3-1.InitBoard() 自定义的棋盘初始化函数
? ? ? ?将mine二维数组的所有元素都初始化为 '0',将show二维数组的所有元素都初始化为 '*'。
//初始化
InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
}
3-2.打印二维数组的内容
//打印二维数组
DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row - 1; i++)
{
printf("%d ", i); //在每一行前面加上行号
}
printf("\n");
for (i = 1; i < row - 1; i++) //数组打印从下标为[1]开始,到下标为[9]结束一共9行
{
printf("%d ", i); //在每一列上面加上列号
for(j = 1; j < col - 1; j++) //数组打印从下标为[1]开始,到下标为[9]结束一共9列
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
打印效果:
mine二维数组:
?show二维数组:
?3-3.随机生成地雷
SetMines(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
int x = 0;
int y = 0;
while (count)
{
x = rand() % row + 1; //生成随机数 % 9行 得到数字1~8 加上1 得到数字 1~9
y = rand() % col + 1; //!!!注意此处的row与col 为ROW和COL,而不是ROWS和COLS
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (board[x][y] == '0') //判断生成雷的位置是否为'0',避免在同一个位置重复生成
{
board[x][y] = '1';
count--;
}
}
}
}
效果:
?3-4.玩家游戏进程
int Mines_num(char mine[ROWS][COLS], int x, int y)
{
//周围8个位置的字符'1'或'0'加在一起减去8个'0',就能得到雷的数量
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';
}
SweepMines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (count < COL * ROW - EASY_COUNT)
{
printf("请输入:>");
scanf("%d%d", &x, &y);
//第一步:判断玩家输入是否正确
if (x > 0 && x < row - 1 && y > 0 && y < col - 1)
{
//第二步:判断该位置是否是雷
if (mine[x][y] == '0') //如果不是雷,则在该位置显示周围8个位置雷的数量
{
//调用自定义Mines_num函数计算周围雷的数量,加'0'变为字符存放在该位置。
show[x][y] = Mines_num(mine, x, y) + '0';
DisplayBoard(show, ROWS, COLS);
count++;
}
else //如果是雷,则游戏结束,并打印存放地雷的数组,让玩家了解到是什么情况
{
DisplayBoard(mine, ROWS, COLS);
printf("很遗憾!!!地雷爆炸了\n");
break;
}
}
else
{
printf("输入错误!!!(请重新输入坐标1 ~ 9)\n");
}
}
if (count == COL * ROW - EASY_COUNT)
{
printf("恭喜你!!!排雷成功 !^o^!\n ");
}
}
game.c的整体逻辑:
#include "game.h"
InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
}
DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row - 1; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i < row - 1; i++)
{
printf("%d ", i);
for(j = 1; j < col - 1; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
SetMines(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
int x = 0;
int y = 0;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
}
int Mines_num(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';
}
SweepMines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (count < COL * ROW - EASY_COUNT)
{
printf("请输入:>");
scanf("%d%d", &x, &y);
if (x > 0 && x < row - 1 && y > 0 && y < col - 1)
{
if (mine[x][y] == '0')
{
int ret = Mines_num(mine, x, y);
show[x][y] = ret + '0';
DisplayBoard(show, ROWS, COLS);
count++;
}
else
{
DisplayBoard(mine, ROWS, COLS);
printf("很遗憾!!!地雷爆炸了\n");
break;
}
}
else
{
printf("输入错误!!!(请重新输入坐标1 ~ 9)\n");
}
}
if (count == COL * ROW - EASY_COUNT)
{
printf("恭喜你!!!排雷成功 !^o^!\n ");
}
}
到这里我们就完成了扫雷游戏的整体游戏逻辑了,快去试试看吧!
|