核心算法:
就是关于点击雷区的操作:
//data数组用来储存雷区,雷9,非雷非数字(0),数字(1-8)
//clickdata数组用来储存雷区是否被按过,没按过(0),左键按过(1),右键按过(2)
int click(int i,int j,int k){ ///点击雷区,雷9,非雷非数字(0),数字(1-8)
if(clickdata[j][i]==1) //已经按下左键
return 0;
if(k==1) //按下左键
{
clickdata[j][i]=1;
if(data[j][i]==9) //扫出雷
{
//出现雷的动作;
}
if(data[j][i]==0) //用递归来扫清非雷非数字的部分
{
//出现非雷非数字的动作;
if(i-1>-1 && data[j][i-1]==0)
click(i-1,j,1);
if(i+1<width && data[j][i+1]==0) //width是雷区的宽
click(i+1,j,1);
if(j-1>-1 && data[j-1][i]==0)
click(i,j-1,1);
if(j+1<height && data[j+1][i]==0) //height是雷区的高
click(i,j+1,1);
}
if(data[j][i]>0 && data[j][i]<9)
{
//出现数字的动作;
}
}
if(k==2) //按下右键
{
if(clickdata[j][i]==0)
{
//出现旗子的动作
clickdata[j][i]=2;
}
else if(clickdata[j][i]==2)
{
//出现未扫过的状态动作
clickdata[j][i]=0;
}
}
return 0;
}
如果以上你看懂了,差不多就可以自己动手了。
以下是我的代码,可以作为参考
运行图:
刚刚C++学了类,所以试了下用类来做,当然不用也可以。
#include<iostream>
#include <string>
#include <windows.h>
#include <graphics.h> //要下载easyx才行
#include <ctime>
#include <cstdlib>
#pragma comment(lib,"winmm.lib")
using namespace std;
class Minesweep{
public:
Minesweep(); //显示界面
~Minesweep();
void startbutton(); //笑脸按钮
void randdata(); //将数据输入
void showmap(); //显示地图
void playing(); //开始游戏
int judge(); //判断游戏输赢
void gameover(int judge); //判断游戏结束
void clickmenu(MOUSEMSG m); //点击菜单
int click(int i,int j,int k); //点击雷区
int restartbutton(MOUSEMSG m); //重新开始,笑脸按钮
int widthbutton(MOUSEMSG m); //宽度箭头按钮
int heightbutton(MOUSEMSG m); //高度箭头按钮
int boombutton(MOUSEMSG m); //炸弹箭头按钮
void showtime(int show); //显示时间
static int imagesize;
static int menuheight;
static int height,width;
static int boomnumber;
static int startbuttonx;
static int startbuttony;
static int wbuttonx;
static int hbuttonx;
static int wbuttony;
static int hbuttony;
static int bbuttonx;
static int bbuttony;
static int button_width;
static int button_height;
static int button_boomnumber;
clock_t time1; //计时用的
clock_t time2;
private:
int **data; ///数据储存雷(9),数字(1-8),无雷无数字部分(0)
int **clickdata; ///判断被点击了没,左键点击1,右键点击2,没点击(0)
};
int Minesweep :: imagesize=25; //载入图片的大小
int Minesweep :: height=10; //雷区高度
int Minesweep :: width =10; //雷区宽度
int Minesweep :: menuheight=30; //菜单栏高度
int Minesweep :: boomnumber=(height*width)/6; //炸弹数
int Minesweep :: startbuttonx; //笑脸按钮的位置
int Minesweep :: startbuttony;
int Minesweep :: wbuttonx; //宽度和高度箭头的位置
int Minesweep :: wbuttony;
int Minesweep :: hbuttonx;
int Minesweep :: hbuttony;
int Minesweep :: bbuttonx; //炸弹箭头的位置
int Minesweep :: bbuttony;
int Minesweep :: button_width=width; //改变后的宽度
int Minesweep :: button_height=height; //改变后的高度
int Minesweep :: button_boomnumber=boomnumber; //改变后的炸弹数
Minesweep::Minesweep(){
initgraph(width*imagesize,height*imagesize+menuheight); /*开始时设置窗口大小*/
}
Minesweep::~Minesweep(){ //结束时释放数据空间
for(int i=0;i<height;i++)
{
delete [] data[i];
delete [] clickdata[i];
}
}
void Minesweep::startbutton(){ //按下笑脸时的动作
randdata();
showmap();
playing();
}
/***************************************将数据输入**********************************************************/
void Minesweep::randdata(){
int i,j;
srand(time(0));
boomnumber=button_boomnumber;
if(!(width==button_width && height==button_height))
{
width=button_width;
height=button_height;
boomnumber=(height*width)/6;
initgraph(width*imagesize,height*imagesize+menuheight); /*设置窗口大小*/
}
else
cleardevice();
button_boomnumber=boomnumber;
data=new int *[height]; //申请数据空间
for(i=0;i<height;i++)
data[i]=new int [width];
for(j=0;j<height;j++)
for(i=0;i<width;i++)
data[j][i]=0;
clickdata=new int *[height]; //clickdata[高][宽]数据初始化
for(i=0;i<height;i++)
clickdata[i]=new int [width];
for(j=0;j<height;j++)
for(i=0;i<width;i++)
clickdata[j][i]=0;
for(i=0;i<boomnumber;i++) //埋入炸弹(为数字9)
while(1)
{
int a= rand()%height;
int b= rand()%width;
if(data[a][b]==0)
{
data[a][b]=9;
break;
}
}
for(j=0;j<height;j++) //填入数字(1-8)
for(i=0;i<width;i++)
{
if(data[j][i]!=0)
continue;
int getnumber=0;
//左右
if(i-1>-1 && data[j][i-1]==9)
getnumber++;
if(i+1<width && data[j][i+1]==9)
getnumber++;
//上下
if(j-1>-1 && data[j-1][i]==9)
getnumber++;
if(j+1<height && data[j+1][i]==9)
getnumber++;
//四个点
if(i-1>-1 && j-1>-1 && data[j-1][i-1]==9)
getnumber++;
if(i-1>-1 && j+1<height && data[j+1][i-1]==9)
getnumber++;
if(i+1<width && j+1<height && data[j+1][i+1]==9)
getnumber++;
if(i+1<width && j-1>-1 && data[j-1][i+1]==9)
getnumber++;
data[j][i]=getnumber;
}
}
/*****************************************显示地图***************************************/
void Minesweep::showmap(){
IMAGE blankimage,smileimage,wbutton,hbutton,bbutton;
loadimage(&blankimage,_T("blank.png"));
Resize(&blankimage,imagesize,imagesize);
for(int x=0;x<width*imagesize;x+=imagesize) //所有空白的位置
for(int y=menuheight;y<height*imagesize+menuheight;y+=imagesize)
{
putimage(x,y,&blankimage);
}
loadimage(&smileimage,_T("smile.png")); //笑脸的位置
Resize(&smileimage,imagesize,imagesize);
startbuttonx=width*imagesize/2-imagesize/2;
startbuttony=menuheight/2-imagesize/2;
putimage(startbuttonx,startbuttony,&smileimage);
wbuttonx=0; //宽度箭头的位置
wbuttony=0;
loadimage(&wbutton,_T("arrow.png"));
Resize(&wbutton,imagesize/2,imagesize);
putimage(wbuttonx,wbuttony,&wbutton);
hbuttonx=imagesize*3/2; //高度箭头的位置
hbuttony=0;
loadimage(&hbutton,_T("arrow.png"));
Resize(&hbutton,imagesize/2,imagesize);
putimage(hbuttonx,hbuttony,&hbutton);
bbuttonx=imagesize*3; //炸弹箭头的位置
bbuttony=0;
loadimage(&bbutton,_T("arrow.png"));
Resize(&hbutton,imagesize/2,imagesize);
putimage(bbuttonx,bbuttony,&bbutton);
char widthstr[10]; //显示宽度数字
itoa(button_width,widthstr,10);
settextstyle(13,0,_T(widthstr));
outtextxy(imagesize/2,imagesize/4,_T(widthstr));
char heightstr[10]; //显示高度数字
itoa(button_height,heightstr,10);
settextstyle(13,0,_T(heightstr));
outtextxy(imagesize*2,imagesize/4,_T(heightstr));
char boomstr[10]; //显示高度数字
itoa(button_boomnumber,boomstr,10);
settextstyle(13,0,_T(boomstr));
outtextxy(imagesize*3+imagesize/2,imagesize/4,_T(boomstr));
}
/*******************************************开始游戏*********************************************/
void Minesweep::playing(){
MOUSEMSG m;
int show=0; //当点击雷区时,show变为1,开始计时
while(1)
{
if(MouseHit())
{
m=GetMouseMsg();
if(m.mkLButton) //左键动作
{
if(m.x>0 && m.x < width*imagesize && m.y>menuheight && m.y < height*imagesize+menuheight) ///点击雷区
{
PlaySound(TEXT("sweepvoice"),NULL,SND_ASYNC);
click(m.x/imagesize,(m.y-menuheight)/imagesize,1); //1是按下左键
if(judge())
break;
show=1;
}
else
clickmenu(m); ///点击菜单
}
if(m.mkRButton) //右键动作
{
PlaySound(TEXT("sweepvoice"),NULL,SND_ASYNC);
if(m.x>0 && m.x < width*imagesize && m.y>menuheight && m.y < height*imagesize+menuheight) //点击雷区
{
click(m.x/imagesize,(m.y-menuheight)/imagesize,2); //2是按下右键
show=1;
}
}
}
showtime(show);
}
gameover(judge()); //游戏结束
FlushMouseMsgBuffer();
while(1)
{
if(MouseHit())
{
m=GetMouseMsg();
if(m.mkLButton)
{
clickmenu(m);
}
}
}
}
///判断游戏输赢和游戏结束//
int Minesweep::judge(){ ///判断胜利,踩雷情况
int i,j;
if(time2>3600*24)
return 1;
for(j=0;j<height;j++)
for(i=0;i<width;i++)
if(clickdata[j][i]==1 && data[j][i]==9)
return 1; //踩雷
for(j=0;j<height;j++)
for(i=0;i<width;i++)
if(clickdata[j][i]==0 && data[j][i]>=0 && data[j][i]<9 )
return 0; //判断全点开了没
return 2; //胜利
}
void Minesweep::gameover(int judge){ //游戏结束后的界面
if(judge==1)
{
PlaySound(TEXT("boom1"),NULL,SND_ASYNC);
for(int j=0;j<height;j++) //游戏失败,放出所有雷
for(int i=0;i<width;i++)
if(data[j][i]==9)
{
click(i,j,1);
}
}
if(judge==2) //游戏通关
{
char str[12]="恭喜通关";
outtextxy(width*imagesize/2-25,(menuheight+height*imagesize)/2,_T(str));
}
}
///按钮设置//
int Minesweep::widthbutton(MOUSEMSG m){ //按下宽度箭头按钮
if(m.x>wbuttonx && m.x < imagesize/2 && m.y>wbuttony && m.y<imagesize/2)
return 1;
else if(m.x>wbuttonx && m.x < imagesize/2 && m.y>imagesize/2 && m.y<imagesize)
return -1;
return 0;
}
int Minesweep::heightbutton(MOUSEMSG m){ //按下高度箭头按钮
if(m.x>hbuttonx && m.x<hbuttonx+imagesize/2 && m.y>hbuttony && m.y<imagesize/2)
return 1;
else if(m.x>hbuttonx && m.x<hbuttonx+imagesize/2 && m.y>hbuttony+imagesize/2 && m.y<imagesize)
return -1;
return 0;
}
int Minesweep::boombutton(MOUSEMSG m){ //按下炸弹箭头按钮
if(m.x>bbuttonx && m.x<bbuttonx+imagesize/2 && m.y>bbuttony && m.y<imagesize/2)
return 1;
else if(m.x>bbuttonx && m.x<bbuttonx+imagesize/2 && m.y>bbuttony+imagesize/2 && m.y<imagesize)
return -1;
return 0;
}
int Minesweep::restartbutton(MOUSEMSG m){
if(m.x>startbuttonx && m.x < startbuttonx+imagesize && m.y>startbuttony && m.y < startbuttony+imagesize)
return 1;
return 0;
}
/点击菜单和雷区动作//
void Minesweep::clickmenu(MOUSEMSG m){ ///点击菜单//
if(restartbutton(m)) //重新开始
{
for(int i=0;i<height;i++)
{
delete [] data[i];
delete [] clickdata[i];
}
startbutton();
}
else if(widthbutton(m) || heightbutton(m) || boombutton(m)) //按到箭头按钮
{
if(widthbutton(m)==1)
button_width++;
else if(widthbutton(m)==-1)
button_width--;
if(heightbutton(m)==1)
button_height++;
else if(heightbutton(m)==-1)
button_height--;
if(boombutton(m)==1)
button_boomnumber++;
else if(boombutton(m)==-1)
button_boomnumber--;
if(button_width<10)
button_width=10;
if(button_width>40)
button_width=40;
if(button_height<10)
button_height=10;
if(button_height>20)
button_height=20;
if(button_boomnumber<10)
button_boomnumber=10;
if(button_boomnumber>button_width*button_height-1)
button_boomnumber=button_width*button_height-1;
char widthstr[10];
itoa(button_width,widthstr,10);
settextstyle(13,0,_T(widthstr));
outtextxy(imagesize/2,imagesize/4,_T(widthstr));
char heightstr[10];
itoa(button_height,heightstr,10);
settextstyle(13,0,_T(heightstr));
outtextxy(imagesize*2,imagesize/4,_T(heightstr)); //
char boomstr[10]; //显示高度数字
cout << button_boomnumber << endl;
itoa(button_boomnumber,boomstr,10);
settextstyle(13,0,_T(boomstr));
outtextxy(imagesize*3+imagesize/2,imagesize/4,_T(boomstr));
}
}
int Minesweep::click(int i,int j,int k){ ///点击雷区
if(clickdata[j][i]==1) //已经按下左键
return 0;
if(k==1) //按下左键
{
clickdata[j][i]=1;
if(data[j][i]==9)
{
IMAGE boomimage;
loadimage(&boomimage,_T("boom.png"));
Resize(&boomimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&boomimage);
}
if(data[j][i]==0)
{
IMAGE numberimage;
loadimage(&numberimage,_T("0.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
//左右
if(i-1>-1 && data[j][i-1]==0)
click(i-1,j,1);
if(i+1<width && data[j][i+1]==0)
click(i+1,j,1);
//上下
if(j-1>-1 && data[j-1][i]==0)
click(i,j-1,1);
if(j+1<height && data[j+1][i]==0)
click(i,j+1,1);
}
if(data[j][i]==1)
{
IMAGE numberimage;
loadimage(&numberimage,_T("1.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==2)
{
IMAGE numberimage;
loadimage(&numberimage,_T("2.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==3)
{
IMAGE numberimage;
loadimage(&numberimage,_T("3.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==4)
{
IMAGE numberimage;
loadimage(&numberimage,_T("4.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==5)
{
IMAGE numberimage;
loadimage(&numberimage,_T("5.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==6)
{
IMAGE numberimage;
loadimage(&numberimage,_T("6.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==7)
{
IMAGE numberimage;
loadimage(&numberimage,_T("7.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
if(data[j][i]==8)
{
IMAGE numberimage;
loadimage(&numberimage,_T("8.png"));
Resize(&numberimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&numberimage);
}
}
if(k==2) //按下右键
{
if(clickdata[j][i]==0)
{
IMAGE flagimage;
loadimage(&flagimage,_T("flag.png"));
Resize(&flagimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&flagimage);
clickdata[j][i]=2;
}
else if(clickdata[j][i]==2)
{
IMAGE blankimage;
loadimage(&blankimage,_T("blank.png"));
Resize(&blankimage,imagesize,imagesize);
putimage(imagesize*i,imagesize*j+menuheight,&blankimage);
clickdata[j][i]=0;
}
}
return 0;
}
///显示计时/
void Minesweep::showtime(int show){
if(show)
{
int hour,munite,second;
time2=(clock()-time1)/1000;
hour=time2/3600;
munite=(time2-hour*3600)/60;
second=time2-hour*3600-munite*60;
char str[10],zero[2]="0";
settextstyle(24,0,_T(str));
settextstyle(24,0,_T(zero));
itoa(hour,str,10);
if(hour<10)
{
outtextxy((width-4)*imagesize,imagesize/4,_T(zero));
outtextxy((width-4)*imagesize+13,imagesize/4,_T(str));
}
else
outtextxy((width-4)*imagesize,imagesize/4,_T(str));
outtextxy((width-3)*imagesize,imagesize/4,_T(":"));
itoa(munite,str,10);
if(munite<10)
{
outtextxy((width-3)*imagesize+12,imagesize/4,_T(zero));
outtextxy((width-2)*imagesize,imagesize/4,_T(str));
}
else
outtextxy((width-3)*imagesize+12,imagesize/4,_T(str));
outtextxy((width-2)*imagesize+12,imagesize/4,_T(":"));
itoa(second,str,10);
if(second<10)
{
outtextxy((width-1)*imagesize,imagesize/4,_T(zero));
outtextxy((width-1)*imagesize+12,imagesize/4,_T(str));
}
else
outtextxy((width-1)*imagesize,imagesize/4,_T(str));
}
else
{
time1=clock();
time2=0;
}
}
/可以开始玩了///
void playgame(){
Minesweep m;
m.startbutton();
}
int main(){
playgame();
cin.get();
return 0;
}
哦,对了图片声音,以及源代码的链接给你们:
链接:https://pan.baidu.com/s/1AYILA1moC3C9iU4YE9OBJw
提取码:9nh3
新手小白刚学C++,有什么建议话,欢迎各位在以下给我留言。