#ifndef __GAME_H__
#define __GAME_H__
#define ROWS 10
#define COLS 10
#define default_count 10
void display(char arr[ROWS+2][COLS+2],int rows,int cols);
void display(char arr[ROWS+2][COLS+2],int rows,int cols);
void set_mine(char arr[ROWS+2][COLS+2],int rows,int cols);
int get_mine_count(char arr[ROWS+2][COLS+2],int x,int y);
void get_null(char arr[ROWS+2][COLS+2],int x,int y);
void move_mine(char arr[ROWS+2][COLS+2],int rows,int cols);
int win_game(char arr[ROWS+2][COLS+2],int x,int y);
#endif __GAME_H__
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "game.h"
#include <stdlib.h>
#include <time.h>
#include <string.h>
void menu()
{
//打印菜单。
printf(" 扫雷 \n");
printf("****************************\n");
printf("******** 1.play> ********\n");
printf("******** 0.exit> ********\n");
printf("****************************\n");
}
enum Option
{
EXIT, //枚举开始退出
PLAY
};
//打印游戏坐标
void display(char arr[ROWS+2][COLS+2],int rows,int cols)
{
int i = 0;
int j = 0;
int k = 0;
printf(" ");
for(k = 1;k<=rows;k++)
{
printf("%-d ",k);
}
printf("\n");
printf("\n");
for(i = 1;i<=rows;i++)
{
printf("%2d ",i);
for(j = 1;j<=cols;j++)
{
printf("%c ",arr[i][j]);
}
printf("\n");
printf("\n");
}
}
//随机函数放置雷
void set_mine(char arr[ROWS+2][COLS+2],int rows,int cols)
{
int count = 0;
count = default_count;
while(count)
{
int i = rand()%ROWS+1;
int j = rand()%COLS+1;
if(arr[i][j] == '0')
{
arr[i][j] = '1';
count--;
}
}
}
//统计周围雷的数量
int get_mine_count(char arr[ROWS+2][COLS+2],int x,int y)
{
return (arr[x-1][y-1]-'0'+arr[x][y-1]-'0'+arr[x+1][y-1]-'0'+arr[x+1][y]-'0'+
arr[x+1][y+1]-'0'+arr[x][y+1]-'0'+arr[x-1][y+1]-'0'+arr[x-1][y]-'0');
}
//第一下点中雷的话移走
void move_mine(char arr[ROWS+2][COLS+2],int rows,int cols)
{
int count = 1;
while(count)
{
int i = rand()%ROWS+1;
int j = rand()%COLS+1;
if(arr[i][j] == '0')
{
arr[i][j] = '1';
count--;
}
}
}
//检查游戏进度
int win_game(char arr[ROWS+2][COLS+2],int rows,int cols)
{
int i = 0;
int j = 0;
int count = 0;
for(i = 1;i<=rows;i++)
{
for(j = 1;j<=cols;j++)
{
if(arr[i][j] == '*')
count++;
}
}
return count;
}
void game()
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
int win = 0;
char mine[ROWS+2][COLS+2] = {0};
char show[ROWS+2][COLS+2] = {0};
srand((unsigned int)time(NULL));
memset(mine,'0',sizeof(char)*(ROWS+2)*(COLS+2)); //初始化为0
memset(show,'*',sizeof(char)*(ROWS+2)*(COLS+2));
display(show,ROWS,COLS); //打印坐标
set_mine(mine,ROWS,COLS);//布雷
display(mine,ROWS,COLS); //展示雷的位置
while(1)
{
printf("请输入坐标:");
scanf("%d%d",&x,&y);
++j;
if(mine[x][y] == '1')
{
if(j == 1)
{
mine[x][y] = '0';
show[x][y] = '0';
move_mine(mine,x,y);//第一个是雷移走
//display(mine,ROWS,COLS);
}
else
{
printf("噗!!!炸死了\n");
break;
}
}
else
{
int count = 0;
count = get_mine_count(mine,x,y);
show[x][y] = count+'0';
//计算放置位置周围的雷数
for(i = x-1;i<=x+1;i++)
{
if(mine[i][y-1]=='0')
show[i][y-1] = '0';
}
i = 0;
for(i = x-1;i<=x+1;i+=2)
{
if(mine[i][y]=='0')
show[i][y] = '0';
}
i = 0;
for(i = x-1;i<=x+1;i++)
{
if(mine[i][y+1]=='0')
show[i][y+1] = '0';
}
}
display(show,ROWS,COLS);
if(win_game(show,ROWS,COLS) == default_count)//计算游戏进程函数
break;
}
if(win_game(show,ROWS,COLS) == default_count)
printf("恭喜你排雷成功\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d",&input);
switch(input)
{
case EXIT:
break;
case PLAY:
game();
break;
default:
printf("输入错误,请重新输入\n");
break;
}
}
while(input);
return 0;
}
这个小游戏的实现主要在于理清游戏逻辑,对各个步骤封装成函数,一步一步来实现。
1.游戏菜单函数,因为每一次的游戏执行都要打印菜单,所以把它封装成函数放在首部。而且用一个swtich语句加枚举类型,使得游戏逻辑更加清晰,把所有的游戏步骤都放在game()函数中。把所有游戏过程都放在while中,因为要连续玩只是在退出的时候退出。
2.game()函数里边封装游戏所有逻辑步骤,display()函数,打印游戏坐标,使用简单的双重for循环实现,为了使玩家填写坐标的时候更加方便添加数字坐标,一目了然。接下来是游戏的随机雷,在最开始define 定义雷的个数和游戏坐标的大小增加游戏的可玩性和可移植性。 用srand随机函数产生坐标,就是随机雷了,为了后期统计雷数方便我们用0代表非雷。再就是统计一个非雷周围的雷数,用了函数get_mine()函数,对周围八个坐标是雷的金星加和返回。
3.为了增加游戏的可玩性,所以觉定如果第一个是雷的话移走,所以就用到了函数move_mine()还是用随机函数srand把第一个雷随机移到其他非雷处。最后是检查排掉的雷的个数是check_win()函数,利用双重for循环记录所有*的个数来判断游戏进程。
4。最后回到游戏的主逻辑部分,设置变量的来接收函数的返回值,进行判断,为了游戏更好的测试,排除不定性,我们打印出雷阵来测试效率更高,反复调试用F10一步步确定整个游戏的过程都是我们所设计的那样来执行的。最后完成这个小游戏。