文章目录
- 前言
- 一、游戏分析与设计
- 1.游戏的过程
- 2.游戏需要的知识点
- 2.1随机数函数
- 2.2头文件的自定义
- 2.3 宏定义的使用
- 二.代码的实现与步骤
- 1.main函数(test.c)
- 2.game.h(头文件)
- 3.game函数(game.c)
- 3.1 InitBoard(初始化函数)``
- 3.2 DisplayBoard(打印棋盘函数)
- 3.3 SetMine(布置雷函数)
- 3.4 FindMine(排查雷函数 )
- 三.原代码
- 1.game.h
- 2.test.c
- 3.game.c
- 四.总结
前言
通过,前面的学习,我们学习了,数组与函数(没有写的话,就是本人懒得写了👻),然后我们就可以编写一个的程序,关于扫雷游戏的编程。
一、游戏分析与设计
这里提供了在线玩扫雷的网址,大家可以先玩玩,观察一下
扫雷游戏网页版 - Minesweeper
1.游戏的过程
- 首先,本游戏是通过控制台进行的排雷游戏。
- 其次,可以通过菜单来控制是否进行游戏。
- 难度为9*9的棋盘,有十个雷.
- 可以排查雷以及标记雷
如果该位置是雷,则游戏失败;
如果该位置不是雷,则可以展开一片直到附近有雷。- 将所有雷都排查出来游戏胜利。
具体流程:
初始化的界面:
游戏开始界面:
游戏结束页面:
2.游戏需要的知识点
2.1随机数函数
我们在这简单的讲述一下:
我们会用到:
rand()>>产出随机数
srand()>>避免rand(),生成假的随机数
time()>>使每次的数都不一样。
#include<stdio.h>
#include<stdlib.h>//srand()的头文件
#include<time.h>//time()的头文件
int main()
{
srand((unsigned int)time(NELL));
//srand要返回正整数型
//time的值不知道,所以用NELL(空)来表示
int i = rand();
printf("%d\n",i);
return 0;
}
这就是随机数的函数的大概写法。
2.2头文件的自定义
我们需要在头文件中创造一个.h的文件,用来存储我们的相关的头文件,函数,宏定义等等,可以使我们的主文件,更简洁,更明了。
但主文件中要用 #include" game.h"来引入头文件,是代码可以正常运行。
2.3 宏定义的使用
正如上图所示,宏定义是用 #define 来修饰的 。如:
#define ROW 9
//注意要有空格。
这样,只要头文件中包含,就可以使ROW的值固定为9;且只要在头文件中修改,就可以使全局的值可以修改。
二.代码的实现与步骤
为了程序更加简明,我们需要设立三个文件,分别为:
test.c的源文件 ,用于游戏的逻辑测试。
game.c的源文件,用于游戏各个函数的代码实现。
game.h的头文件,用于函数声明以及各种数据类型的包含。
1.main函数(test.c)
首先为了整个游戏做到可以多次玩,它可以是放在循环里的,这个时候我们可以用一个do while语句来作为主体,玩家是需要选择的,所以我们可以用到switch语句来进行下一步的操作。代码初步如下:
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void mune()
{
printf("****************\n");
printf("****1.PLAY******\n");
printf("****0.EXIT******\n");
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
mune();
printf("请输入你的选项:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("GAME OVER\n");
break;
default:
printf("输入错误,请重新输入。\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
2.game.h(头文件)
设置 test.c需要的相关的头文件,并且运用宏定义设置棋盘的行与列和雷的个数。
#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//定好雷的个数为10;
3.game函数(game.c)
3.1 InitBoard(初始化函数)``
因为,在计算机里,对“0”和“1”这两个数非常敏感。而且两个数代表了真与假,所以我们可以用两个数字来代表是否有雷。所以我们可以将数组里全放上“0”,然后再随机生成10个“1”,这可以大概描述游戏的运行布骤。
所以我们先初始化棋盘:
//制作二个二维数组,一个可见,一个不可见;
char mine[ROWS][COLS] = { 0 };//存放雷的信息
char show[ROWS][COLS] = { 0 };//存放排放出的雷的信息
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;//使棋盘初始化为0;
}
}
}
这样,你就可以打印棋盘,使棋盘在控制台中显示出来。
3.2 DisplayBoard(打印棋盘函数)
打印棋盘,但仅仅打印show函数,而不是mine函数,这样我们就可以隐藏埋雷的地图,也可以放后面,中雷后显示出来。
DisplayBoard(show, ROW, COL);
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
printf("******扫雷*****\n");
int i = 0;
for(i = 0;i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 0;
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
3.3 SetMine(布置雷函数)
布置雷函数,我们需要使用随机数生成函数,并且要保证雷不能在同一位置,从而使雷的个数减少。并且运用count的个数的减少,来判断雷的个数。
SetMine(mine, ROW, COL);
void SetMine(char mine[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 (mine[x][y] != '1')
{
mine[x][y] = '1';
count--;
}
}
}
3.4 FindMine(排查雷函数 )
这里我们运用了两个函数,其一是,判断周围雷的个数,在我们选的位置上下左右八个位置中,使用while来循环减’0’,因为字符1减字符0,正好等于49-48=1,所以可以计算,周围雷的个数。
FindMine(mine, show, ROW, COL);
int GetMineCount(char mine[ROWS][COLS], int x, int y)
//判断周围雷的个数
{
int i = 0;
int count = 0;
for (i = -1; i <= 1; i++)
{
int j = 0;
for (j = -1; j <= 1; j++)
{
count += (mine[x + i][y + j] - '0');//八个位置的和减去'0'>>'1'-'0'=49-48=1>>字符型转整型
}
}
return count;
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < col * row - EASY_COUNT)
{
printf("请输入要排查的坐标:");
scanf("%d %d",&x,&y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')//注意 :==
{
printf("很遗憾,你踩雷了,游戏结束\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("输入的坐标有误x(1~9),y(1~9),重新输入");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
这样,进行编写,你就可以得到排雷游戏的大概编写思路,如何有了清晰的了解,你也可以进行尝试,并对照下方的原代码。
三.原代码
1.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 10
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
2.test.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void mune()
{
printf("****************\n");
printf("****1.PLAY******\n");
printf("****0.EXIT******\n");
}
void game()
{
//制作二个二维数组,一个可见,一个不可见;
char mine[ROWS][COLS] = { 0 };//存放雷的信息
char show[ROWS][COLS] = { 0 };//存放排放出的雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//开始排雷
FindMine(mine, show, ROW, COL);
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
mune();
printf("请输入你的选项:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("GAME OVER\n");
break;
default:
printf("输入错误,请重新输入。\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
3.game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
printf("******扫雷*****\n");
int i = 0;
for(i = 0;i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 0;
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//布置雷>>棋盘随机10各个坐标
void SetMine(char mine[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 (mine[x][y] != '1')
{
mine[x][y] = '1';
count--;
}
}
}
//排查雷
int GetMineCount(char mine[ROWS][COLS], int x, int y)
//判断周围雷的个数
{
int i = 0;
int count = 0;
for (i = -1; i <= 1; i++)
{
int j = 0;
for (j = -1; j <= 1; j++)
{
count += (mine[x + i][y + j] - '0');//八个位置的和减去'0'>>'1'-'0'=49-48=1>>字符型转整型
}
}
return count;
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < col * row - EASY_COUNT)
{
printf("请输入要排查的坐标:");
scanf("%d %d",&x,&y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')//注意 :==
{
printf("很遗憾,你踩雷了,游戏结束\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("输入的坐标有误x(1~9),y(1~9),重新输入");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
四.总结
对于这个排雷游戏,还有很多功能等待开发与维护,以后也会不定期更新优化这个小游戏的,如有其他有趣的想法也会在第一时间与大家分享!