利用C语言学习到的知识,就可以写一些简单的小游戏,比如:扫雷游戏。
在开始敲代码之前,需要做如下准备:
一、 回顾一下怎么玩扫雷:
点击格子中的任意一个位置,如果点到雷,那么就炸死,游戏结束,如果这个位置没有雷,就会显示周围8个位置的雷的总数,同时会展开该位置周围没雷的地方,就这样直到游戏结束;
二、思考用C语言实现游戏:
要求如下:
- 扫雷中第一步不能被炸死;
- 排雷过程中要可以展开周围不是雷的地方;
- 游戏可以选择两个难度,初级与高级;
⑴、给出两个数组,一个是用来布雷的(mine数组),另外一个用来显示给玩家,当然就不能把雷的位置给出来啦(show数组);
⑵、打印游戏的菜单,分装一个menu()函数;
⑶、选择游戏的难度,分装一个level_menu()函数;
⑷、初始化布雷数组,对于初级难度,在mine1数组中布置雷,布置雷的时候注意不能超过给的数组大小,同理操作高级难度;
⑸、初始化给玩家展示的数组,两个难度初始化都为’*‘;
⑹、打印,在刚开始写的时候,为了更好的操控,将布雷数组也打印;
⑺、开始扫雷;
⑻、判断玩家是否赢了游戏。
三、具体化想法设计(以下内容举例初级难度,高级难度同理):
注意:以下内容均关于游戏的一些实现,全部置于game.c这个源文件中。
1.初始化两个数组中,可以很巧妙的利用memset()函数, 代码如下:
void InitBoard1(char board[ROWS1][COLS1], int rows, int cols, char set)
{
memset(board, set, rows*cols*sizeof(board[0][0]));
}
注意:
关于memset()函数,函数原型是:extern void memset(void buffer, int c, int count),buffer为指针或者数组,c为赋给buffer的值,count为buffer的长度。
2、打印出扫雷的格子,代码如下:
void DisplayBoard1(char board[ROWS1][COLS1], int row, int col)
{
int i = 0;
int j = 0;
for(i=0; i<=row; i++)
{
printf("%2d ",i);//第一行的序号,方便扫雷输入坐标
}
printf("\n");
for(i=1; i<=row; i++)
{
printf("%d ",i);//第一列的序号
for(j=1; j<=col; j++)
{
printf("%3c", board[i][j]);
}
printf("\n");
}
}
3、随机布置雷的位置,代码如下:
void SetMine1(char mine1[ROWS1][COLS1], int row, int col, int count)//初级mine数组中布置雷
{
int x = 0;
int y = 0;
while(count)
{
x = rand()%row+1;
y = rand()%col+1;
if(mine1[x][y] == '0')
{
mine1[x][y] = '1';
count--;
}
}
}
注意:
布置雷的时候,千万注意坐标的取值问题,利用rand()函数生成随机数为坐标值,在利用rand()函数时,需要同时调用srand()函数,并加入相应头文件。
4、未踩到雷时,显示周围8个坐标的雷的总数,代码如下:
static int GetMineCount1(char mine[ROWS1][COLS1], int x, int y)
{
return 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]+mine[x-1][y]-8*'0';//注意返回类型为整型
}
5、没有踩到雷时,展开周围无雷的地方,代码如下:
static void OpenMine1(char mine1[ROWS1][COLS1],char show1[ROWS1][COLS1],int row ,int col, int x,int y)
{
int ret = 0;
ret = GetMineCount1(mine1, x, y);
if(ret == 0)
{
show1[x][y]=' ';
if(x-1>0 && y>0 && show1[x-1][y]=='*')
OpenMine1(mine1, show1, row, col, x-1, y);
if(x-1>0 && y+1<=col && show1[x-1][y+1]=='*')
OpenMine1(mine1, show1, row, col, x-1, y+1);
if(x>0 && y+1<=col && show1[x][y+1]=='*')
OpenMine1(mine1, show1, row, col, x, y+1);
if(x+1<=row && y+1<=col && show1[x+1][y+1]=='*')
OpenMine1(mine1, show1, row, col, x+1, y+1);
if(x+1<=row && y>0 && show1[x+1][y]=='*')
OpenMine1(mine1, show1, row, col, x+1, y);
if(x+1<=row && y-1>0 && show1[x+1][y-1]=='*')
OpenMine1(mine1, show1, row, col, x+1, y-1);
if(x>0 && y-1>0 && show1[x][y-1]=='*')
OpenMine1(mine1, show1, row, col, x, y-1);
if(x-1>0 && y-1>0 && show1[x-1][y-1]=='*')
OpenMine1(mine1, show1, row, col, x-1, y-1);
}
else
{
show1[x][y] = GetMineCount1(mine1, x, y)+'0';//若坐标周围有雷,显示雷数
}
}
6、为增加游戏趣味性,确保第一步不被炸死,代码如下:
void FirstSafe1(char mine1[ROWS1][COLS1], char show1[ROWS1][COLS1], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
int tmp = 0;
int a = 0;
int b = 0;
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
a = x;
b = y;
if(mine1[x][y] == '1')
{
mine1[x][y] = '0';
count = GetMineCount1(mine1, x, y);
show1[x][y] = count+'0';
while(tmp)
{
x = rand()%row+1;
y = rand()%col+1;
if(mine1[x][y] == '0')
{
mine1[x][y] = '1';
}
tmp--;
}
}
OpenMine1(mine1, show1, row, col, a, b);
DisplayBoard1(show1, ROW1, COL1);
}
7、判断玩家是否赢了该局游戏,代码如下:
int IsWin1(char show1[ROWS1][COLS1], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for(i=0; i<=row; i++)
{
for(j=0; j<=col; j++)
{
if(show1[i][j] == '*')
{
count++;
}
}
}
return count;
}
8、扫雷过程,代码如下:
void FindMine1(char mine1[ROWS1][COLS1], char show1[ROWS1][COLS1], int row, int col,int count)//扫雷初级
{
int x = 0;
int y = 0;
int win = 0;
while(wincount)
{
FirstSafe1(mine1, show1, row, col);//第一步安全
if(x>=1 && x<=row && y>=1 && y<=col)
{
if(mine1[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
DisplayBoard1(mine1, ROW1, COL1);
break;
}
else
{
int count = GetMineCount1(mine1, x, y);
show1[x][y] = count + '0';
OpenMine1(mine1,show1,row ,col, x,y);
DisplayBoard1(show1, ROW1, COL1);
win++;
}
}
}
if(IsWin1(show1, row, col) == LOW_COUNT)
{
printf("恭喜你,扫雷成功!\n");
DisplayBoard1(show1, ROW1, COL1);
}
}
四、游戏两个难度整体代码如下:
1、game.h头文件中:
#ifndef __GAME_H__
#define __GAME_H__
#include
#include
#include
#include
#define LOW_COUNT 10//初级版雷的个数
#define HIGH_COUNT 40//高级版雷的个数
#define ROW1 9//初级数组
#define COL1 9
#define ROWS1 ROW1+2
#define COLS1 COL1+2
#define ROW2 16//高级数组
#define COL2 16
#define ROWS2 ROW2+2
#define COLS2 COL2+2
void InitBoard1(char board[ROWS1][COLS1], int rows, int cols, char set);
void InitBoard2(char board[ROWS2][COLS2], int rows, int cols, char set);
void DisplayBoard1(char board[ROWS1][COLS1], int row, int col);
void DisplayBoard2(char board[ROWS2][COLS2], int row, int col);
void SetMine1(char mine1[ROWS1][COLS1], int row, int col, int count);
void SetMine2(char mine2[ROWS2][COLS2], int row, int col, int count);
void FindMine1(char mine1[ROWS1][COLS1], char show1[ROWS1][COLS1], int row, int col,int count);//初级扫雷
void FindMine2(char mine2[ROWS2][COLS2], char show1[ROWS2][COLS2], int row, int col,int count);//初级扫雷
int IsWin1(char show1[ROWS1][COLS1], int row, int col);
int IsWin2(char show2[ROWS2][COLS2], int row, int col);
void FirstSafe1(char mine1[ROWS1][COLS1], char show1[ROWS1][COLS1], int row, int col);
void FirstSafe2(char mine2[ROWS2][COLS2], char show2[ROWS2][COLS2], int row, int col);
#endif //__GAME_H__
2、test.c源文件,用于测试游戏大的,整体代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("**************************** ^@^ ***\n");
printf("********** 1. play **********\n");
printf("********** 0. exit **********\n");
printf("************************************\n");
}
void level_menu()
{
printf("## 1. 初级 ##\n");
printf("## 2. 高级 ##\n");
}
void game()
{
int level = 0;
int row = 0;
int col = 0;
int x = 0;
int y = 0;
char mine1[ROWS1][COLS1]={0};
char show1[ROWS1][COLS1]={0};
char mine2[ROWS2][COLS2]={0};
char show2[ROWS2][COLS2]={0};
do
{
level_menu();
printf("请选择游戏难度:\n");
scanf("%d",&level);
switch(level)
{
case 1:
InitBoard1(mine1,ROWS1,COLS1,'0');
InitBoard1(show1,ROWS1,COLS1,'*');
SetMine1(mine1, ROW1, COL1, LOW_COUNT);//布置雷
//DisplayBoard1(mine1, ROW1, COL1);
// printf("\n");
DisplayBoard1(show1, ROW1, COL1);
FindMine1(mine1, show1, ROW1, COL1, LOW_COUNT);//扫雷
IsWin1(show1, row, col);
break;
case 2:
InitBoard2(mine2,ROWS2,COLS2,'0');
InitBoard2(show2,ROWS2,COLS2,'*');
SetMine2(mine2, ROW2, COL2,HIGH_COUNT);//布置雷
//DisplayBoard2(mine2, ROW2, COL2);
//printf("\n");
DisplayBoard2(show2, ROW2, COL2);
FindMine2(mine2, show2, ROW2, COL2, HIGH_COUNT);//扫雷
IsWin2(show2, row, col);
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
}while((level==1)||(level==2));
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d",&input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
}while(input);
}
int main()
{
test();
return 0;
}
3、game.c源文件,存放游戏相关的函数,代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard1(char board[ROWS1][COLS1], int rows, int cols, char set)
{
memset(board, set, rows*cols*sizeof(board[0][0]));
}
void InitBoard2(char board[ROWS2][COLS2], int rows, int cols, char set)
{
memset(board, set, rows*cols*sizeof(board[0][0]));
}
void DisplayBoard1(char board[ROWS1][COLS1], int row, int col)
{
int i = 0;
int j = 0;
for(i=0; i<=row; i++)
{
printf("%2d ",i);//第一行的序号,方便扫雷输入坐标
}
printf("\n");
for(i=1; i<=row; i++)
{
printf("%d ",i);//第一列的序号
for(j=1; j<=col; j++)
{
printf("%3c", board[i][j]);
}
printf("\n");
}
}
void DisplayBoard2(char board[ROWS2][COLS2], int row, int col)
{
int i = 0;
int j = 0;
for(i=0; i<=row; i++)
{
printf("%3d",i);
}
printf("\n");
for(i=1; i<=row; i++)
{
printf("%2d ",i);
for(j=1; j<=col; j++)
{
printf("%3c", board[i][j]);
}
printf("\n");
}
}
void SetMine1(char mine1[ROWS1][COLS1], int row, int col, int count)//初级mine数组中布置雷
{
int x = 0;
int y = 0;
while(count)
{
x = rand()%row+1;
y = rand()%col+1;
if(mine1[x][y] == '0')
{
mine1[x][y] = '1';
count--;
}
}
}
void SetMine2(char mine2[ROWS2][COLS2], int row, int col, int count)//初级mine数组中布置雷
{
int x = 0;
int y = 0;
while(count)
{
x = rand()%row+1;
y = rand()%col+1;
if(mine2[x][y] == '0')
{
mine2[x][y] = '1';
count--;
}
}
}
static int GetMineCount1(char mine[ROWS1][COLS1], int x, int y)
{
return 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]+mine[x-1][y]-8*'0';
}
static int GetMineCount2(char mine[ROWS2][COLS2], int x, int y)
{
return 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]+mine[x-1][y]-8*'0';
}
static void OpenMine1(char mine1[ROWS1][COLS1],char show1[ROWS1][COLS1],int row ,int col, int x,int y)
{
int ret = 0;
ret = GetMineCount1(mine1, x, y);
if(ret == 0)
{
show1[x][y]=' ';
if(x-1>0 && y>0 && show1[x-1][y]=='*')
OpenMine1(mine1, show1, row, col, x-1, y);
if(x-1>0 && y+1<=col && show1[x-1][y+1]=='*')
OpenMine1(mine1, show1, row, col, x-1, y+1);
if(x>0 && y+1<=col && show1[x][y+1]=='*')
OpenMine1(mine1, show1, row, col, x, y+1);
if(x+1<=row && y+1<=col && show1[x+1][y+1]=='*')
OpenMine1(mine1, show1, row, col, x+1, y+1);
if(x+1<=row && y>0 && show1[x+1][y]=='*')
OpenMine1(mine1, show1, row, col, x+1, y);
if(x+1<=row && y-1>0 && show1[x+1][y-1]=='*')
OpenMine1(mine1, show1, row, col, x+1, y-1);
if(x>0 && y-1>0 && show1[x][y-1]=='*')
OpenMine1(mine1, show1, row, col, x, y-1);
if(x-1>0 && y-1>0 && show1[x-1][y-1]=='*')
OpenMine1(mine1, show1, row, col, x-1, y-1);
}
else
{
show1[x][y] = GetMineCount1(mine1, x, y)+'0';//若坐标周围有雷,显示雷数
}
}
static void OpenMine2(char mine2[ROWS2][COLS2],char show2[ROWS2][COLS2],int row ,int col, int x,int y)
{
int ret = 0;
ret = GetMineCount2(mine2, x, y);
if(ret == 0)
{
show2[x][y]=' ';
if(x-1>0 && y>0 && show2[x-1][y]=='*')
OpenMine2(mine2, show2, row, col, x-1, y);
if(x-1>0 && y+1<=col && show2[x-1][y+1]=='*')
OpenMine2(mine2, show2, row, col, x-1, y+1);
if(x>0 && y+1<=col && show2[x][y+1]=='*')
OpenMine2(mine2, show2, row, col, x, y+1);
if(x+1<=row && y+1<=col && show2[x+1][y+1]=='*')
OpenMine2(mine2, show2 ,row, col, x+1, y+1);
if(x+1<=row && y>0 && show2[x+1][y]=='*')
OpenMine2(mine2, show2, row, col, x+1, y);
if(x+1<=row && y-1>0 && show2[x+1][y-1]=='*')
OpenMine2(mine2, show2, row, col, x+1, y-1);
if(x>0 && y-1>0 && show2[x][y-1]=='*')
OpenMine2(mine2, show2, row, col, x, y-1);
if(x-1>0 && y-1>0 && show2[x-1][y-1]=='*')
OpenMine2(mine2, show2, row, col, x-1, y-1);
}
else
{
show2[x][y] = GetMineCount2(mine2, x, y)+'0';//若坐标周围有雷,显示雷数
}
}
void FirstSafe1(char mine1[ROWS1][COLS1], char show1[ROWS1][COLS1], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
int tmp = 0;
int a = 0;
int b = 0;
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
a = x;
b = y;
if(mine1[x][y] == '1')
{
mine1[x][y] = '0';
count = GetMineCount1(mine1, x, y);
show1[x][y] = count+'0';
while(tmp)
{
x = rand()%row+1;
y = rand()%col+1;
if(mine1[x][y] == '0')
{
mine1[x][y] = '1';
}
tmp--;
}
}
OpenMine1(mine1, show1, row, col, a, b);
DisplayBoard1(show1, ROW1, COL1);
}
void FirstSafe2(char mine2[ROWS2][COLS2], char show2[ROWS2][COLS2], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
int tmp = 0;
int a = 0;
int b = 0;
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
a = x;
b = y;
if(mine2[x][y] == '1')
{
mine2[x][y] = '0';
count = GetMineCount2(mine2, x, y);
show2[x][y] = count+'0';
while(tmp)
{
x = rand()%row+1;
y = rand()%col+1;
if(mine2[x][y] == '0')
{
mine2[x][y] = '1';
}
tmp--;
}
}
OpenMine2(mine2, show2, row, col, a, b);
DisplayBoard2(show2, ROW2, COL2);
}
int IsWin1(char show1[ROWS1][COLS1], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for(i=0; i<=row; i++)
{
for(j=0; j<=col; j++)
{
if(show1[i][j] == '*')
{
count++;
}
}
}
return count;
}
int IsWin2(char show2[ROWS2][COLS2], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for(i=0; i<=row; i++)
{
for(j=0; j<=col; j++)
{
if(show2[i][j] == '*')
{
count++;
}
}
}
return count;
}
void FindMine1(char mine1[ROWS1][COLS1], char show1[ROWS1][COLS1], int row, int col,int count)//扫雷初级
{
int x = 0;
int y = 0;
int win = 0;
while(wincount)
{
FirstSafe1(mine1, show1, row, col);//第一步安全
if(x>=1 && x<=row && y>=1 && y<=col)
{
if(mine1[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
DisplayBoard1(mine1, ROW1, COL1);
break;
}
else
{
int count = GetMineCount1(mine1, x, y);
show1[x][y] = count + '0';
OpenMine1(mine1,show1,row ,col, x,y);
DisplayBoard1(show1, ROW1, COL1);
win++;
}
}
}
if(IsWin1(show1, row, col) == LOW_COUNT)
{
printf("恭喜你,扫雷成功!\n");
DisplayBoard1(show1, ROW1, COL1);
}
}
void FindMine2(char mine2[ROWS2][COLS2], char show2[ROWS2][COLS2], int row, int col,int count)//扫雷初级
{
int x = 0;
int y = 0;
int win = 0;
while(wincount)
{
FirstSafe2(mine2, show2, row, col);//第一步安全
if(x>=1 && x<=row && y>=1 && y<=col)
{
if(mine2[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
DisplayBoard2(mine2, ROW2, COL2);
break;
}
else
{
int count = GetMineCount2(mine2, x, y);
show2[x][y] = count + '0';
OpenMine2(mine2,show2,row ,col, x,y);
DisplayBoard2(show2, ROW2, COL2);
win++;
}
}
}
if(IsWin2(show2, row, col) == HIGH_COUNT)
{
printf("恭喜你,扫雷成功!\n");
DisplayBoard2(show2, ROW2, COL2);
}
}