引言
扫雷是Windows系统自带的经典游戏,陪伴了许多人的童年。今天,我将带大家用C语言从零开始实现一个简易版的扫雷游戏。通过这个项目,你不仅能巩固C语言基础知识,还能学习游戏开发的基本逻辑。
一、游戏设计思路
扫雷游戏的核心机制包括:
-
生成随机地雷分布
-
计算每个格子周围的地雷数量
-
处理玩家输入
-
判断游戏胜负条件
二、完整代码实现
完整的代码分为三个文件
1.test.c
用来存放主函数
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("* * * * * * * * * * *\n");
printf("* * * 1 p l a y * * *\n");
printf("* * * 0 e x i t * * *\n");
printf("* * * * * * * * * * *\n");
}
void game()
{
char mine[rows][cols];//存放布置的雷
char show[rows][cols];//存放已排查的雷
//初始化数组元素
init(mine, rows, cols,'0');
init(show, rows, cols,'*');
//布置地雷
setmine(mine, row, col);
//打印棋盘
//print(mine, rows, cols);
print(show, rows, cols);
//排查雷的位置
findmine(mine,show, rows, cols);
}
int main()
{
int n;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择是否进行游戏\n");
scanf("%d", &n);
switch (n)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新选择\n");
break;
}
} while (n);
return 0;
}
2.game.c
这是扫雷游戏的核心文件,包含数组初始化,布置地雷,处理玩家输入数据以及统计玩家输入坐标周围8个点的雷的个数
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void init(char board[rows][cols], int r, int c,char set)
{
int i,j;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
board[i][j] = set;
}
}
}
void print(char board[rows][cols], int r, int c)
{
int i, j;
printf("————扫 雷 游 戏————\n");
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");
}
printf("\n");
}
//int xz()
//{
// printf("请选择难度\n");
// printf("1->简单模式\n");
// printf("2->中等模式\n");
// printf("3->极难模式\n");
// int n;
// int count;
// scanf("%d", &n);
// switch (n)
// {
// case 1:
// count = easycount;
// break;
// case 2:
// count = midcount;
// break;
// case 3:
// count = highcount;
// break;
// default:
// printf("没有此难度\n");
// break;
// }
// return count;
//}
void setmine(char board[rows][cols], int r, int c)
{
int minecount=easycount;
//minecount = xz();
while (minecount)
{
int x = rand() % r + 1;
int y = rand() % c + 1; //这里是放到循环里面 不断生成随机数的
if (board[x][y] == '0')
{
board[x][y] = '1';
minecount--;
}
}
}
void findmine(char board[rows][cols],char show[rows][cols], int r, int c)
{
int x;
int y;
int count;
int win = 0;
while (win<row*col-easycount)
{
printf("请输入要排查的坐标\n");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x][y] == '1')
{
printf("很遗憾你被炸死了\n");
print(board, row, col);
break;
}
if (board[x][y] == '0')
{
count = board[x + 1][y] + board[x - 1][y] + board[x][y + 1] + board[x][y - 1] +
board[x + 1][y - 1] + board[x - 1][y - 1] + board[x + 1][y + 1] + board[x - 1][y + 1] - 8 * '0';
show[x][y] = count + '0';
print(show, row, col);
win++;
}
}
else
{
printf("输入的坐标错误\n");
}
}
if (win == row * col - easycount)
{
printf("你赢了\n");
print(board, row, col);
}
}
3 game.h
这是game.c的头文件,里面包含了对数组行列的定义,及诸多常见的头文件
#pragma once
#define row 9
#define col 9
#define rows row+2
#define cols col+2
#define easycount 10
#define midcount 10
#define highcount 10
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void init(char board[rows][cols], int r, int c,char set);
void print(char board[rows][cols], int r, int c);
void setmine(char board[rows][cols], int r, int c);
void findmine(char board[rows][cols], char show[rows][cols], int r,int c);
三、关键功能解析
1 数组初始化
目的是将存放地雷的数组全部初始化为符号‘0’,方便之后将地雷设置为符号‘1’,另外将展示给玩家的数组初始化为‘*’,让玩家推测地雷位置并标记周围雷个数
char mine[rows][cols];//存放布置的雷
char show[rows][cols];//存放已排查的雷
init(mine, rows, cols,'0');
init(show, rows, cols,'*');
void init(char board[rows][cols], int r, int c,char set)
{
int i,j;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
board[i][j] = set;
}
}
}
2 布置地雷
运用rand函数和srand函数产生10个不同的x,y都在1~9的随机坐标来放置地雷,确保了游戏的随机性和可玩性,使用if判断语句有效避免了生成同一坐标的问题
setmine(mine, row, col);
void setmine(char board[rows][cols], int r, int c)
{
int minecount=easycount;
//minecount = xz();
while (minecount)
{
int x = rand() % r + 1;
int y = rand() % c + 1; //这里是放到循环里面 不断生成随机数的
if (board[x][y] == '0')
{
board[x][y] = '1';
minecount--;
}
}
}
3 打印棋盘
这是相对简单的部分,相当于打印一个简单的二维数组,可以将存放雷的数组和存放已排查雷的信息的数组都打印出来调试和改错,最后需注释调打印存放雷信息的数组,避免玩家提前知道雷存放位置
//打印棋盘
//print(mine, rows, cols);
print(show, rows, cols);
void print(char board[rows][cols], int r, int c)
{
int i, j;
printf("————扫 雷 游 戏————\n");
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");
}
printf("\n");
}
4 排查地雷
这部分是整个程序中最核心的一部分,随着玩家输入每一个坐标,程序要做到有雷结束游戏,没雷统计周围雷的个数
//排查雷的位置
findmine(mine,show, rows, cols);
void findmine(char board[rows][cols],char show[rows][cols], int r, int c)
{
int x;
int y;
int count;
int win = 0;
while (win<row*col-easycount)
{
printf("请输入要排查的坐标\n");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x][y] == '1')
{
printf("很遗憾你被炸死了\n");
print(board, row, col);
break;
}
if (board[x][y] == '0')
{
count = board[x + 1][y] + board[x - 1][y] + board[x][y + 1] + board[x][y - 1] +
board[x + 1][y - 1] + board[x - 1][y - 1] + board[x + 1][y + 1] + board[x - 1][y + 1] - 8 * '0';
show[x][y] = count + '0';
print(show, row, col);
win++;
}
}
else
{
printf("输入的坐标错误\n");
}
}
if (win == row * col - easycount)
{
printf("你赢了\n");
print(board, row, col);
}
}
五、扩展改进建议
-
增加难度选择:可以添加不同大小的棋盘和地雷数量
-
添加计时功能:记录玩家完成游戏所用时间
-
图形界面:使用EasyX等图形库实现图形化界面
-
保存游戏进度:实现游戏的保存和读取功能
-
标记地雷:确保不会因为失误导致游戏失败
结语
通过扫雷程序的设计,我深入了解了数组和函数的使用,等之后学了更多知识再来改进这一程序,希望大家在评论区多多指教