文章目录
- 项目思路
- 一、分文件进行创建
- 二、进入游戏前的目录
- 2.1 目录的功能:
- 2.2 目录界面:
- 2.3 选择进入或退出游戏
- 2.3.1 代码示范
- 2.3.2 图片示例:
- 三、画出游戏界面
- 3.1 创建两个数组
- 3.2 初始化数组
- 3.3 打印游戏界面
- 3.3.1 代码思路
- 3.3.2 代码示范:
- 四、用随机值放雷
- 4.1 代码思路:
- 4.2 代码示范:
- 五、游玩扫雷
- 5.1 代码思路:
- 5.2 注意事项:
- 5.3 代码实现:
- 六、整体代码示范
- game.h
- test.c
- game.c
- 写在最后
项目思路
- 分文件进行创建
- 进入游戏前的目录
- 画出游戏界面
- 用随机值放雷
- 游玩扫雷
接下来,我们分步骤进行详细的解释说明。
一、分文件进行创建
在具体的项目实施中,我们需要分成不同的文件进行创建和书写,以此来保证项目的模块化。
那么在扫雷的实际书写中,
- 源文件:
- 测试游戏用的代码文件用test.c或者日期.c来作为文件名
- 游戏实现的底层代码用game.c文件作为文件名
- 头文件
- 游戏实现中使用的各个函数的声明,以及包含的其他库函数的头文件需要写在头文件game.h文件里
如图所示:
- 游戏实现中使用的各个函数的声明,以及包含的其他库函数的头文件需要写在头文件game.h文件里
二、进入游戏前的目录
2.1 目录的功能:
- 在游戏开始时,给玩家视觉上的帮助和提示
- 让玩家可以选择进入游戏或者退出游戏
- 将游戏形成一个可以不断重玩的循环
接下来,我们分步骤进行书写:
2.2 目录界面:
void menu()
{printf("***********************\n");printf("*****1、开始游戏*******\n");printf("*****0、退出游戏*******\n");printf("***********************\n");
}
接着,在main函数里面进行调用:
int main()
{menu();return 0;
}
这样目录的表面就写好了,接下来需要写玩家选择进入游戏和退出游戏的功能了
2.3 选择进入或退出游戏
选择功能的逻辑:1进入游戏,0退出游戏。
显然,必备的库函数有scanf,switch、case和default。为了让游戏的体验更加良好,可以再加一个printf增加视觉上的游玩帮助,用户友好。
那么根据刚刚的逻辑,可以写出如下的选择结构,其中game函数虽然还没有写出来,但是整体的框架可以先确定下来,之后再往里慢慢写内容。
2.3.1 代码示范
int main()
{int input = 0;menu();printf("请选择:--->");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("非法输入!请重试\n");break;}return 0;
}
2.3.2 图片示例:
三、画出游戏界面
3.1 创建两个数组
因为扫雷是一个隐藏式的游戏,放雷的数组玩家是不能看到的,所以需要两个数组,一个用来存放雷,一个用来展示给玩家隐藏后的界面,用来游玩。
创建数组代码示范:
char mine[ROWS][COLS];char show[ROWS][COLS];
这里的行和列,用自定义变量来代替,这样以后在想更改行列的时候就可以很方便了
自定义变量代码在头文件game.h中,代码示范:
#define ROW 9
#define COL 9
3.2 初始化数组
现在数组已经创建好了,由于没有进行初始化,数组里放的是一些“烫烫烫”之类的乱码。
所以需要写一个函数,给这两个数组进行初始化,这一步也是为之后的重玩奠定了基础。
代码思路:遍历数组每一个元素并赋值。
由于是给数组赋值,直接通过地址操作数组的,所以不需要返回值,直接void类型就可以。
至于接收值,需要接收:数组名、行、列、以及需要赋值的符号,这样才能让函数有效的对不同的数组进行初始化。
代码示范:
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = set;}}
}
在game里面的函数:
void game()
{char mine[ROWS][COLS];//用mine数组来放雷char show[ROWS][COLS];//用show数组来展示隐藏后的雷区InitBoard(mine, ROWS, COLS,'0');//把放雷的数组赋值成全0,这样可以方便之后的扫雷显示InitBoard(show, ROWS, COLS, '*');//把隐藏后的雷区赋成*(这个换其他的符号也可以)
}
3.3 打印游戏界面
3.3.1 代码思路
由于打印游戏界面是一个需要频繁进行的操作,无论是每次扫雷,还是被炸死的时候显示雷的位置,都需要打印。所以在这里,我们同样需要单独写一个函数来完成这个操作。
- 遍历数组并打印
- 返回值:由于是直接打印,是一个动作,所以做完后直接销毁就行,void类型
- 接收值:需要接收需要打印的数组、行、列
- 注意事项:
- 标头可以打印一个扫雷游戏分割线
- 在合适的地方加上换行,以保证游戏界面是9x9的正方形
- 在边缘处加上行和列的标号,以便玩家更方便的看到想扫的雷的坐标
- 注意是char数组,用%c 来打印,每个元素后面最好加空格,每一句后最好加换行
- 注意打印时数组的下标要从1开始,不要从0开始,否则扫雷的时候会向右下偏一位
3.3.2 代码示范:
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{printf("------扫雷游戏------\n");for (i = 0; i <= row; i++){printf("%d ", i); //在第一行打印列数}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);//在第一列打印行数for (j = 1; j <= col; j++){printf("%c ", board[i][j]);//打印每一位元素}printf("\n");}
}
图片示例:
四、用随机值放雷
4.1 代码思路:
- 首先放雷是需要一个随机性的,那么就可以使用srand和rand函数(伪随机数),加上时间戳,构成一个真随机数,再利用这个真随机数取一个行列的模,就可以实现随机的放雷了。
- 随机取十个坐标,把mine里面的数字放成1,10个雷全部放完之后就有71个0和10个1。
- 在实现代码的时候需要注意,随机取的坐标不能重复,需要是0才能赋1。
- 一共只需要十个雷,while循环,再用一个int count来计算真实赋进去的雷的个数,就可以实现随机放雷了。
- 由于还是远程操作数组,所以返回值是void,接收值仍然是数组和行列。
- 在雷数方面,可以通过自定义变量来方便以后的操作。
4.2 代码示范:
void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count) {i = rand() % row+1;j = rand() % col+1;if (board[i][j] == '0'){board[i][j] = '1';count--;}}
}
头文件的代码:
#define EASY_COUNT 10
五、游玩扫雷
5.1 代码思路:
- printf进行视觉提示,scanf让玩家输入坐标
- 将坐标所处的数组元素进行判断
- 如果是雷,游戏结束
- 如果不是雷,统计该地点周围8个点位的雷数,并显示在棋盘上
- 如果位置超出棋盘范围,则重新输入
- 此过程不断循环,直到除了雷以外的所有点位被排干净,判定玩家赢
5.2 注意事项:
- 如果该点位处于边角位,如果统计周边8个点位,数组会越界,所以需要把数组多拓两行,避免越界
- 数字和字符的相互转换:加上‘0’。比如如果想要把数字1转换为字符1,就需要加一个字符0,原理是0的ASCII码值是48,1的ASCII码值是49……加上字符0相当于加上48,正好是字符1的ASCII码值
5.3 代码实现:
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS] ,int row, int col)
{int win = 0;while (win < col * row - EASY_COUNT){printf("请输入要排查的坐标>:");scanf("%d %d", &i, &j);if (i > 0 && i <= row && j > 0 && j <= col){if (mine[i][j] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{int count = GetCountMine(mine, i, j);show[i][j] = count + '0';DisplayBoard(show, ROW, COL);win++;}}elseprintf("位置非法,请重新输入");}if (win == col * row - EASY_COUNT){printf("恭喜你,游戏胜利!\n");}
}
六、整体代码示范
game.h
#pragma once
#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 10void InitBoard(char board[ROWS][COLS],int row,int col,char set);
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void SetMine(char board[ROWS][COLS], int row, int col);
void FindMine(char board[ROWS][COLS], int row, int col);
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{printf("********************\n");printf("****** 1.play ******\n");printf("****** 0.exit ******\n");printf("********************\n");
}void game()
{char mine[ROWS][COLS];char show[ROWS][COLS];InitBoard(mine, ROWS, COLS,'0');InitBoard(show, ROWS, COLS, '*');//DisplayBoard(mine, ROW, COL); 这里的展示棋盘是用来测试代码用的,实际应用不需要DisplayBoard(show, ROW, COL);SetMine(mine, ROW, COL);//DisplayBoard(mine, ROW, COL);这里的展示棋盘是用来测试代码用的,实际应用不需要FindMine(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("退出游戏\n");break;default:printf("非法输入\n");break;}} while (input);return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"int i, j = 0;
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = set;}}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{printf("------扫雷游戏------\n");for (i = 0; i <= row; i++){printf("%d ", i); }printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count) {i = rand() % row+1;j = rand() % col+1;if (board[i][j] == '0'){board[i][j] = '1';count--;}}
}int GetCountMine(char mine[ROWS][COLS] ,int x,int y)
{return (mine[x - 1][y + 1] + mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y + 1] + mine[x][y - 1] + mine[x + 1][y + 1] + mine[x + 1][y] + mine[x + 1][y - 1] - 8 * '0');
}void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS] ,int row, int col)
{int win = 0;while (win < col * row - EASY_COUNT){printf("请输入要排查的坐标>:");scanf("%d %d", &i, &j);if (i > 0 && i <= row && j > 0 && j <= col){if (mine[i][j] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{int count = GetCountMine(mine, i, j);show[i][j] = count + '0';DisplayBoard(show, ROW, COL);win++;}}elseprintf("位置非法,请重新输入");}if (win == col * row - EASY_COUNT){printf("恭喜你,游戏胜利!\n");}
}
写在最后
如果本文对您有帮助,可不可以给我一个小小的点赞呀❤~您的支持是我最大的动力。
博主小白一枚,才疏学浅,难免有所纰漏,欢迎大家讨论和提出问题,博主一定第一时间改正。
谢谢观看嘿嘿(๑•̀ㅂ•́)و✧~!