C语言编写小游戏:MinesWeeper(扫雷)闯关版
程序员文章站
2022-04-07 15:38:18
...
《扫雷》:大众类的益智小游戏,游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
话不多说,我们直接进入正题。
首先,我们得给用户显示一个菜单栏,供用户选择,所以我们先来编写菜单函数:
void menu()
{
printf("********************\n");
printf("********扫雷********\n");
printf("** 1.paly 0.exit **\n");
printf("********************\n");
printf("Please select:");
}
菜单有了之后,就要写主函数了:
int main()
{
int select = 0;//初始化变量select,用来接收玩家输入内容
do{
menu();//首先显示除我们刚才所写的菜单
scanf("%d",&select);//接收玩家输入的内容
switch(select)
{
case 1://玩家输入1,直接进入游戏
game();
break;
case 0://如果玩家输入0,直接退出游戏
exit(0);
default://玩家输入了其他字符,提示玩家输入错误
printf("Error!please try again!\n");
break;
}
}while(1);
system("pause");
return 0;
}
写完主函数之后,我们就要写游戏的主逻辑game函数了,直接上代码,把思路会写进注释当中:
在写游戏主逻辑函数之前,我们先宏定义几个参数,以便后续适用方便。这里我们设计的游戏为10*10的格子,然后第一关雷的数量设置成20:
#define ROW 10//定义ROW的大小为10
#define COL 10//定义COL的大小为10
#define MINE_NUM 20//定义雷的MINE_NUM的大小为20
void game()
{
int i = 1;//先初始化一个变量,控制关卡
int x,y;//定义两个变量,用来接收玩家输入的坐标
int a = 0;//初始化变量a,用来统计玩家所排除格子数量
do
{//我们首先需要定义两个二维数组,一个用来系统布雷,另一个显示给玩家
char mine[ROW+2][COL+2];//定义系统布雷的数组
char show[ROW+2][COL+2];//定义给用户显示的数组
memset(mine,'0',(ROW+2)*(COL+2));//将系统布雷数组的全部内容设置为字符‘0’
memset(show,'*',(ROW+2)*(COL+2));//将显示数组的全部内容设置为字符‘*’
printf("第%d关\n",i);//显示当前关卡
lay_mines(mine,ROW+2,COL+2,i);//布雷
do{
print_board(show,ROW+2,COL+2);//向用户显示坐标界面
printf("Please input your coordinate:<x,y>");//提示玩家输入坐标
scanf("%d%d",&x,&y);//接收玩家输入的坐标
if(x>=1&&x<=10&&y>=1&&y<=10)//判断玩家输入坐标是否合法
{
if(mine[x][y] == '1')//判断玩家所选坐标位置是否是雷。这里字符‘1’代表雷
{
printf("It's too bad!Game over!\n");//提示玩家游戏结束
print_board(mine,ROW+2,COL+2);//显示出雷的位置
goto END;//跳到END位置
}
else//表示玩家所选位置不是雷,我们就要计算该位置周围雷的数量
{
int count = get_mine_num(mine,ROW+2,COL+2,x,y);//用get_mine_num()函数传入该位置周围雷的个数
show[x][y] = count + '0';//将该位置雷的个数(这里加上字符‘0’,目的是将数字转化为对应字符)给到显示数组的对应位置
a++;//排除数量自增
if(ROW*COL-i*MINE_NUM == a)//如果排除数目与系统布雷数组中非雷个数相等,表示玩家获胜
{
printf("Congratulations!You win!\n");
i++;//关卡数自增,以便后续进入下一关
break;
}
}
}
}while(1);
}while(i<=4);//游戏设置的最高关数4.
END:
printf("Do you want to play again?\n");
}
游戏主逻辑写完之后,我们就来写主逻辑函数当中所使用到的函数,按照从上到下的顺序,先来写系统布雷的函数:
void lay_mines(char mine[][COL+2],int row,int col,int a)
{
int x;//定义变量x,用来记录系统布雷位置的横坐标
int y;//定义变量y,用来记录系统布雷位置的纵坐标
int count = 0;//定义变量count,用来控制布雷数量
srand((unsigned long)time(NULL));//生成随机数的函数
do{
x = (rand() % (ROW))+1;//生成的随机数取余10再加一,用来控制x的取值范围必须在1~10
y = (rand() % (COL))+1;//同上
if(mine[x][y] == '0')//如果随机数对应的坐标位置是字符‘0’,说明此处没有雷
{
mine[x][y] = '1';//将该位置写入字符‘1’
count++;//已布雷个数自增
}
}while(count < (a*MINE_NUM));//如果已布雷个数小于关卡数*MINE,继续循环布雷,直到布满a*MINE_NUM个雷为止
}
显示坐标的函数:显示坐标的函数根据个人喜好,这里先展示一下这个函数显示的坐标:
void print_board(char board[][COL+2],int row,int col)
{
int i = 1;
int j = 0;
printf(" ");//先输出3个空格
for(;i<=COL;i++)
printf("%3d",i);//输出列坐标,每3个位置输出对应数字
printf("\n");//换行
printf(" ");//输出3个空格
for(i=0;i<ROW;i++)
printf("---");//输出列坐标下面的横线
printf("\n");//换行
for(i = 1;i<=ROW;i++)
{
printf("%2d|",i);//输出列坐标
for(j = 1;j<=COL;j++)
{
printf("%2c|",board[i][j]);//输出对应坐标内容
}
printf("\n");换行
}
}
下来就是统计对应位置周围雷的个数的函数:这个函数很容易,无非就是将系统布雷数组的对应位置周围8个位置的内容相加,然后将结果返回。
int get_mine_num(char mine[][COL+2],int row,int col,int x,int y)
{
int num = 0;
num = (mine[x-1][y-1] - '0') + (mine[x-1][y] - '0') + (mine[x-1][y+1] - '0') + (mine[x][y-1] - '0') + (mine[x][y+1] - '0') + (mine[x+1][y-1] - '0') + (mine[x+1][y] - '0') + (mine[x+1][y+1] - '0');
return num;
}
至此,所有工作全部搞定!
下面奉上小编的全部代码:
头文件部分:
#ifndef _GAME_H_
#define _GAME_H_
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
#pragma warning(disable:4996)
#define ROW 10
#define COL 10
#define MINE_NUM 20
void game();
#endif
源文件main.c:
#include "game.h"
void menu()
{
printf("********************\n");
printf("********扫雷********\n");
printf("** 1.paly 0.exit **\n");
printf("********************\n");
printf("Please select:");
}
int main()
{
int select = 0;
do{
menu();
scanf("%d",&select);
switch(select)
{
case 1:
game();
break;
case 0:
exit(0);
default:
printf("Error!please try again!\n");
break;
}
}while(1);
system("pause");
return 0;
}
源文件game.c:
#include "game.h"
void print_board(char board[][COL+2],int row,int col)
{
int i = 1;
int j = 0;
printf(" ");
for(;i<=COL;i++)
printf("%3d",i);
printf("\n");
printf(" ");
for(i=0;i<ROW;i++)
printf("---");
printf("\n");
for(i = 1;i<=ROW;i++)
{
printf("%2d|",i);
for(j = 1;j<=COL;j++)
{
printf("%2c|",board[i][j]);
}
printf("\n");
}
}
void lay_mines(char mine[][COL+2],int row,int col,int a)
{
int x;
int y;
int count = 0;
srand((unsigned long)time(NULL));
do{
x = (rand() % (ROW))+1;
y = (rand() % (COL))+1;
if(mine[x][y] == '0')
{
mine[x][y] = '1';
count++;
}
}while(count < (a*MINE_NUM));
}
int get_mine_num(char mine[][COL+2],int row,int col,int x,int y)
{
int num = 0;
num = (mine[x-1][y-1] - '0') + (mine[x-1][y] - '0') + (mine[x-1][y+1] - '0') + (mine[x][y-1] - '0') + (mine[x][y+1] - '0') + (mine[x+1][y-1] - '0') + (mine[x+1][y] - '0') + (mine[x+1][y+1] - '0');
return num;
}
void game()
{
int i = 1;
int x,y;
int win = 0;
do
{
char mine[ROW+2][COL+2];
char show[ROW+2][COL+2];
memset(mine,'0',(ROW+2)*(COL+2));
memset(show,'*',(ROW+2)*(COL+2));
printf("第%d关\n",i);
lay_mines(mine,ROW+2,COL+2,i);
do{
system("cls");
print_board(show,ROW+2,COL+2);
printf("Please input your coordinate:<x,y>");
scanf("%d%d",&x,&y);
if(x>=1&&x<=10&&y>=1&&y<=10)
{
if(mine[x][y] == '1')
{
printf("It's too bad!Game over!\n");
print_board(mine,ROW+2,COL+2);
goto END;
}
else
{
int count = get_mine_num(mine,ROW+2,COL+2,x,y);
show[x][y] = count + '0';
win++;
if(ROW*COL-i*MINE_NUM == win)
{
printf("Congratulations!You win!\n");
i++;
break;
}
}
}
}while(1);
}while(i<=4);
END:
printf("Do you want to play again?\n");
}
后面再来一张程序运行的结果:
上一篇: python中if的用法
下一篇: 关于array_diff的详细介绍