Hello,大家好!我是鸿。继上次用C来实现了三子棋,想必各位还不是很尽兴吧?没关系,今天又有一个简单有趣的小游戏来啦!它就是——扫雷,废话不多说接下来就跟着我一起玩一下吧。
目录
一、游戏介绍
在电脑上扫雷是一款非常经典的小游戏,也是一些操作系统自带的游戏之一。一般由多个正方形区块组成,其中有些区块隐藏着炸弹,而其他区块则显示数字,数字表示该方块周围8个格子中有多少个炸弹。玩家需要在不触雷的前提下,依靠数字推断出哪些方块是炸弹,然后标记出来。标记完所有炸弹后,玩家将在不触雷的情况下清空所有非炸弹的方块,游戏胜利。如果玩家在标记过程中触雷,游戏失败。
二、基本思路
1.生成菜单方便玩家选择
2.生成棋盘
3.电脑随机放置雷
4.玩家排雷
5.判断游戏胜负
三、游戏代码实现
1、打印菜单
通过switch语句和循环供玩家选择,0代表退出游戏,1进入游戏,如果是无效的选择则让玩家重新选择
void menu()//菜单函数
{
printf("\n");
printf(" ***************************\n");
printf(" ****** 扫 雷 *******\n");
printf(" ****** 0. exit *******\n");
printf(" ****** 1. play *******\n");
printf(" ***************************\n");
printf("\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
//扫雷小游戏运行测试文件
#include"MineSweep.h"
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 0 :
printf("退出游戏!\n");
break;
case 1:
game();
break;
default:
printf("该选择无效!请重新选择\n");
break;
}
} while (input);
return 0;
}
2、生成棋盘
首先我们需要生成9×9的游戏棋盘,但是为了在放置雷时可以同=统一算法我们需要在外围多加一圈,即为11×11的二维数组,我们可以定义两个11×11的二维字符数组,一个用于放置雷,另一个用于统计雷并显示出来给玩家。‘0标识不是雷,字符’1‘标识为雷,字符’*'标识没有排查部分,空格标识已排除部分
ROWS和COLS分别为#difine定义的常量标识 11
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
3、初始化棋盘并显示棋盘
我们需要定义函数InitBoard(),和PrintBoard()通过传不同的参数”0“和”*“对两个数组进行初始化,然后打印show数组,此时传参的打印范围应为9×9
void InitBoard(char board[ROWS][COLS], int 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;
}
}
}
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 0; i <= col; 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.电脑随机放置雷
接下来就是玩家通过坐标对雷进行排查了,我们定义一个Set Mine函数进行放置雷的操作
通过rand()生成随机下标X和Y对mine数组中元素更改为10个’1‘表是安放10个雷。这里需要注意几点:
1.雷安放需要限定在9×9的格子范围内
2.不能将雷放置在同一个格子里面
运行截图:
5.排查雷
这里我们这里定义两个函数FindMine和GetMineCount,分别对雷进行排查和统计雷的个数,将Setmine函数放置在while数组中进行循环判断,玩家通过输入坐标进行排查,如果输入的坐标位置恰好就是雷,那么退出并结束游戏。当10个雷都被排查出来即为获胜。如果输入的坐标位置不是雷则返回该坐标周围雷的个数,并在棋盘显示。注意由于show数组为字符数组所以统计雷的个数返回的应该还是字符,通过ascll表,我们对返回雷的数组加一个字符’0‘即可转换为字符。
void SetMine(char board[ROWS][COLS], int row, int col)
{
//基础版设置十个雷
int count = BASIC;
int x = 0;
int y = 0;
srand((unsigned int)time(NULL));
while (count)
{
//随机放置10个雷
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
int GetMineCount(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';
}
效果展示:
6.封装函数
定义一个game函数对上述所用到的函数进行封装,并建一个头文件对它们进行声明,在主函数里面运行。
头文件:
#pragma once
//扫雷小游戏函数声明文件
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 9//棋盘行
#define COL 9//棋盘列
#define ROWS ROW+2
#define COLS COL+2
#define BASIC 10//基础版,定义10个雷
void menu();//菜单
void game();//游戏函数主题实现
void InitBoard(char board[ROWS][COLS], int row, int col,char set);//初始化函数
void PrintBoard(char board[ROWS][COLS], int row, int col);//显示棋盘
void SetMine(char board[ROWS][COLS], int row, int col);//设置雷
int GetMineCount(char mine[ROWS][COLS], int x, int y);//计算周围雷的个数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//排查雷
game函数:
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine,ROWS,COLS,'0');//初始化雷
InitBoard(show, ROWS, COLS,'*');//初始化棋盘
PrintBoard(show, ROW, COL);//显示棋盘
SetMine(mine, ROW, COL);//安放雷
//PrintBoard(mine, ROW, COL);//显示雷的位置
FindMine( mine, show, ROW, COL);//排查雷
}
主函数:
#define _CRT_SECURE_NO_WARNINGS 1
//扫雷小游戏运行测试文件
#include"MineSweep.h"
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 0 :
printf("退出游戏!\n");
break;
case 1:
game();
break;
default:
printf("该选择无效!请重新选择\n");
break;
}
} while (input);
return 0;
}
四、源码:
#pragma once
//扫雷小游戏函数声明文件
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 9//棋盘行
#define COL 9//棋盘列
#define ROWS ROW+2
#define COLS COL+2
#define BASIC 10//基础版,定义10个雷
void menu();//菜单
void game();//游戏函数主题实现
void InitBoard(char board[ROWS][COLS], int row, int col,char set);//初始化函数
void PrintBoard(char board[ROWS][COLS], int row, int col);//显示棋盘
void SetMine(char board[ROWS][COLS], int row, int col);//设置雷
int GetMineCount(char mine[ROWS][COLS], int x, int y);//计算周围雷的个数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//排查雷
#define _CRT_SECURE_NO_WARNINGS 1
//扫雷小游戏主要函数实现文件
#include"MineSweep.h"
void menu()//菜单函数
{
printf("\n");
printf(" ***************************\n");
printf(" ****** 扫 雷 *******\n");
printf(" ****** 0. exit *******\n");
printf(" ****** 1. play *******\n");
printf(" ***************************\n");
printf("\n");
}
void InitBoard(char board[ROWS][COLS], int 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;
}
}
}
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 0; i <= col; 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 = BASIC;
int x = 0;
int y = 0;
srand((unsigned int)time(NULL));
while (count)
{
//随机放置10个雷
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
int GetMineCount(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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win =(ROW*COL- BASIC);
while (win)//当棋盘中雷还没有排完
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')//如果该坐标位置存放的是雷
{
system("cls");//清理屏幕
printf("很遗憾,挑战失败!\n");
PrintBoard(mine, ROW, COL);
break;
}
else//如果不是雷,就统计x,y坐标周围雷的个数
{
system("cls");//清理屏幕
PrintBoard(mine, ROW, COL);
int c = GetMineCount(mine, x, y);
show[x][y] = c + '0';//将雷的个数转化为字符,并在棋盘中显示
PrintBoard(show, ROW, COL);
win--;
}
}
else
{
printf("该坐标无效,重新输入:\n");
}
}
if (win == 0)
{
printf("恭喜你,排雷成功\n");
PrintBoard(mine, ROW, COL);
}
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine,ROWS,COLS,'0');//初始化雷
InitBoard(show, ROWS, COLS,'*');//初始化棋盘
PrintBoard(show, ROW, COL);//显示棋盘
SetMine(mine, ROW, COL);//安放雷
//PrintBoard(mine, ROW, COL);//显示雷的位置
FindMine( mine, show, ROW, COL);//排查雷
}
#define _CRT_SECURE_NO_WARNINGS 1
//扫雷小游戏运行测试文件
#include"MineSweep.h"
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 0 :
printf("退出游戏!\n");
break;
case 1:
game();
break;
default:
printf("该选择无效!请重新选择\n");
break;
}
} while (input);
return 0;
}
五、总结
首先在定义二为数组时,我们要进行扩大一圈,方埋雷和统计雷,所以Set mine函数和Get Count函数传参范围为9×9,由于二维数组数据类型为字符,所以在Get Count函数返回坐标周围雷的个数时应该转换为字符类型才能存入show数组里面。
到这里扫雷小游戏就结束啦!感谢各位的阅读!🌹