赞
踩
目录
这种类型的小游戏,是对基础知识很好的复习!
实现前准备:
一 . 了解游戏如何玩
简单版举例:
一个9*9的棋盘中有10个雷,你要将他们一一排除,直到排除完所有雷,踩到雷你就会死亡。
踩到不是雷的地方,会扫描附近8格方格,并会告诉你这附近8个方格中的雷数。
如:
图中的2附近8个方格中,只有最后两个未排除那他们一定就是雷
你不信?你踩下去试试:
二.实现前思想
- 可以用二维数组来当棋盘
- 用1当雷0为非雷,这样可以方便计算附近的雷数
- 编写函数,实现输入输出和判断游戏状态的函数
三. 解决代码较多问题
因为考虑到代码量较多,为了代码的整洁性,可读性,我把代码分成了3个部分
- minesweeper.c —— 用来实现游戏的本身的逻辑
- game.c —— 功能函数的实现
- game.h —— 函数的声明和头文件和宏的等声明
不管如何要先进入系统,所有用do while循环实现,然后打印一个菜单给玩家选择:
菜单:
//菜单 void menu() { printf("*****************************\n"); printf("******** 1 . play *******\n"); printf("******** 0 . exit *******\n"); printf("*****************************\n"); }
有了菜单玩家要选择,创建input变量,把退出项设为0,input就可以作为循环的表达式,在c语言中0为假1为真,真执行,假不执行,玩家选择0为假喜欢停止退出程序
- 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");
- }
- } while (input);
- return 0;
- }
游戏主体需要实现各种功能,把他们放在game.c文件中,函数、宏、头文件、声明在game.h头文件中
考虑到如果是边缘的方块要检测,那就非常的不好办了:
我们干脆做大一圈,但只使用内圈,这样排除起来就方便了:
定义宏做为二维数组参数:
-
- //控制棋盘大小:
- //如:9*9
- #define ROW 9
- #define COL 9
-
- //实际使用+2保证棋盘大一圈
- #define ROWS ROW+2
- #define COLS COL+2
创建二维数组,用来做棋盘,由于考虑到1作为了雷,那检测显示附近的雷数如果是1就麻烦了,所以创建两个数组一个用来放雷,一个用来打印和显示附近雷数。
- //设计两个数组存放信息
- //mine放雷
- //show用来打印和附近雷的数量
- char mine[ROWS][COLS] = { 0 };
- char show[ROWS][COLS] = { 0 };
我们把mine放雷:1为雷0为非雷
再把show用来打印和附近的雷数:#为雷*为非雷
实参:
- //mine - 全部初始化为 0
- //show - 全部初始化为 *
- init_board(mine, ROWS, COLS, '0');
- init_board(show, ROWS, COLS, '*');
形参:
- //初始化
- void init_board(char board[ROWS][COLS], char rows, int cols, char set)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- board[i][j] = set;//set为传过来的图案如:0或*
- }
- }
- }
函数声明放在game.h文件中:
后面就不说函数定义了都跟函数形参那一排一样
- //初始化棋盘
- void init_board(char board[ROWS][COLS], int rows, int cols, char set);
初始化好了棋盘,我们需要一个能够随时打印棋盘的函数:
实参:
display_board(show, ROW, COL);
形参:
- //棋盘打印
- void display_board(char board[ROWS][COLS], int row, int col)
- {
- int i = 0;
- int j = 0;
- 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");
- }
-
- }
效果:
其余部分计是棋盘
棋盘出来了但里面还没有雷
这里就要介绍前面主函数中的:
srand((unsigned int)time(NULL));
了解:
#include <stdlib.h>
1.rand库函数 生成一个随机数 在调用rend之前,需要先调用srand随机生成器
2.srand 设置一个随机的起点
- //(强制类型转换unsigned int)是因为srand里的数据类型是unsigned int
- //NULL是因为time是返回当前时间(秒数),这里并不需要他返回
- srand((unsigned int)time(NULL));
这里我们再定义一个宏可以随意的控制雷的数量:
- //控制雷数:
- #define EASY_COUNT 10
函数实现:
- //布置雷
- void set_mine(char mine[ROWS][COLS], int row, int col)
- {
- int count = EASY_COUNT;
- while (count)
- {
- //EASY_COUNT = 10
- //随机值 % 9 = 0 - 8的数字
- //+ 1 产生 1 - 9 的数
- //刚好符合我们要使用的二维数组的下标
- int x = rand() % row + 1;
- int y = rand() % col + 1;
-
- if (mine[x][y] == '0')
- {
- mine[x][y] = '1';
- count--;
- }
- }
- }
效果:
由于我们存放的是字符数字 如: ' 3 '
他的ASCII码并不是3看图:
但是可以发现这样的规律:
0 - 9字符的ASCII码减去0得原数字
' 2 ' - ' 0 ' = 50 - 48 = 2
那我们就可以把周围排查的数加起来的和,减去 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');
- }
提醒:
- mine数组是放雷的
- show是用来显示的
- //玩家排除雷,初步
- 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 (1)
- {
- printf("请输入排雷坐标:>");
- scanf("%d %d", &x, &y);
- if (x >= 1 && x <= row && y >= 1 && y <= col)
- {
- int count = get_mine_count(mine, x, y);//设计一个函数来排查周围8个方格中的雷
- show[x][y] = count + '0';
- display_board(show, ROW, COL);
- }
- else
- {
- printf("非法坐标,请重新输入\n");
- }
- }
- }
-
效果:
可以看到,排查的位置周围有两个雷
在这段代码中我们只判断了,输入的值超出界限的情况,但是还有许多游戏状态:
- 还有坐标重复
- 被雷炸死
- 还有最后胜利的状态
加入判断:
- //排雷
- void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
- {
- int x = 0;
- int y = 0;
- int win = 0;
- // win依依排查到最后等于71不在 < 9 * 9 - 10 = 71
- while (win < row * col - EASY_COUNT)//当win排查出所有雷,停止循环
- {
- 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");
- display_board(mine, ROW, COL);
- break;
- }
- else
- {
- //设计一个函数来排查周围8个方格中的雷
- int count = get_mine_count(mine, x, y);
- show[x][y] = count + '0';//得出来的值+‘ 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);
- }
- }
这里为了给大家展示我把雷的数量改到79,把mine放雷的棋盘一起打印出来,给大家看游戏各个状态
胜利状态:
重复输入状态:
超出范围状态:
炸死状态:
源码:
minesweeper.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()
- {
- //设计两个数组存放信息
- //mine放雷
- //show用来打印和附近雷的数量
- char mine[ROWS][COLS] = { 0 };
- char show[ROWS][COLS] = { 0 };
-
-
- //mine - 全部初始化为 0
- //show - 全部初始化为 *
- init_board(mine, ROWS, COLS, '0');
- init_board(show, ROWS, COLS, '*');
-
- //打印棋盘
- /*display_board(mine, ROW, COL);
- display_board(show, ROW, COL);*/
-
- //布置雷
- set_mine(mine, ROW, COL);
- /*display_board(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 :
- game();
- break;
- case 0 :
- printf("退出游戏\n");
- break;
- default:
- printf("输入错误请重新选择\n");
- }
- } while (input);
- return 0;
- }
game.c
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"game.h"
- //初始化
- void init_board(char board[ROWS][COLS], char rows, int cols, char set)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- board[i][j] = set;//set为传过来的图案如:0或*
- }
- }
- }
-
- //棋盘打印
- void display_board(char board[ROWS][COLS], int row, int col)
- {
- int i = 0;
- int j = 0;
- 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 set_mine(char mine[ROWS][COLS], int row, int col)
- {
- int count = EASY_COUNT;
- while (count)
- {
- //EASY_COUNT = 10
- //随机值 % 9 = 0 - 8的数字
- //+ 1 产生 1 - 9 的数
- //刚好符合我们要使用的二维数组的下标
- 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 win = 0;
- // win依依排查到最后等于71不在 < 9 * 9 - 10 = 71
- while (win < row * col - EASY_COUNT)//当win排查出所有雷,停止循环
- {
- 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");
- display_board(mine, ROW, COL);
- break;
- }
- else
- {
- int count = get_mine_count(mine, x, y);//设计一个函数来排查周围8个方格中的雷
- show[x][y] = count + '0';//得出来的值+‘ 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);
- }
- }
-
- 玩家排除雷,初步
- //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 (1)
- // {
- // printf("请输入排雷坐标:>");
- // scanf("%d %d", &x, &y);
- // if (x >= 1 && x <= row && y >= 1 && y <= col)
- // {
- // int count = get_mine_count(mine, x, y);//设计一个函数来排查周围8个方格中的雷
- // show[x][y] = count + '0';
- // display_board(show, ROW, COL);
- // }
- // else
- // {
- // printf("非法坐标,请重新输入\n");
- // }
- // }
- //}
game.h
- //控制棋盘大小:
- //如:9*9
- #define ROW 9
- #define COL 9
-
-
- //实际使用+2保证棋盘大一圈
- #define ROWS ROW+2
- #define COLS COL+2
-
-
- //控制雷数:
- #define EASY_COUNT 10
-
-
- #include<stdio.h>
- #include<stdlib.h>
- #include<time.h>
-
-
- //初始化棋盘
- void init_board(char board[ROWS][COLS], int rows, int cols, char 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);
如果这篇博客对你有帮助,一键三连走一波,你们的支持是我最大的动力!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。