1.游戏主逻辑
游戏我创建了三个文件来完成,便于分工和包装,分别是头文件game.h用来存放函数声明和库函数,test.c用来编写游戏主逻辑,以及game.c用来编写是实现整个游戏的函数
1.1创建游戏菜单以及开始选项
游戏至少玩一次,还可以继续玩,所以用do while循环实现主逻辑,首先打印一个菜单,用switch语句给玩家两个选项:1.开始游戏,2.退出游戏,输入其他提示输入错误重新输入。
void menu() { printf("**********************************\n"); printf("******** 1.play ********\n"); printf("******** 0.exit ********\n"); printf("**********************************\n"); } int main() { int input = 0; srand((unsigned int)time(NULL)); do { //打印菜单 menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: printf("开始游戏\n"); play_game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择:>\n"); break; } } while (input); return 0; }
1.2游戏规则和思路
游戏规则:输入要排查的坐标,会显示以该坐标为中心的周围8个格子内的雷的个数,如果排查的位置是雷则游戏失败,排查完所有的雷即游戏成功。
游戏思路:根据规则就需要我们首先来初始化并打印一个棋盘,在棋盘中随机置雷,让玩家来输入坐标排雷,据此来判断坐标周围雷的个数有以及游戏的成败。
1.3游戏主逻辑代码实现
1.3.1棋盘越界问题
这里我们要考虑一下判断时的棋盘越界问题,看图:
这里咱想到一种解决方法,那就是初始化时使用11*11的棋盘,而在使用和在屏幕上显示时使用9*9的棋盘,这样就不用考虑越界问题了,如下图:
1.3.2设置置雷棋盘和排雷棋盘
用户每排查一个坐标次我们都需要将棋盘打印出来让用户观察该坐标周围有几个雷的情况,如果这样的话一旦我们将棋盘打印出来那么所有的雷不就暴露了吗?为了解决这一问题,我使用了两个棋盘,一个置雷棋盘用0来初始化用1来布置雷(0表示非雷,1表示有雷),一个排雷棋盘用*来初始化给用户观察,根据输入的坐标在置雷棋盘中判断,然后将数字在排雷棋盘中显示出来,其他位置依旧是全*覆盖,这样就能很好的解决这一问题
解决了上面这两个问题我们就可以来初始化棋盘了
1.3.3初始化棋盘
创建两个数组存放信息
//设置两个数组存放信息 char mine[ROWS][COLS] = { 0 }; char show[ROWS][COLS] = { 0 };
行和列在头文件中用#define来定义:
//9*9棋盘 #define ROW 9 #define COL 9 //11*11棋盘 #define ROWS ROW+2 #define COLS COL+2
初始化棋盘:
置雷棋盘全部初始化为0,排雷棋盘全部初始化为*,共用一个初始化数组
//初始化棋盘 void init_board(char board[ROWS][COLS],int rows,int cols,int set) { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } } //初始化置雷棋盘 init_board(mine, ROWS, COLS, '0'); //初始化排雷棋盘 init_board(show, ROWS, COLS, '*');
1.3.4布置雷
要实现随机布置雷,这里需要使用随机值调用rand()函数,要用到srand()随机生成器,这个生成器只需要调用一次,所以放在main()函数开头不必进入循环,这里要注意加一个该坐标是否被占用的判断,没有就将该坐标赋值为1,反之则重新随机布置
void set_mine(char mine[ROWS][COLS], int row, int col)//9*9 { //随机布10个雷 int count = EASY_COUNT; while (count) { //在11*11的棋盘中给9*9棋盘布置雷,所以横纵坐标都+1 int x = rand() % row + 1; int y = rand() % col + 1; //判断该坐标是否被占用,没有的话就赋值'1'表示有雷 if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }
1.3.5打印排雷棋盘
我们将棋盘整的尽量整洁美观便于用户观察,像这样:
具体代码实现:
void display_board(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; //列号 for (j=0;j<=col;j++) { printf("%d ", j); } printf("\n"); for (i = 1; i <= row; i++) { //行号 printf("%d ", i); //排雷棋盘 for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } }
1.3.6排查雷
我们需要注意几个点:1.判断坐标是否越界;2.判断坐标是否被排查过;3.判断所排查的坐标周围有几个雷;4.每排查一次都需要打印一遍置雷棋盘方便用户观察
这里我们重点讲一下实现第三点:由于咱们是用0来初始化用1来布置雷,这里将想要排查的坐标的周围的8个坐标的值相加再减去8 * '0'就可以得到周围雷的个数将其赋给想要排查的坐标打印出来就完成了。
具体代码实现:
//判断坐标周围有几个雷 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 win = 0; while (win<row * col - EASY_COUNT) { printf("请输入要排查的雷的坐标:>"); scanf("%d %d", &x, &y); //判断是否越界(9*9) if (x >= 1 && x <= row && y >= 1 && y <= col) { //判断坐标是否被排查过 if (show[x][y] == '*') { if (mine[x][y] == '1') { printf("很遗憾,你被炸死了\n"); //打印一遍置雷棋盘 display_board(mine, ROW, COL); break; } else { //判断坐标周围有几个雷 int count = get_mine_count(mine, x, y); show[x][y] = count + '0'; //打印一遍排雷棋盘 display_board(show, ROW, COL); win++; } } else { printf("该坐标已经被排查过了\n"); } } else { printf("坐标非法,请重新输入\n"); } //排完雷则游戏结束 if (win == row * col - EASY_COUNT) { printf("恭喜你,扫雷成功!\n"); display_board(mine, ROW, COL); } } }
2.整个游戏代码
2.1game.h 函数声明和库函数
#pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> //9*9棋盘 #define ROW 9 #define COL 9 //11*11棋盘 #define ROWS ROW+2 #define COLS COL+2 //设置雷的个数 #define EASY_COUNT 10 //初始化棋盘 void init_board(char board[ROWS][COLS], int rows, int cols, int set); //打印棋盘 void display_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);
2.2test.c 游戏主逻辑
#define _CRT_SECURE_NO_WARNINGS #include"game.h" void menu() { printf("**********************************\n"); printf("******** 1.play ********\n"); printf("******** 0.exit ********\n"); printf("**********************************\n"); } void play_game() { //设置两个数组存放信息 char mine[ROWS][COLS] = { 0 }; char show[ROWS][COLS] = { 0 }; //初始化棋盘 //将mine初始化为全'0',将show初始化为全'*' //直接将'0'和'*'传入函数,用char类型接收,,方便一个函数初始化两个数组 init_board(mine, ROWS, COLS, '0'); init_board(show, ROWS, COLS, '*'); //打印棋盘 //布置雷 set_mine(mine, ROW, COL); //排查雷 display_board(show, 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: printf("开始游戏\n"); play_game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择:>\n"); break; } } while (input); return 0; }
2.3game.c 游戏函数实现
#define _CRT_SECURE_NO_WARNINGS #include"game.h" //初始化棋盘 void init_board(char board[ROWS][COLS],int rows,int cols,int set) { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void display_board(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; //列号 for (j=0;j<=col;j++) { printf("%d ", j); } 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 set_mine(char mine[ROWS][COLS], int row, int col)//9*9 { //随机布10个雷 int count = EASY_COUNT; while (count) { //在11*11的棋盘中给9*9棋盘布置雷,所以横纵坐标都+1 int x = rand() % row + 1; int y = rand() % col + 1; //判断该坐标是否被占用,没有的话就赋值'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 win = 0; while (win<row * col - EASY_COUNT) { printf("请输入要排查的雷的坐标:>"); scanf("%d %d", &x, &y); //判断是否越界(9*9) if (x >= 1 && x <= row && y >= 1 && y <= col) { //判断坐标是否被排查过 if (show[x][y] == '*') { if (mine[x][y] == '1') { printf("很遗憾,你被炸死了\n"); //打印一遍置雷棋盘 display_board(mine, ROW, COL); break; } else { //判断坐标周围有几个雷 int count = get_mine_count(mine, x, y); show[x][y] = count + '0'; //打印一遍排雷棋盘 display_board(show, ROW, COL); win++; } } else { printf("该坐标已经被排查过了\n"); } } else { printf("坐标非法,请重新输入\n"); } //排完雷则游戏结束 if (win == row * col - EASY_COUNT) { printf("恭喜你,扫雷成功!\n"); display_board(mine, ROW, COL); } } }
整个小游戏到这里就结束,友友们喜欢的话不妨来个关注加三连支持一下,后期会持续更新C语言干货!