前言:经过前面的学习,我们可以写一些比较简单点的程序了,比如扫雷
首先我们要先设计扫雷游戏的结构:
1、游戏的界面
(1)用户界面
(2)用户选择
2、游戏逻辑的实现
(1)存储雷的信息
(2)布置雷
(3)显示游戏界面
(4)排查雷
3、游戏结束
总体来说就这三个步骤
一、游戏的界面:
也就是游戏菜单
如下图:
供用户选择的界面
代码如下:
void menu()//显示菜单
{
printf("**************************\n");
printf("***** 1. play *****\n");
printf("***** 0. exit *****\n");
printf("**************************\n");
}
然后就是用户选择:
void test()//
{
int input = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 0:
printf("退出游戏\n");
break;
case 1:
game();//如果用户选择的是1就开始游戏,调用game函数
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
这个函数的作用就是让用户选择是开始游戏还是退出游戏。
二、游戏的内容:
我们要想实现这个扫雷游戏,就要先了解他的结构
就拿网页版的扫雷游戏来说:
他是一个9*9的一个结构 ,但是扫雷游戏的规则是:
以输入坐标为中心,输入坐标显示的是周围黄色方框的雷的个数和,所以当我们输入最边上坐标时,他就会越界访问,所以我们要避免越界访问就需要扩大数组。
2.1 数组的创建
那么我们就需要一个11*11的数组,里面的9*9数组用于存储需要排查雷的信息,外面的那一层
是为了防止越界访问。当然外面的那层是不放任何数据的,只用初始化就行了。
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
这里我是先宏定义了ROW和COL为9,后面方便修改
下面是数组创建的代码:
char mine[ROWS][COLS] = { 0 };//创建扫雷信息的数组
char show[ROWS][COLS] = { 0 };//创建显示需要排查雷的数组
我们这里创建了两个数组,一个是用于存放雷的信息,一个是用于显示给用户看
2.2 数组的初始化
我们需要先初始化上面的两个数组,便于存放雷的信息
void Board(char arr[ROWS][COLS], int rows, int cols,char set)//初始化棋盘的函数
{
for (int i = 0;i < rows;i++)
{
for (int j = 0;j < cols;j++)
{
arr[i][j] = set;
}
}
}
我们这里只创建了一个初始化函数,当我们需要调用的时候把实参改一下就行了,不然容易代码冗余。
2.3 雷的布置
当然我们初始化好数组之后就该布置雷了
void Setmine(char mine[ROWS][COLS],int row,int col)//布置雷的函数
{
int l = lei;//在此之前我是先宏定义了#define lei 10的所以这里直接给l赋lei的值
while(l)
{
int x = rand() % row + 1;//使用随机数生成随机坐标
int y = rand() % col + 1;//同上一样的道理
if (mine[x][y] == '0')
{
mine[x][y] = '1';
l--;//布置好了一个雷之后就,需要布置雷的个数就减一
}
}
}
我们定义字符‘1’为雷,直到布置完10个雷为止
当然我们使用了rand()函数就需要srand
所以要在test函数里面加上srand函数例如:
void test()
{
int input = 0;
srand((unsigned int)time(NULL));//随机数种子
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 0:
printf("退出游戏\n");
break;
case 1:
game();
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
还需要引用头文件#include<stdlib.h>
2.4 显示棋盘
我们需要把需要排查雷的界面显示给用户看
void Display(char show[ROWS][COLS],int row,int col)//棋盘显示函数
{
printf(" ------扫雷游戏------\n");//为了看起来美观而加上的装饰
printf("|");
for (int i = 0;i <= row;i++)
{
printf("%d ", i);
}
printf("\b|");//装饰
printf("\n");
for (int i = 1;i <= row;i++)
{
printf("|");//装饰
printf("%d",i);
for (int j = 1;j <= col;j++)
{
printf("%2c",show[i][j]);//显示需要排查雷的信息
}
printf("|");//装饰
printf("\n");
}
printf(" --------------------\n");//装饰
显示结果如下:
当然装饰不唯一,也可以任意发挥。
2.5 排查雷
这也是游戏逻辑的最后一步了,排查雷
void Find(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)游戏逻辑实现的函数
{
int x = 0, y = 0;
while(1)//死循环
{
printf("请输入你要排查的坐标:");
scanf("%d %d", &x, &y);
if ((x == 0 || x > 9) || (y == 0 || y > 9))//如果输入的坐标不符合就会提示
{
printf("输入的坐标错误,请重新输入:");
}
else
{
if (show[x][y] == '*')//如果show[x][y]没有被排查就会执行以下程序
{
if (mine[x][y] == '1')//如果是雷,就炸死,退出游戏
{
printf("很遗憾,你被炸死了。\n");
Display(mine, ROW, COL);//调用显示棋盘信息的函数,显示给用户看那些地方有雷
break;//退出游戏
}
else//如果不是雷就会显示周围雷的个数
{
system("cls");//这里用了一个清屏函数,在玩游戏的时候能够更直观
int c = Getmine(mine, x, y);//这是一个统计周围雷的个数的函数
show[x][y] = c + '0';
Display(show, ROW, COL);
}
}
else//如果show[x][y]不等于‘*’,就说明这个坐标被排查过了
{
printf("该坐标被排查过了\n");
}
}
}
}
这里我们还需要一个统计雷的函数
int Getmine(char mine[ROWS][COLS], int x, int y)//获取该坐标周围雷的数量
{
int a = 0;
for (int i = x - 1;i <= x + 1;i++)//就是一个二维数组的遍历
{
for (int j = y - 1;j <= y + 1;j++)
{
if(mine[i][j] =='1')//如果mine[i][j]是‘1’的话,就+1
{
a++;
}
}
}
return a;//返回a的值
}
代码实现:
三、游戏结束
当然我们如果把所有的非雷的坐标排除了之后就会游戏结束
所以我们只需要在Find()函数中稍作修改就可以了
void Find(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)游戏逻辑实现的函数
{
int x = 0, y = 0;
int b = 0;//当我们没有排查的时候,排查量为0
while(b<row*col-lei)//当排查量=需要排查-雷的个数时就退出循环
{
printf("请输入你要排查的坐标:");
scanf("%d %d", &x, &y);
if ((x == 0 || x > 9) || (y == 0 || y > 9))
{
printf("输入的坐标错误,请重新输入:");
}
else
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了。\n");
Display(mine, ROW, COL);
break;
}
else
{
system("cls");
int c = Getmine(mine, x, y);
show[x][y] = c + '0';
Display(show, ROW, COL);
b++;//每排查一个坐标,排查量就加1
}
}
else
{
printf("该坐标被排查过了\n");
}
}
}
if (b == row*col- lei)//当排查量=需要排查-雷的个数时游戏结束,玩家胜利
{
printf("you win!!!\n");
}
}
整个游戏代码如下
这里我分成三个文件来实现的
这是头文件saolei.h的代码
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define lei 10
#define gezi ROW * COL
void menu();
void Board(char arr[ROWS][COLS], int rows, int cols,char set);
void Display(char arr[ROWS][COLS],int row,int col);
void Setmine(char arr[ROWS][COLS],int row,int col);
void Find(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col);
saolei.c
//游戏逻辑的实现
#include"saolei.h"
void Board(char arr[ROWS][COLS], int rows, int cols,char set)//初始化棋盘的函数
{
for (int i = 0;i < rows;i++)
{
for (int j = 0;j < cols;j++)
{
arr[i][j] = set;
}
}
}
void Display(char arr[ROWS][COLS],int row,int col)//棋盘显示函数
{
printf(" ------扫雷游戏------\n");
printf("|");
for (int i = 0;i <= row;i++)
{
printf("%d ", i);
}
printf("\b|");
printf("\n");
for (int i = 1;i <= row;i++)
{
printf("|");
printf("%d",i);
for (int j = 1;j <= col;j++)
{
printf("%2c",arr[i][j]);
}
printf("|");
printf("\n");
}
printf(" --------------------\n");
}
void Setmine(char mine[ROWS][COLS],int row,int col)//布置雷的函数
{
int l = lei;
while(l)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
l--;
}
}
}
int Getmine(char mine[ROWS][COLS], int x, int y)//因为这个函数被static修饰成静态函数了,所以这个函数只能在此文件中调用,获取该坐标周围雷的数量
{
int a = 0;
for (int i = x - 1;i <= x + 1;i++)
{
for (int j = y - 1;j <= y + 1;j++)
{
if(mine[i][j] =='1')
{
a++;
}
}
}
return a;
}
void Find(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//游戏逻辑实现的函数
{
int x = 0, y = 0;
int b = 0;
while(b<row*col-lei)
{
printf("请输入你要排查的坐标:");
scanf("%d %d", &x, &y);
if ((x == 0 || x > 9) || (y == 0 || y > 9))
{
printf("输入的坐标错误,请重新输入:");
}
else
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了。\n");
Display(mine, ROW, COL);
break;
}
else
{
system("cls");
int c = Getmine(mine, x, y);
show[x][y] = c + '0';
Display(show, ROW, COL);
b++;
}
}
else
{
printf("该坐标被排查过了\n");
}
}
}
if (b == row*col- lei)
{
printf("you win!!!\n");
}
}
game .c
//游戏的测试
#include "saolei.h"
void game()
{
char mine[ROWS][COLS] = { 0 };//创建扫雷信息的数组
char show[ROWS][COLS] = { 0 };//创建显示信息的数组
Board(mine, ROWS, COLS,'0');//初始化雷信息棋盘
Board(show, ROWS, COLS, '*');//初始化显示信息棋盘
//布置雷
Setmine(mine,ROW,COL);//布置雷
Display(show, ROW, COL);//显示棋盘
Find(mine,show,ROW,COL);//查找雷
}
void menu()//显示菜单
{
printf("**************************\n");
printf("***** 1. play *****\n");
printf("***** 0. exit *****\n");
printf("**************************\n");
}
void test()//
{
int input = 0;
srand((unsigned int)time(NULL));//随机数种子
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 0:
printf("退出游戏\n");
break;
case 1:
game();
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
总结:
总体来说这个扫雷小游戏分为几小步:
1、显示菜单界面
2、用户选择
3、创建数组方便存储信息
4、初始化数组
5、布置雷
6、显示需要排查雷的数组
7、开始游戏,输入需要排查的坐标(需要判断输入的坐标是否有效,是否重复)
8、判断该坐标是否是雷,如果不是,统计该坐标周围雷的个数,再显示。如果是,就结束游戏。
9、如果把所有非雷的坐标都排查完了,游戏结束,玩家胜利