#include <time.h>
#include <conio.h>
/************************************************************************/
/* 地图状态约定*/
/* 0 : 周围9个格子都没有雷*/
/* 1~8: 周围9个格子有1~8个雷 */则茄拍
/* -1 : 有雷的格子 */
/* -2 : 被翻开的有雷的格子 */
/* -3 : 地图边界 */
/************************************************************************/
int Map[12][12]={0} /* 当前在玩的雷图 */
int MapShow[12][12]={0} /* 当前用户选择过的地方孙羡,即“已翻开”的格子 */
int nSpaceLeft = 100 /* 剩余的空白数,如果为0,则任务成功! */
int lastX,lastY /* 失败时,记录挖到雷的位置 */
int AllMaps[5][12][12]={0}/* 供用户选择的五张雷图 */
/* 显示雷区(每次用户 *** 作之后都要重新显示) */
void DrawMap()
/* 初始化雷区 */
void InitMap()
/* 游戏开始时,加载用户选择的一幅雷图 */
void LoadMap(int index)
/* 玩扫雷游戏 */
int Play()
/* 绘制主菜单 */
void DrawMainMenu()
/* 显示结果 */
void ShowResult(int result)
/* 主函数 */
int main(int argc, char* argv[])
{
char ch
int result
srand(time(NULL))/* 按当前时间初始化随机数,这样每次启动的时候,雷的位置的不一样 */
InitMap()/* 初始化5张雷图,供用户选择 */
while(1) /* 用while循环,保证只有在用户选择退出时,才退出游戏 */
{
DrawMainMenu() /* 绘制主菜单 */
flushall() /* 清空所有输入输出缓冲区,纳吵主要是清空输入缓冲区,防止前面的输入对getch()的干扰 */
ch = getch() /* 读取输入 */
switch(ch)
{
case '1': /* 用户选择1 */
printf("\n\t请输入雷图编号(1-5):")
while (1) /* 循环输入,如果输入错误就一直要求输入 */
{
flushall()
ch = getch()/* 读取用户输入的雷图编号 */
if (ch >= '1' &&ch <= '5') /* 只有在1-5之间有效 */
{
LoadMap(ch-'1')/* ch -'1',将用户输入转换为雷图下标(下标从0开始,所以是-'1')*/
break /* 如果输入正确,就退出循环输入 */
}
else
{
/* 输入错误,则提示重新输入 */
printf("\n\t输入无效!请重新输入雷图编号(1-5):")
flushall()
}
}
result = Play() /* 开始玩扫雷游戏 */
ShowResult(result)/* 显示游戏结果 */
break
case '2': /* 用户选择2 */
exit(0) /* 直接退出 */
break
default: /* 无效输入 */
/* 不做任何 *** 作,重新显示主菜单 */
break
}
}
return 0
}
void LoadMap(int index)
{
int i,j
nSpaceLeft = 90
for(i=0i<12i++)
for(j=0j<12j++)
{
Map[i][j] = AllMaps[index][i][j]/* 将5张雷图中的下标为index的那一张载入到Map数组 */
MapShow[i][j] = 0 /* 重新开始游戏,所以所有格子都是“未翻开”状态 */
}
}
void InitMap()
{
int i,j,k
int m,n
/* 要初始化5张地图 */
for(k=0k<5k++)
{
/* 初始化地图的边界 */
for(i=0i<12i++)
{
/* 下标为0和11的位置都是“边界”,这些位置不属于雷区,仅在程序内部使用 */
AllMaps[k][0][i] = -3
AllMaps[k][11][i] = -3
AllMaps[k][i][0] = -3
AllMaps[k][i][11] = -3
}
/* 先初始化10个雷的位置 */
for(i=0i<10i++)
{
m = rand()%10 + 1/* 随机选一个X坐标 */
n = rand()%10 + 1/* 随机选一个Y坐标 */
if(AllMaps[k][m][n] == 0) /* 如果随机产生的位置之前没有被安排放置雷 */
{
AllMaps[k][m][n] = -1/* 放置一个雷 */
}
else /* 随机产生的位置在之前已经放置了雷了 */
{
i--/* 这个位置无效,重新产生一个 */
}
}
/* 计算每个格子周围雷的个数 */
for(i=1i<11i++)
for(j=1j<11j++)
{
if(AllMaps[k][i][j] != -1)
{
AllMaps[k][i][j] = 0
/* 周围的8个位置,有一个雷就加一 */
/************************************************************************/
/* 坐标[i][j]周围的8个坐标位置: */
/* [i-1][j-1] [i-1][j] [i-1][j+1] */
/* [i][j-1] [i][j][i][j+1] */
/* [i+1][j-1] [i+1][j] [i+1][j+1] */
/************************************************************************/
if(AllMaps[k][i-1][j-1] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i-1][j] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i-1][j+1] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i][j-1] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i][j+1] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i+1][j-1] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i+1][j] == -1)
AllMaps[k][i][j]++
if(AllMaps[k][i+1][j+1] == -1)
AllMaps[k][i][j]++
}
}
}
}
void DrawMap()
{
int i,j
system("cls") /* 清屏 */
/* 绘制坐标和边框 */
printf("\n\n\n")
printf("\t Y ")
for(i=1i<11i++) printf("%-02d",i-1)
printf("\n\tX |###################|\n")
/* 每一行按规则绘制雷区 */
for(i=1i<11i++)
{
printf("\t%-02d|",i-1)/* 显示X坐标 */
for(j=1j<11j++)
{
if(MapShow[i][j]) /* 如果该位置被用户“挖开”了,就照实显示 */
{
if (Map[i][j] >= 0) /* 非雷,显示周围雷的个数 */
{
printf("%d|",Map[i][j])
}
/*else if(Map[i][j] == 0)
{
printf("0|")
}*/
else if (Map[i][j] == -1) /* 雷,显示* */
{
printf("*|")
}
else if (Map[i][j] == -2) /* 用户挖到的雷,显示@ */
{
printf("@|")
}
else /* 其他情况(目前不会出现,方便以后扩展) */
{
printf(" |")
}
}
else /* 如果该位置没有被用户“挖开”,则显示空格 */
{
printf(" |")
}
}
printf("\n")
}
printf("\t |###################|\n")
}
void DrawMainMenu()
{
system("cls")
printf("\n\n\n\n\n\n")
printf("\t|###################|\n")
printf("\t| 请选择! |\n")
printf("\t|1. 开始扫雷|\n")
printf("\t|2. 退出|\n")
printf("\t|###################|\n")
}
int Play()
{
char chX,chY/* 用户输入 */
int X,Y/* 用户输入转换为整数下标 */
int i,j
while (1)
{
DrawMap() /* 重新绘制雷区图 */
/* 输入X坐标 */
printf("\n\t请输入X:")
flushall()
while(1)
{
chX = getch()
if (chX >= '0' &&chX <= '9')
{
X = chX - '0' + 1
break
}
else
{
printf("\n\t输入无效!请重新输入X:")
flushall()
}
}
/* 输入Y坐标 */
printf("\n\t请输入Y:")
flushall()
while(1)
{
chY = getch()
if (chY >= '0' &&chY <= '9')
{
Y = chY - '0' + 1
break
}
else
{
printf("\n\t输入无效!请重新输入Y:")
flushall()
}
}
if(MapShow[X][Y] == 0) /* 输入的是未翻开的位置 */
{
MapShow[X][Y] = 1 /* 将该位置标记为“已翻开” */
if(Map[X][Y] == -1) /* 如果挖到的是雷 */
{
Map[X][Y] = -2 /* 标记为-2,表示这是被用户挖到的雷 */
for(i=1i<11i++)
for(j=1j<11j++)
MapShow[i][j]=1/* 游戏结束,自动将所有位置“翻开” */
/* 记录用户挖到雷的位置坐标 */
lastX = X-1
lastY = Y-1
return 0/* 游戏失败! */
}
else /* 如果挖到的不是雷 */
{
nSpaceLeft-- /* 剩余空白数减一 */
if(nSpaceLeft==0) /* 剩余空白数为0,则表示游戏成功 */
{
return 1/* 游戏胜利! */
}
}
}
else /* 输入的是已翻开的位置 */
{
printf("\n\t你输入的位置是[%d,%d]\n\t这个位置已经翻开!请重新输入!\n\t按任意键继续...\n",X-1,Y-1)
flushall()
getch()
}
}
}
void ShowResult( int result )
{
DrawMap()
if(result == 1) /* 游戏成功 */
{
printf("\n\t恭喜!您完成的扫雷任务!\n\t按任意键继续...")
flushall()
getch()
}
else /* 游戏失败 */
{
printf("\n\t哈哈!您在位置[%d,%d]挖到雷了,任务失败!\n\t按任意键继续...",lastX, lastY)
flushall()
getch()
}
}
源代码#include <graphics.h>#include <stdlib.h>
#include <dos.h>
#define LEFTPRESS 0xff01
#define LEFTCLICK 0xff10
#define LEFTDRAG 0xff19
#define MOUSEMOVE 0xff08
struct
{
int num/*格子当前处于什么状态,1有雷,0已经显示过数字或者空白格子*/
int roundnum/*统计格子周围有多少雷*/
int flag/*右键按下显示红旗的标志,0没有红旗标志,1有红旗标志*/
}Mine[10][10]
int gameAGAIN=0/*是否重来的变量*/
int gamePLAY=0/*是否是第一次玩游戏的标志*/
int mineNUM/*统计处理过的格子数*/
char randmineNUM[3]/*显示数字的字符串*/
int Keystate
int MouseExist
int MouseButton
int MouseX
int MouseY
void Init(void)/*图形驱动*/
void MouseOn(void)/*鼠标光标显示*/
void MouseOff(void)/*鼠标光标隐藏*/
void MouseSetXY(int,int)/*设置当前位置*/
int LeftPress(void)/*左键按下*/
int RightPress(void)/*鼠标右键按下*/
void MouseGetXY(void)/*得到当前位置*/
void Control(void)/*游戏开始,重新,关闭*/
void GameBegain(void)/*游戏开始画面*/
void DrawSmile(void)/*画笑脸*/
void DrawRedflag(int,int)/*显示红旗*/
void DrawEmpty(int,int,int,int)/*两种空格子的显示*/
void GameOver(void)/*游戏结束*/
void GameWin(void)/*显示扰滚胜利*/
int MineStatistics(int,int)/*统计每个格子周围的雷数*/侍袜
int ShowWhite(int,int)/*显示无雷区的空白部分*/
void GamePlay(void)/*游戏过程*/
void Close(void)/*图形关闭*/
void main(void)
{
Init()
Control()
Close()
}
void Init(void)/*图形开始*/
{
int gd=DETECT,gm
initgraph(&gd,&gm,"c:\\program files\\winyes\\tc20h\\bgi")
}
void Close(void)/*图形关闭*/
{
closegraph()
}
void MouseOn(void)/*鼠标光标显示*/
{
_AX=0x01
geninterrupt(0x33)
}
void MouseOff(void)/*鼠标光标隐藏*/
{
_AX=0x02
geninterrupt(0x33)
}
void MouseSetXY(int x,int y)/*设置当前位置*/
{
_CX=x
_DX=y
_AX=0x04
geninterrupt(0x33)
}
int LeftPress(void)/*鼠标左键按下*/
{
_AX=0x03
geninterrupt(0x33)
return(_BX&1)
}
int RightPress(void)/*鼠标右键按下*/
{
_AX=0x03
geninterrupt(0x33)
return(_BX&2)
}
void MouseGetXY(void)/*得到当前位置*/
{
_AX=0x03
geninterrupt(0x33)
MouseX=_CX
MouseY=_DX
}
void Control(void)/*游戏开始,重新,关闭*/
{
int gameFLAG=1/*游戏失败后判断是否重新开始的老李激标志*/
while(1)
{
if(gameFLAG)/*游戏失败后没判断出重新开始或者退出游戏的话就继续判断*/
{
GameBegain()/*游戏初始画面*/
GamePlay()/*具体游戏*/
if(gameAGAIN==1)/*游戏中重新开始*/
{
gameAGAIN=0
continue
}
}
MouseOn()
gameFLAG=0
if(LeftPress())/*判断是否重新开始*/
{
MouseGetXY()
if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)
{
gameFLAG=1
continue
}
}
if(kbhit())/*判断是否按键退出*/
break
}
MouseOff()
}
void DrawSmile(void)/*画笑脸*/
{
setfillstyle(SOLID_FILL,YELLOW)
fillellipse(290,75,10,10)
setcolor(YELLOW)
setfillstyle(SOLID_FILL,BLACK)/*眼睛*/
fillellipse(285,75,2,2)
fillellipse(295,75,2,2)
setcolor(BLACK)/*嘴巴*/
bar(287,80,293,81)
}
void DrawRedflag(int i,int j)/*显示红旗*/
{
setcolor(7)
setfillstyle(SOLID_FILL,RED)
bar(198+j*20,95+i*20,198+j*20+5,95+i*20+5)
setcolor(BLACK)
line(198+j*20,95+i*20,198+j*20,95+i*20+10)
}
void DrawEmpty(int i,int j,int mode,int color)/*两种空格子的显示*/
{
setcolor(color)
setfillstyle(SOLID_FILL,color)
if(mode==0)/*没有单击过的大格子*/
bar(200+j*20-8,100+i*20-8,200+j*20+8,100+i*20+8)
else
if(mode==1)/*单击过后显示空白的小格子*/
bar(200+j*20-7,100+i*20-7,200+j*20+7,100+i*20+7)
}
void GameBegain(void)/*游戏开始画面*/
{
int i,j
cleardevice()
if(gamePLAY!=1)
{
MouseSetXY(290,70)/*鼠标一开始的位置,并作为它的初始坐标*/
MouseX=290
MouseY=70
}
gamePLAY=1/*下次按重新开始的话鼠标不重新初始化*/
mineNUM=0
setfillstyle(SOLID_FILL,7)
bar(190,60,390,290)
for(i=0i<10i++)/*画格子*/
for(j=0j<10j++)
DrawEmpty(i,j,0,8)
setcolor(7)
DrawSmile()/*画脸*/
randomize()
for(i=0i<10i++)/*100个格子随机赋值有没有地雷*/
for(j=0j<10j++)
{
Mine[i][j].num=random(8)/*如果随机数的结果是1表示这个格子有地雷*/
if(Mine[i][j].num==1)
mineNUM++/*现有雷数加1*/
else
Mine[i][j].num=2
Mine[i][j].flag=0/*表示没红旗标志*/
}
sprintf(randmineNUM,"%d",mineNUM)/*显示这次总共有多少雷数*/
setcolor(1)
settextstyle(0,0,2)
outtextxy(210,70,randmineNUM)
mineNUM=100-mineNUM/*变量取空白格数量*/
MouseOn()
}
void GameOver(void)/*游戏结束画面*/
{
int i,j
setcolor(0)
for(i=0i<10i++)
for(j=0j<10j++)
if(Mine[i][j].num==1)/*显示所有的地雷*/
{
DrawEmpty(i,j,0,RED)
setfillstyle(SOLID_FILL,BLACK)
fillellipse(200+j*20,100+i*20,7,7)
}
}
void GameWin(void)/*显示胜利*/
{
setcolor(11)
settextstyle(0,0,2)
outtextxy(230,30,"YOU WIN!")
}
int MineStatistics(int i,int j)/*统计每个格子周围的雷数*/
{
int nNUM=0
if(i==0&&j==0)/*左上角格子的统计*/
{
if(Mine[0][1].num==1)
nNUM++
if(Mine[1][0].num==1)
nNUM++
if(Mine[1][1].num==1)
nNUM++
}
else
if(i==0&&j==9)/*右上角格子的统计*/
{
if(Mine[0][8].num==1)
nNUM++
if(Mine[1][9].num==1)
nNUM++
if(Mine[1][8].num==1)
nNUM++
}
else
if(i==9&&j==0)/*左下角格子的统计*/
{
if(Mine[8][0].num==1)
nNUM++
if(Mine[9][1].num==1)
nNUM++
if(Mine[8][1].num==1)
nNUM++
}
else
if(i==9&&j==9)/*右下角格子的统计*/
{
if(Mine[9][8].num==1)
nNUM++
if(Mine[8][9].num==1)
nNUM++
if(Mine[8][8].num==1)
nNUM++
}
else if(j==0)/*左边第一列格子的统计*/
{
if(Mine[i][j+1].num==1)
nNUM++
if(Mine[i+1][j].num==1)
nNUM++
if(Mine[i-1][j].num==1)
nNUM++
if(Mine[i-1][j+1].num==1)
nNUM++
if(Mine[i+1][j+1].num==1)
nNUM++
}
else if(j==9)/*右边第一列格子的统计*/
{
if(Mine[i][j-1].num==1)
nNUM++
if(Mine[i+1][j].num==1)
nNUM++
if(Mine[i-1][j].num==1)
nNUM++
if(Mine[i-1][j-1].num==1)
nNUM++
if(Mine[i+1][j-1].num==1)
nNUM++
}
else if(i==0)/*第一行格子的统计*/
{
if(Mine[i+1][j].num==1)
nNUM++
if(Mine[i][j-1].num==1)
nNUM++
if(Mine[i][j+1].num==1)
nNUM++
if(Mine[i+1][j-1].num==1)
nNUM++
if(Mine[i+1][j+1].num==1)
nNUM++
}
else if(i==9)/*最后一行格子的统计*/
{
if(Mine[i-1][j].num==1)
nNUM++
if(Mine[i][j-1].num==1)
nNUM++
if(Mine[i][j+1].num==1)
nNUM++
if(Mine[i-1][j-1].num==1)
nNUM++
if(Mine[i-1][j+1].num==1)
nNUM++
}
else/*普通格子的统计*/
{
if(Mine[i-1][j].num==1)
nNUM++
if(Mine[i-1][j+1].num==1)
nNUM++
if(Mine[i][j+1].num==1)
nNUM++
if(Mine[i+1][j+1].num==1)
nNUM++
if(Mine[i+1][j].num==1)
nNUM++
if(Mine[i+1][j-1].num==1)
nNUM++
if(Mine[i][j-1].num==1)
nNUM++
if(Mine[i-1][j-1].num==1)
nNUM++
}
return(nNUM)/*把格子周围一共有多少雷数的统计结果返回*/
}
int ShowWhite(int i,int j)/*显示无雷区的空白部分*/
{
if(Mine[i][j].flag==1||Mine[i][j].num==0)/*如果有红旗或该格处理过就不对该格进行任何判断*/
return
mineNUM--/*显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利*/
if(Mine[i][j].roundnum==0&&Mine[i][j].num!=1)/*显示空格*/
{
DrawEmpty(i,j,1,7)
Mine[i][j].num=0
}
else
if(Mine[i][j].roundnum!=0)/*输出雷数*/
{
DrawEmpty(i,j,0,8)
sprintf(randmineNUM,"%d",Mine[i][j].roundnum)
setcolor(RED)
outtextxy(195+j*20,95+i*20,randmineNUM)
Mine[i][j].num=0/*已经输出雷数的格子用0表示已经用过这个格子*/
return
}
/*8个方向递归显示所有的空白格子*/
if(i!=0&&Mine[i-1][j].num!=1)
ShowWhite(i-1,j)
if(i!=0&&j!=9&&Mine[i-1][j+1].num!=1)
ShowWhite(i-1,j+1)
if(j!=9&&Mine[i][j+1].num!=1)
ShowWhite(i,j+1)
if(j!=9&&i!=9&&Mine[i+1][j+1].num!=1)
ShowWhite(i+1,j+1)
if(i!=9&&Mine[i+1][j].num!=1)
ShowWhite(i+1,j)
if(i!=9&&j!=0&&Mine[i+1][j-1].num!=1)
ShowWhite(i+1,j-1)
if(j!=0&&Mine[i][j-1].num!=1)
ShowWhite(i,j-1)
if(i!=0&&j!=0&&Mine[i-1][j-1].num!=1)
ShowWhite(i-1,j-1)
}
void GamePlay(void)/*游戏过程*/
{
int i,j,Num/*Num用来接收统计函数返回一个格子周围有多少地雷*/
for(i=0i<10i++)
for(j=0j<10j++)
Mine[i][j].roundnum=MineStatistics(i,j)/*统计每个格子周围有多少地雷*/
while(!kbhit())
{
if(LeftPress())/*鼠标左键盘按下*/
{
MouseGetXY()
if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)/*重新来*/
{
MouseOff()
gameAGAIN=1
break
}
if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/
{
j=(MouseX-190)/20/*x坐标*/
i=(MouseY-90)/20/*y坐标*/
if(Mine[i][j].flag==1)/*如果格子有红旗则左键无效*/
continue
if(Mine[i][j].num!=0)/*如果格子没有处理过*/
{
if(Mine[i][j].num==1)/*鼠标按下的格子是地雷*/
{
MouseOff()
GameOver()/*游戏失败*/
break
}
else/*鼠标按下的格子不是地雷*/
{
MouseOff()
Num=MineStatistics(i,j)
if(Num==0)/*周围没地雷就用递归算法来显示空白格子*/
ShowWhite(i,j)
else/*按下格子周围有地雷*/
{
sprintf(randmineNUM,"%d",Num)/*输出当前格子周围的雷数*/
setcolor(RED)
outtextxy(195+j*20,95+i*20,randmineNUM)
mineNUM--
}
MouseOn()
Mine[i][j].num=0/*点过的格子周围雷数的数字变为0表示这个格子已经用过*/
if(mineNUM<1)/*胜利了*/
{
GameWin()
break
}
}
}
}
}
if(RightPress())/*鼠标右键键盘按下*/
{
MouseGetXY()
if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*当前鼠标位置在格子范围内*/
{
j=(MouseX-190)/20/*x坐标*/
i=(MouseY-90)/20/*y坐标*/
MouseOff()
if(Mine[i][j].flag==0&&Mine[i][j].num!=0)/*本来没红旗现在显示红旗*/
{
DrawRedflag(i,j)
Mine[i][j].flag=1
}
else
if(Mine[i][j].flag==1)/*有红旗标志再按右键就红旗消失*/
{
DrawEmpty(i,j,0,8)
Mine[i][j].flag=0
}
}
MouseOn()
sleep(1)
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)