今天带来了《扫雷》游戏的代码及其编程思路,废话不多说,开始讲解:
一、先构思
一个游戏打开以后先映入眼帘的是游戏的开始菜单,那么先这就展示我们的游戏菜:
这里给定两个选项“选择1开始游戏,选择0退出游戏”。
void Menu()//开始菜单
{
printf("************************\n");
printf("*****输入1开始游戏******\n");
printf("*****输入0退出游戏******\n");
printf("************************\n");
}
那么第二步就是选了之后应该干什么,如果选了1,那么开始,选了0,那就退出,那么如果输入了其他的数字呢?我们也可以提示玩家重新输入:
int qq = 1;
int input = 0;
printf("请输入,按回车键结束->");
scanf("%d", &input);
switch (input)
{
case 1:
{
}break;
case 0:
{
printf("您即将推出游戏\n");
}break;
default:
{
printf("输入了不合法的参数,请重新输入。\n");
}break;
}
这个代码有个问题,那就是完了一次之后程序就会退出,不够过瘾,那么我们就可以把它放到循环里:
int qq = 1;
int input = 0;
do
{
printf("请输入,按回车键结束->");
scanf("%d", &input);
switch (input)
{
case 1:
{
goto Begin;
}break;
case 0:
{
printf("您即将推出游戏\n");
qq = 0;
}break;
default:
{
printf("输入了不合法的参数,请重新输入。\n");
}break;
}
} while (qq);
主体大致就是这样。我们先从简单的开始:
二、代码实现
为了方便后期修改代码,我将各个部分进行模块化
首先是开始菜单
void Menu()//开始菜单
{
printf("************************\n");
printf("*****输入1开始游戏******\n");
printf("*****输入0退出游戏******\n");
printf("************************\n");
}
然后是开始游戏的主体
游戏开始后,首先看到的是扫雷游戏的棋盘,那么这个棋盘应该怎么实现呢?
我们已经学习过二维数组,这里可以通过打印数组的方式展现棋盘,那么我们先写一个打印数组的函数:
void Print_Checkerboard(char arr[Row1][Col1],int row,int col)//打印棋盘,在输入row和col时注意数组元素是否溢出(输入的数加上1需要小于等于数组元素个数(行,列))
{
for (int i = 0; i <= col; i++)
{
printf("%2d", i);
}
printf("\n");
for (int x = 1; x <= row; x++)
{
printf("%2d ", x);
for (int y = 1; y <= col; y++)
{
printf("%c ", arr[x][y]);
}
printf("\n");
}
}
然后我们在定义两个字符型的二维数组,为什么是两个呢?一个是需要打印给玩家看的,一个是统计雷子的数量的,在后期我们可以知道原因:
char mine[Row1][Col1] = { '0' };
char show[Row1][Col1] = { '0' };
然后再头文件里声明行和列用来设置数组的行和列
#define Row 9
#define Col 9
#define Row1 Row+2
#define Col1 Col+2
现在有了行和列,但是我们的数组空空的,好像少了点什么,在这里,我们把数组设置为11x11的大小,具体原因看后面统计雷子数量那里,然后一个数组放满字符“0”,以便用来统计雷子数量,一个数组放满字符“*”,用来显示未知的位置:
void Checkerboard_initialization(char arr[Row1][Col1], char s, int row, int col)//棋盘初始化
{
for(int i = 0;i< row;i++)
{
for (int a = 0; a < col; a++)
{
arr[i][a] = s;
}
}
Checkerboard_initialization(mine, '0', Row1, Col1);
Checkerboard_initialization(show, '*', Row1, Col1);
然后就是将雷子放入全都是“0”的数组里:
void Checkerboard_landmine(char arr[Row1][Col1],int row,int col,int count)//放置雷,最后一个是雷的数量
{
int i = count;
while (i)
{
//注意把产生随机数的语句放入循环,不然随机数不变,会成为死循环
int rands = rand() % row + 1;
int rands1 = rand() % col + 1;
if(arr[rands][rands1]!='1')
{
arr[rands][rands1] = '1';
i--;
}
}
}
首先这里有一个知识点,就是生成随机数用来当做坐标,将雷子放入里面,需要用到“rand”函数,但是为了防止每次生成的随机数都是一样的,所以还需要用到“srand”函数用来设置“种子”,为了保证每次的“种子”不一样,还需用到“time”函数来返回时间戳,需要用到“stdlib.h”和“time.h”的头文件,具体用法请查询资料,这里不作过多解释。
void Rand( ) // 生成随机数种子
{
srand((unsigned int)time(NULL));
}
然后就是统计坐标周围的八个点的雷子数,放到的数组show里:
int count = (arrmine[x - 1][y + 1]
+ arrmine[x - 1][y] + arrmine[x - 1][y - 1]
+ arrmine[x][y + 1] + arrmine[x][y - 1]
+ arrmine[x + 1][y + 1] + arrmine[x + 1][y]
+ arrmine[x + 1][y - 1] - 8 * '0');
arrshow[x][y] = count + '0';//加'0'是为了将整型转化成字符型,因为数组是字符型
这里的arrshow[][]是一个形参,因为是我的自定义函数,它也是show这个数组
前方设置成11*11的数组就是为了便于统计9*9最边缘的雷子数
再次打印棋盘
Print_Checkerboard(arrshow, Row, Col);
如果游戏碰到雷子,游戏就会结束,如果没碰到雷,游戏继续:
arrshow[x][y] = count + '0';//加'0'是为了将整型转化成字符型,因为数组是字符型
if (arrmine[x][y] != '1')
{
Print_Checkerboard(arrshow, Row, Col);
printf("\n");
}
else if (arrmine[x][y] == '1')
{
printf("你被炸死了,菜就多练\n");
Print_Checkerboard(arrmine, Row, Col);
printf("\n");
break;
}
如果排雷排完了,那么游戏通关
if (coun == (Row * Col - landmine))
{
printf("恭喜你,游戏通关");
}
这里if括号里的判断条件是棋盘坐标的总个数减去雷子数,用来判断雷子是否排完。
由于初学C语言,代码略显凌乱,写博客不太方便
三、以下是全部代码:
1,源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "Game.h"
void Game_Begin(char arrmine[Row1][Col1], char arrshow[Row1][Col1] ,int landmine)//a代表雷子的数量
{
int x, y;
int coun = 0;
Print_Checkerboard(arrshow, Row, Col);
while (coun < (Row*Col - landmine))
{
coun++;
printf("请输入游戏坐标(行,列),中间用空格隔开,按回车键即可输入->");
(void)scanf("%d %d", &x, &y);
if (x > Row || y > Col || x <= 0 || y <= 0)
{
printf("输入不正确,请重新输入\n");
}
if(x<=Row && y<=Col && x>0 && y>0)
{
int count = (arrmine[x - 1][y + 1]
+ arrmine[x - 1][y] + arrmine[x - 1][y - 1]
+ arrmine[x][y + 1] + arrmine[x][y - 1]
+ arrmine[x + 1][y + 1] + arrmine[x + 1][y]
+ arrmine[x + 1][y - 1] - 8 * '0');
arrshow[x][y] = count + '0';//加'0'是为了将整型转化成字符型,因为数组是字符型
if (arrmine[x][y] != '1')
{
Print_Checkerboard(arrshow, Row, Col);
printf("\n");
}
else if (arrmine[x][y] == '1')
{
printf("你被炸死了,菜就多练\n");
Print_Checkerboard(arrmine, Row, Col);
printf("\n");
break;
}
}
}
if (coun == (Row * Col - landmine))
{
printf("恭喜你,游戏通关");
}
}
int main()
{
int landmine=10;//设置雷子数
int qq = 1;
//展开游戏菜单
Begin:
Menu();
int input = 0;
do
{
printf("请输入,按回车键结束->");
(void)scanf("%d", &input);
switch (input)
{
case 1:
{
//创建两个数组,作为棋盘
char mine[Row1][Col1] = { '0' };
char show[Row1][Col1] = { '0' };
//棋盘初始化
Checkerboard_initialization(mine, '0', Row1, Col1);
Checkerboard_initialization(show, '*', Row1, Col1);
Rand();//生成随机数种子
Checkerboard_landmine(mine, Row, Col, landmine);//放置雷(最后一个数是雷的数量)
Game_Begin(mine, show, landmine);//游戏开始,最后一个是雷子数量
goto Begin;
}break;
case 0:
{
printf("您即将推出游戏\n");
qq = 0;
}break;
default:
{
printf("输入了不合法的参数,请重新输入。\n");
}break;
}
} while (qq);
return 0;
}
2,头文件和他的源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "Game.h"
void Menu()//开始菜单
{
printf("************************\n");
printf("*****输入1开始游戏******\n");
printf("*****输入0退出游戏******\n");
printf("************************\n");
}
void Checkerboard_initialization(char arr[Row1][Col1], char s, int row, int col)//棋盘初始化
{
for(int i = 0;i< row;i++)
{
for (int a = 0; a < col; a++)
{
arr[i][a] = s;
}
}
}
void Print_Checkerboard(char arr[Row1][Col1],int row,int col)//打印棋盘,在输入row和col时注意数组元素是否溢出(输入的数加上1需要小于等于数组元素个数(行,列))
{
for (int i = 0; i <= col; i++)
{
printf("%2d", i);
}
printf("\n");
for (int x = 1; x <= row; x++)
{
printf("%2d ", x);
for (int y = 1; y <= col; y++)
{
printf("%c ", arr[x][y]);
}
printf("\n");
}
}
void Rand( ) // 生成随机数种子
{
srand((unsigned int)time(NULL));
}
void Checkerboard_landmine(char arr[Row1][Col1],int row,int col,int count)//放置雷,最后一个是雷的数量
{
int i = count;
while (i)
{
//注意把产生随机数的语句放入循环,不然随机数不变,会成为死循环
int rands = rand() % row + 1;
int rands1 = rand() % col + 1;
if(arr[rands][rands1]!='1')
{
arr[rands][rands1] = '1';
i--;
}
}
}
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define Row 9
#define Col 9
#define Row1 Row+2
#define Col1 Col+2
void Rand();//生成随机数种子
void Menu();//菜单初始化
void Checkerboard_initialization();//棋盘初始化
void Print_Checkerboard(); //打印棋盘
void Checkerboard_landmine(char arr[Row1][Col1],int row,int col,int count);//放置雷