经过上次的三子棋小游戏,我又写了一个扫雷的小游戏
具体思路如下:
首先我们应该得打印一个游戏页面,俗话说的好:游戏界面,就是编程师的脸面。(好像是我总结的)
void mune()
{
printf("|---------------------------|\n");
printf("|~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
printf("|~~~~~~~~~~~扫雷~~~~~~~~~~~~|\n");
printf("|~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
printf("|~~~~~1.play 0.end~~~~~|\n");
printf("|~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
printf("|---------------------------|\n");
}
如下:
接下来就是选择菜单了
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
mune();
printf("请选择:");
scanf("%d",&input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入有误\n");
break;
}
break;
}while(input);
return 0;
}
这个菜单我就不细细说明了
紧接着我们改打印一个棋盘了
void game()
{
//首先声明一点,棋盘我们在运行时候是要创建2个棋盘的,一个作为雷阵,一个作为展现给我们玩家的棋盘。
char board[ROWS][COLS]={0};//建立一个2维数组并赋值0
char show[ROWS][COLS]={0};//建立一个2维数组并赋值0
char ret = 0;
init_board(board,'0',ROWS,COLS);//这是给棋盘赋值为字符0(雷阵),在这里我解释一下为什么要赋值成字符型呢,因为我们这个扫雷的规则是如果四周有雷的话它会把雷的数量加起来,并且显示出来。并且打印棋盘的时候得打印*类型这样为了方便起见,我们把这个数字赋值成字符型。
init_board(show,'*',ROWS,COLS);//这是展现给我们的棋盘,就赋值成为*
mine_board(board);//这是给雷阵布雷
display_board(board,ROW,COL);//这是为了测试需要我们打印雷阵,等游戏测试完毕这个就不需要了
display_board(show,ROW,COL);//打印展示棋盘
play_move(board,show,ROW,COL);//开始扫雷
}
首先来介绍给棋盘赋值
//在这里我们引入一个函数可以对数组类型进行统一赋值。
void init_board(char arr[ROWS][COLS],char set,int row,int col)
{
memset(arr,set,col*row*sizeof(arr[0][0]));
}
接下来该布置雷阵了
void mine_board(char arr[ROWS][COLS])
{
int count = EASY;//这是设定的难度等级,可以在头文件中自己设定在这里我们先设定EASY为10个。
while(count)
{
int i = rand()%9+1;
int j = rand()%9+1;
if(arr[i][j]=='0')
{
arr[i][j] = '1';
count--;
}
}
}
接下来是打印棋盘,我们要看下我们放置的雷是否正确
void display_board(char arr[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
printf(" ");
for(i=1; i<=row; i++)
{
printf("%d ",i);
}
printf("\n");
for(i=1; i<=row; i++)
{
printf("%d ",i);
for(j=1; j<=col; j++)
{
printf("%c ",arr[i][j]);
}
printf("\n");
}
printf("-------------------\n");
}
接下来我们检验一下雷阵是否布置正确
在第一个图上,我们明显的可以看到共有10个1,这10个1就是雷。这就说明我们的雷阵布置正确。而下面对额棋盘就是我们要排雷的棋盘。
接下来就是我们开始排雷了,为了增加游戏的可玩性,我们设置成(你排的第一个坐标肯定不会踩到雷,即使踩到,那就偷偷的把这个雷移走。在让我们看来没有踩到雷)
void play_move(char arr[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
int tmp = 0;//统计我们排雷的次数
char m = 0;
do
{
printf("请输入坐标:");
scanf("%d%d",&i,&j);
if((arr[i][j]=='1')&&(tmp == 0))//这里我们检验一下第一个排雷的坐标是不是雷,如果是那就进入这个程序。
{
arr[i][j]='0';//先偷偷的把这个值赋为'0'
get_mine_count(arr,show,i,j);//再来对这个坐标进行扫描看周围是否有雷。
while(1)//我们把刚才雷给消掉,现在少了一个雷,那我们就要重新在其他地方布置一个雷。
{
x = rand()%9+1;//产生一个随机的坐标
y = rand()%9+1;
if(arr[x][y] == '0')//检查这个坐标是否有雷,如果没有雷,则就把雷放入这个坐标,如果有雷重新生成一个坐标,再次检测。
{
arr[x][y]='1';
display_board(show,ROW,COL);
tmp++;//排除了第一次坐标踩到雷,这个值++,就不会再次进入移动雷的程序了。
break;
}
}
continue;
}
if(arr[i][j]=='1')//你踩到雷了
{
printf("炸死了\n");
break;
}
else if(arr[i][j]=='0')
{
get_mine_count(arr,show,i,j);//开始检查四周的雷数
tmp++;//计算你排雷的个数
}
display_board(show,ROW,COL);//排完一次雷,就得重新打印一次棋盘
if(tmp ==(row*col-EASY))//你成功的排完所有雷
{
printf("游戏胜利,成功排完所有雷\n");
}
}while(tmp < (row*col-EASY));
}
接下来我们测试一下第一次踩到雷而不会被炸
在这里我们看到坐标1 2有雷,那我们来试试
可以看到在我们的雷阵中,这个雷被悄悄的移到了3 5这个坐标中。
为什么雷阵的1 2坐标会是’ ‘呢,下面有解释。
接下来我们要做的是展开(意思是,如果我们的坐标周围没有雷,那么会遵照他的四周扩散开,直到有雷才会停止)在这里我们用递归的方法会好一点
void get_mine_count(char arr[ROWS][COLS],char show[ROWS][COLS],int i,int j)
{
if(i<(ROWS-1)&&j<(COLS-1)&&i>0&&j>0)//所有的坐标必须在棋盘范围内
{
if((arr[i][j]=='0'))//没有踩到雷
{
int count=0;
arr[i][j] = ' ';//这个就是我们把第一个雷移开,这个在雷阵的坐标中就是空格符号的原因
if(arr[i-1][j-1]=='1')
count++;
if(arr[i-1][j]=='1')
count++;
if(arr[i-1][j+1]=='1')
count++;
if(arr[i][j-1]=='1')
count++;
if(arr[i][j+1]=='1')
count++;
if(arr[i+1][j-1]=='1')
count++;
if(arr[i+1][j]=='1')
count++;
if(arr[i+1][j+1]=='1')
count++;
show[i][j]=(count+'0');
}
if(show[i][j]=='0')//这里就是递归
{
show[i][j]=' ';
if(show[i-1][j-1]=='*')
get_mine_count(arr,show,(i-1),(j-1));
if(show[i-1][j]=='*')
get_mine_count(arr,show,(i-1),(j));
if(show[i-1][j+1]=='*')
get_mine_count(arr,show,(i-1),(j+1));
if(show[i][j-1]=='*')
get_mine_count(arr,show,(i),(j-1));
if(show[i][j+1]=='*')
get_mine_count(arr,show,(i),(j+1));
if(show[i+1][j-1]=='*')
get_mine_count(arr,show,(i+1),(j-1));
if(show[i+1][j]=='*')
get_mine_count(arr,show,(i+1),(j));
if(show[i+1][j+1]=='*')
get_mine_count(arr,show,(i+1),(j+1));
}
}
}
让我们看一下效果图吧
接下来我们测试一下(测试的时候可以把EASY调大一点,因为我们现在是测试一下,没必要认真的排上几十次,认真的话你就输了。我把EASY换成了76,意思是只要我走5次没踩到雷我就赢了)
在这里我们看到只有五个位置是安全的
游戏胜利
接下来我们来测试一下输了的情况
那么来几张真实 的游戏体验图
好了整体游戏的思路就完了。程序如下
————————————————————————————game.h————————————————————————————
——————————————————game.h————————————————————
#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define EASY 10
#define HARD 40
void init_board(char arr[ROWS][COLS],char set,int row,int col);
void display_board(char arr[ROWS][COLS],int row,int col);
void mine_board(char arr[ROWS][COLS]);
void play_move(char arr[ROWS][COLS],char show[ROWS][COLS],int row,int col);
void get_mine_count(char arr[ROWS][COLS],char show[ROWS][COLS],int i,int j);
#endif //__GAME_H__
——————————————————game.c————————————————————
#include <stdio.h>
#include "game.h"
void init_board(char arr[ROWS][COLS],char set,int row,int col)
{
memset(arr,set,col*row*sizeof(arr[0][0]));
}
void mine_board(char arr[ROWS][COLS])
{
int count = EASY;
while(count)
{
int i = rand()%9+1;
int j = rand()%9+1;
if(arr[i][j]=='0')
{
arr[i][j] = '1';
count--;
}
}
}
void display_board(char arr[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
printf(" ");
for(i=1; i<=row; i++)
{
printf("%d ",i);
}
printf("\n");
for(i=1; i<=row; i++)
{
printf("%d ",i);
for(j=1; j<=col; j++)
{
printf("%c ",arr[i][j]);
}
printf("\n");
}
printf("-------------------\n");
}
void get_mine_count(char arr[ROWS][COLS],char show[ROWS][COLS],int i,int j)
{
if(i<(ROWS-1)&&j<(COLS-1)&&i>0&&j>0)
{
if((arr[i][j]=='0'))
{
int count=0;
arr[i][j]=' ';
if(arr[i-1][j-1]=='1')
count++;
if(arr[i-1][j]=='1')
count++;
if(arr[i-1][j+1]=='1')
count++;
if(arr[i][j-1]=='1')
count++;
if(arr[i][j+1]=='1')
count++;
if(arr[i+1][j-1]=='1')
count++;
if(arr[i+1][j]=='1')
count++;
if(arr[i+1][j+1]=='1')
count++;
show[i][j]=(count+'0');
}
if(show[i][j]=='0')
{
show[i][j]=' ';
if(show[i-1][j-1]=='*')
get_mine_count(arr,show,(i-1),(j-1));
if(show[i-1][j]=='*')
get_mine_count(arr,show,(i-1),(j));
if(show[i-1][j+1]=='*')
get_mine_count(arr,show,(i-1),(j+1));
if(show[i][j-1]=='*')
get_mine_count(arr,show,(i),(j-1));
if(show[i][j+1]=='*')
get_mine_count(arr,show,(i),(j+1));
if(show[i+1][j-1]=='*')
get_mine_count(arr,show,(i+1),(j-1));
if(show[i+1][j]=='*')
get_mine_count(arr,show,(i+1),(j));
if(show[i+1][j+1]=='*')
get_mine_count(arr,show,(i+1),(j+1));
}
}
}
void play_move(char arr[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
int tmp = 0;
char m = 0;
do
{
int ret = 0;
printf("请输入坐标:");
scanf("%d %d",&i,&j);
if(!(((i>=1)&&(i<=row))||((j>=1)&&(j<=col))))
{
printf("坐标有误,请重新输入坐标\n");
continue;
}
if(arr[i][j]==' ')
{
printf("坐标已刷新,请重新输入坐标\n");
continue;
}
if((arr[i][j]=='1')&&(tmp == 0))
{
arr[i][j]='0';
while(1)
{
x = rand()%9+1;
y = rand()%9+1;
if(arr[x][y] == '0')
{
arr[x][y]='1';
get_mine_count(arr,show,i,j);
display_board(show,ROW,COL);
tmp++;
break;
}
}
}
if(arr[i][j]=='1')
{
printf("炸死了\n");
break;
}
else if(arr[i][j]=='0')
{
get_mine_count(arr,show,i,j);
tmp++;
display_board(show,ROW,COL);
}
for(i=1; i<=row; i++)
{
for(j=1; j<=col; j++)
{
if(arr[i][j] == ' ')
ret++;
}
}
if(ret == row*col-EASY)
{
printf("游戏胜利,成功排完所有雷\n");
break;
}
}while(tmp < (row*col-EASY));
}
——————————————————test.c————————————————————
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "game.h"
void mune()
{
printf("|---------------------------|\n");
printf("|~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
printf("|~~~~~~~~~~~扫雷~~~~~~~~~~~~|\n");
printf("|~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
printf("|~~~~~1.play 0.end~~~~~|\n");
printf("|~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
printf("|---------------------------|\n");
}
void game()
{
char board[ROWS][COLS]={0};
char show[ROWS][COLS]={0};
char ret = 0;
init_board(board,'0',ROWS,COLS);
init_board(show,'*',ROWS,COLS);
mine_board(board);
display_board(board,ROW,COL);
display_board(show,ROW,COL);
play_move(board,show,ROW,COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
mune();
printf("请选择:");
scanf("%d",&input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入有误\n");
break;
}
break;
}while(input);
return 0;
}