扫雷游戏
自己动手写了扫雷游戏(C语言版)。
我使用了EasyX这个库(下载地址:http://www.easyx.cn EasyX 2014冬至版)。
在写扫雷游戏过程中用到了
1.二维数组的划分与创建
划分:
int **p,i;
p=(int **)malloc(sizeof(int *)*mine_row);
for(i=0;iint*)malloc(sizeof(int)*mine_line);
释放:
for (i=0; ii++)
free(p[i]);
free(p);
2.用递归实现扫雷游戏中的点开空白(不是数字)大面积出现的情况。
3.运用2重循环实现游戏不会结束,点击笑脸刷新游戏。
4.画图要仔细的计算。
我的想法是:如果是雷则记为-1,什么都没有为0,然后是数字12345678。红旗标记则加一个大点的数,如+10,+20,取消标记再减去相同数。挖开雷也是加个大点的数字,+50。用if..else if 判断每个周围是否有雷,有雷则+1,没雷不加。如果自身是雷则跳过。产生雷的地方使用随机数。
使用方法:
srand((unsigned)time(NULL));i=rand()%mine_row;
//Mine Game
#include
#include
#include
#include
#include
int mine_row,mine_line,size;//行数 ,列数 ,每个格子大小
int m_x,m_y; //横坐标,纵坐标
int **p;
int m_marked; //标记的个数
int m_digged; //挖了的个数
int m_faceX;//笑脸长
int m_faceY;//笑脸高
int mine_number;//雷总个数
int STATE=0;//状态
void draw_box(int x,int y,int width,int heigh,int type,int depth);
void graph();
void draw_area(int w);
void lay_mine(int mine_number);
void draw_mine(int x,int y);
void show_all_data();
void show_number(int x,int y,int number,int w);
void Around_mine_number();
int Mouse_Click_left(MOUSEMSG *mouse);
void Mouse_Click(unsigned int t1,unsigned int t2,int t);
int dig_mine(int x,int y);
void cal_dig_mine(int x,int y,int *i,int *j);
void dig_mine1(int i,int j);
void dig_mine2(int i,int j);
void draw_flag(int i,int j);
void Mouse_Click_right(MOUSEMSG *mouse);
void put_flag(int i,int j);
void show_game(char str[]);
void smile_face();
void scan_mine();
void Mouse_Move(MOUSEMSG *mouse);
void show_mine_number();
void show_Minenumber(int x,int y,int num);
void initialize();
void show_time(int t);
#define GAME_FAILURE 0
#define GAME_RUNNING 1
#define GAME_RESTART 2
void main()
{
int i;
printf("行数 列数 雷数\n");
scanf("%d %d %d",&mine_line,&mine_row,&mine_number);
fflush(stdin);
while(1)
{
int t1=0L,t2=0L,t=0;
initialize();
Mouse_Click(t1,t2,t);
}
for (i=0; iint i;
initgraph(800,600);
size=30;
m_x=(getwidth()-mine_line*(size+1)-1)/2;
m_y=(getheight()-mine_row*(size+1)-1)/2;
p=(int **)malloc(sizeof(int *)*mine_row);
for(i=0;i*(p+i)=(int *)malloc(sizeof(int)*mine_line);
m_faceX=m_x+(mine_line*(size+1)-1)/2-size/2;
m_faceY=m_y-3-(2*(size+1))*3/4;
}
void draw_area(int w)
{
int x,y;
int i,j;
int width,heigh;
//总体
x=m_x-size;
y=m_y-size*2;
width=mine_line*(size+1)-1+size*2;
heigh=mine_row*(size+1)-1+size*3;
draw_box(x,y,width,heigh,1,0);
//放小格子的框
x=m_x-3;
y=m_y-3;
width=mine_line*(size+1)+3*2;
heigh=mine_row*(size+1)+3*2;
draw_box(x,y,width,heigh,1,3);
//左长方形小格
x=m_x;
y=m_y-3-(2*(size+1))*3/4;
draw_box(x,y+2,size*3,size,1,2);
//右长方形小格
x=m_x+(mine_line-3)*(size+1);
y=m_y-3-(2*(size+1))*3/4;
draw_box(x,y+2,size*3,size,1,2);
//小格子
y=m_y;
x=m_x;
for(i=0;ifor(j=0;jsize+1)*j,y+(size+1)*i,size,size,w,2);
}
}
void draw_box(int x,int y,int width,int heigh,int type,int depth)//画出每个小格深度之类的
{
int i;
setcolor(WHITE);
rectangle(x,y,x+width,y+heigh);
setfillstyle(BS_SOLID);
setfillcolor(LIGHTGRAY);
floodfill(x+width/2,y+heigh/2,WHITE);
if(0==depth)
{
setcolor(LIGHTGRAY);
rectangle(x,y,x+width,y+heigh);
return;
}
if(type==1) setcolor(DARKGRAY);
else if(type==2) setcolor(WHITE);
for(i=0;iif(type==1) setcolor(WHITE);
else if(type==2) setcolor(DARKGRAY);
for(i=0;iint mine_number)//布置雷
{
int i,j,count=0;
srand((unsigned)time(NULL));
for(i=0;ifor(j=0;j0;
while(countrand()%mine_row;
j=rand()%mine_line;
if(p[i][j]+1)
{
p[i][j]=-1;
count++;
}
}
}
void draw_mine(int x,int y)
{
x=x+size/2;
y=y+size/2+1;
setcolor(BLACK);
circle(x,y,size/3);
setfillstyle(BS_SOLID);
setfillcolor(BLACK);
floodfill(x,y,BLACK);
setfillcolor(BLACK);
floodfill(x,y,BLACK);
rectangle(x-size/10,y,x+size/10,y-size*4/10);
floodfill(x,y-size*4/10+1,BLACK);
}
void show_number(int x,int y,int number,int w)//每个格子里数字(雷数)颜色不同
{
char str[5];
if(number==0)
str[0]='\0';
else if(number<10)
{
str[0]=number+'0';
str[1]='\0';
}
else if(number<100)
{
str[0]=number/10+'0';
str[1]=number%10+'0';
str[2]='\0';
}
else if(number<1000)
{
str[0]=number/10+'0';
str[1]=number%10/10+'0';
str[2]=number%10+'0';
str[3]='\0';
}
draw_box(x,y,size,size,w,2);
settextstyle(size*2/3, size/2, _T("宋体"));
setbkmode(TRANSPARENT);
switch(number)
{
case 1:
setcolor(BLUE);
break;
case 2:
setcolor(GREEN);
break;
case 3:
setcolor(CYAN);
break;
case 4:
setcolor(RED);
break;
case 5:
setcolor(MAGENTA);
break;
case 6:
setcolor(YELLOW);
break;
case 7:
setcolor(WHITE);
break;
case 8:
setcolor(LIGHTGREEN);
break;
default:
setcolor(DARKGRAY);
break;
}
outtextxy(x+size/4,y+size/6,str);
}
void show_all_data()
{
int i,j;
draw_area(1);
for(i=0;ifor(j=0;jif(p[i][j]==-1)
draw_mine(m_x+(size+1)*j,m_y+(size+1)*i);
if(p[i][j]>=0&&p[i][j]<=8)
show_number(m_x+(size+1)*j,m_y+(size+1)*i,p[i][j],1);
}
}
void Around_mine_number()//判断每个格子周围雷的数量
{
int i,j;
for(i=0;ifor(j=0;jif(p[i][j]==-1)
continue;
if(i==0&&j==0)//左上角
{
if(p[i][j+1]==-1) p[i][j]++;
if(p[i+1][j+1]==-1) p[i][j]++;
if(p[i+1][j]==-1) p[i][j]++;
}
else if((j==mine_line-1)&&(i==0)) //右上角
{
if(p[i][j-1]==-1) p[i][j]++;
if(p[i+1][j]==-1) p[i][j]++;
if(p[i+1][j-1]==-1) p[i][j]++;
}
else if((i==mine_row-1)&&(j==0))//左下角
{
if(p[i][j+1]==-1) p[i][j]++;
if(p[i-1][j+1]==-1) p[i][j]++;
if(p[i-1][j]==-1) p[i][j]++;
}
else if((i==mine_row-1)&&(j==mine_line-1)) //右下角
{
if(p[i][j-1]==-1) p[i][j]++;
if(p[i-1][j]==-1) p[i][j]++;
if(p[i-1][j-1]==-1) p[i][j]++;
}
else if(i==0&&(j1&&j>0)) //上边
{
if(p[i][j-1]==-1) p[i][j]++;
if(p[i][j+1]==-1) p[i][j]++;
if(p[i+1][j]==-1) p[i][j]++;
if(p[i+1][j-1]==-1) p[i][j]++;
if(p[i+1][j+1]==-1) p[i][j]++;
}
else if((i==mine_row-1)&&(j1&&j>0))//下边
{
if(p[i][j+1]==-1) p[i][j]++;
if(p[i][j-1]==-1) p[i][j]++;
if(p[i-1][j]==-1) p[i][j]++;
if(p[i-1][j+1]==-1) p[i][j]++;
if(p[i-1][j-1]==-1) p[i][j]++;
}
else if((i1&&i>0)&&j==0) //左边
{
if(p[i][j+1]==-1) p[i][j]++;
if(p[i-1][j]==-1) p[i][j]++;
if(p[i-1][j+1]==-1) p[i][j]++;
if(p[i+1][j]==-1) p[i][j]++;
if(p[i+1][j+1]==-1) p[i][j]++;
}
else if((i1&&i>0)&&j==mine_line-1) //右边
{
if(p[i][j-1]==-1) p[i][j]++;
if(p[i+1][j]==-1) p[i][j]++;
if(p[i+1][j-1]==-1) p[i][j]++;
if(p[i-1][j]==-1) p[i][j]++;
if(p[i-1][j-1]==-1) p[i][j]++;
}
else
{
if(p[i][j+1]==-1) p[i][j]++;
if(p[i][j-1]==-1) p[i][j]++;
if(p[i+1][j]==-1) p[i][j]++;
if(p[i+1][j+1]==-1) p[i][j]++;
if(p[i+1][j-1]==-1) p[i][j]++;
if(p[i-1][j]==-1) p[i][j]++;
if(p[i-1][j+1]==-1) p[i][j]++;
if(p[i-1][j-1]==-1) p[i][j]++;
}
}
}
void Mouse_Click(unsigned int t1,unsigned int t2,int t)//鼠标操作
{
int state;
int x,y;
MOUSEMSG mouse;
while(1)
{
t1 = time(NULL);
if(t1!=t2)
{
if(STATE==1)
{
if(t<999)
t++;
show_time(t);
t2=t1;
}
}
if(!MouseHit())
continue;
show_mine_number();
mouse=GetMouseMsg();
x=m_x+mine_line*(size+1)-1;
y=m_y+mine_row*(size+1)-1;
Mouse_Move(&mouse);
switch(mouse.uMsg)
{
case WM_LBUTTONDOWN : //鼠标左键
state=Mouse_Click_left(&mouse);
break;
case WM_RBUTTONDOWN :
Mouse_Click_right(&mouse);
break;
}
if(m_marked+m_digged==mine_row*mine_line&&m_marked==mine_number)
{
show_game("SUCCESSFUL!");
getch();
break;
}
if(state==GAME_FAILURE)
{
show_game("FAILURE!");
getch();
break;
}
if(state==GAME_RESTART)
break;
}
}
int Mouse_Click_left(MOUSEMSG *mouse)//鼠标左键,挖雷
{
int x,y;
int i,j;
int state;
x=m_x+mine_line*(size+1)-1;
y=m_y+mine_row*(size+1)-1;
if(x>=(mouse->x)&&(mouse->x)>=m_x&&(mouse->y)<=y&&(mouse->y)>=m_y)
{
STATE=1;
cal_dig_mine(mouse->x,mouse->y,&i,&j);
state=dig_mine(i,j);
return state;
}
x=m_faceX+size*4/3;
y=m_faceY+size*4/3;
if((mouse->x)>m_faceX&&(mouse->x)mouse->y)mouse->y)>m_faceY)
{
draw_box(m_faceX,m_faceY,size*4/3,size*4/3,0,1);
smile_face();
state=GAME_RESTART;
return state;
}
}
int dig_mine(int i,int j)//开挖
{
if(p[i][j]==-1)
{
int i,j;
for(i=0;ifor(j=0;jif(p[i][j]==-1)
{
draw_box(m_x+(size+1)*j,m_y+(size+1)*i,size,size,1,2);
draw_mine(m_x+(size+1)*j,m_y+(size+1)*i);
}
return GAME_FAILURE;
}
else if(08)
{
show_number(m_x+(size+1)*j,m_y+(size+1)*i,p[i][j],1);
p[i][j]+=10;
m_digged++;
return GAME_RUNNING;
}
else if(p[i][j]==0)
{
draw_box(m_x+(size+1)*j,m_y+(size+1)*i,size,size,1,2);
p[i][j]+=10;
m_digged++;
dig_mine1(i,j);
}
return GAME_RUNNING;
}
void cal_dig_mine(int x,int y,int *i,int *j)
{
*i=(y-m_y)/(size+1);
*j=(x-m_x)/(size+1);
}
void dig_mine1(int i,int j)//挖雷
{
dig_mine2(i,j-1);
dig_mine2(i,j+1);
dig_mine2(i+1,j);
dig_mine2(i+1,j+1);
dig_mine2(i+1,j-1);
dig_mine2(i-1,j);
dig_mine2(i-1,j+1);
dig_mine2(i-1,j-1);
}
void dig_mine2(int i,int j)
{
if(0>i||i>=mine_row)
return;
if(0>j&&j>=mine_line)
return;
dig_mine(i,j);
}
void draw_flag(int i,int j)//画标记小红旗
{
int depth;
setcolor(RED);
line(m_x+(size+1)*j+size*3/8,m_y+(size+1)*i+size/8,m_x+(size+1)*j+size*6/8,m_y+(size+1)*i+size*5/8);
line(m_x+(size+1)*j+size*3/8,m_y+(size+1)*i+size/8,m_x+(size+1)*j+size*3/8,m_y+(size+1)*i+size*5/8);
line(m_x+(size+1)*j+size*3/8,m_y+(size+1)*i+size*5/8,m_x+(size+1)*j+size*6/8,m_y+(size+1)*i+size*5/8);
setfillstyle(BS_SOLID);
setfillcolor(RED);
floodfill(m_x+(size+1)*j+size*3/8+1,m_y+(size+1)*i+size/8+3,RED);
setcolor(BLACK);
for(depth=0;depth<2;depth++)
line(m_x+(size+1)*j+size*3/8-depth,m_y+(size+1)*i+size/8,m_x+(size+1)*j+size*3/8-depth,m_y+(size+1)*i+size*7/8);
}
void Mouse_Click_right(MOUSEMSG *mouse)//鼠标右键
{
int x,y;
int i,j;
x=m_x+mine_line*(size+1)-1;
y=m_y+mine_row*(size+1)-1;
if(x>=(mouse->x)&&(mouse->x)>=m_x&&(mouse->y)<=y&&(mouse->y)>=m_y)
{
cal_dig_mine(mouse->x,mouse->y,&i,&j);
put_flag(i,j);
}
}
void put_flag(int i,int j)//鼠标右键的标记功能
{
if(p[i][j]>=-1&&p[i][j]<=8)
{
draw_flag(i,j);
p[i][j]+=20;
m_marked++;
return ;
}
if(p[i][j]>=19&&p[i][j]<=28)
{
p[i][j]-=20;
draw_box(m_x+(size+1)*j,m_y+(size+1)*i,size,size,2,2);
m_marked--;
return ;
}
}
void show_game(char str[])//显示输赢 成功或失败
{
int x,y;
settextstyle(2*size, size, _T("宋体"));
setcolor(RED);
x=mine_line*(size+1)-1-textwidth(str);
y=mine_row*(size+1)-1-textheight(str);
x=x/2+m_x;
y=y/2+m_y;
outtextxy(x+size/4,y+size/6,str);
}
void smile_face() //绘制笑脸
{
int x,y;
x=m_faceX+size*2/3;
y=m_faceY+size*2/3;
setcolor(RED);
circle(x,y,size*2/3);
line(x-size/3,y-size/4,x-size/6,y-size/4);
line(x+size/6,y-size/4,x+size/3,y-size/4);
line(x-size/6,y+size/4,x+size/6,y+size/4);
}
void Mouse_Move(MOUSEMSG *mouse)//鼠标移动 移动到指定位置会变化
{
int x,y;
x=m_faceX+size*4/3;
y=m_faceY+size*4/3;
if((mouse->x)>m_faceX&&(mouse->x)mouse->y)mouse->y)>m_faceY)
{
draw_box(m_faceX,m_faceY,size*4/3,size*4/3,2,1);
smile_face();
}
else
{
draw_box(m_faceX,m_faceY,size*4/3,size*4/3,0,0);
smile_face();
}
}
void show_mine_number()//显示雷个数的边框
{
int x,y,width,heigh;
x=m_x;
y=m_y-(2*(size+1))*3/4;
width=size*3;
heigh=size;
draw_box(x,y,width,heigh,1,2);
show_Minenumber(x,y,mine_number-m_marked);
}
void show_Minenumber(int x,int y,int num)//显示雷个数的字体
{
char str[6];
int i=0;
if(num>=10000)
return;
if(num<0)
{
str[i++]='-';
num=-num;
}
if(num>=1000)
{
str[i++]=num/1000+48;
num=num%1000;
}
if(num>=100)
{
str[i++]=num/100+48;
num=num%100;
}
if(num>=10)
{
str[i++]=num/10+48;
num=num%10;
}
str[i++]=num+48;
str[i]='\0';
settextstyle(size*2/3, size/2, _T("宋体"));
setcolor(RED);
setbkmode(TRANSPARENT);
outtextxy(x+size/4,y+size/6,str);
}
void initialize()//初始化
{
STATE=0;
graph();
m_marked=0;
m_digged=0;
draw_area(2);
smile_face();
lay_mine(mine_number);
Around_mine_number();
}
void show_time(int t)//显示时间
{
int x,y,width,heigh;
x=m_x+(mine_line-3)*(size+1);;
y=m_y-3-(2*(size+1))*3/4+1;
width=size*3;
heigh=size;
draw_box(x,y,width,heigh,1,2);
show_Minenumber(x,y,t);
}
点击笑脸,没有实现凹下去。。sorry
可以在添加个按键,实现未标识的方块是否有地雷的概率~~~