- 注册时间
- 2006-7-15
- 最后登录
- 1970-1-1
|
最近学C语言,拿Lava练手编了个扫雷.
不知道是递归快还是回溯快?
(本帖公布的代码供学习用,允许任何人转载.)
递归代码如下:- //=======================
- //= 程序:挖地雷 =
- //= 核心算法:递归 =
- //= 作者:闫茂源 =
- //= 地点:HB.JM.龙泉中学 =
- //= 时间:2006/12/17 =
- //=======================
- #define FALSE 0
- #define TURE 1
- #define SMILE 1
- #define OU 2
- #define LAUGH 3
- #define SAD 4
- #define MARK 9
- #define CROSS 10
- #define BLACK 11
- #define MINE 12
- #define ENTER 13
- #define KPD 14
- #define KPU 19
- #define KU 20
- #define KD 21
- #define KR 22
- #define KL 23
- #define KH 25
- #define ESC 27
- #define KF1 28
- #define KSP 32
- /*字符数据 0123456789*/
- char number_0[]={0x3C,0x42,0x42,0x42,0x42,0x00,0x42,0x42,0x42,0x42,0x3C};
- char number_1[]={0x00,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x00};
- char number_2[]={0x3C,0x02,0x02,0x02,0x02,0x3C,0x40,0x40,0x40,0x40,0x3C};
- char number_3[]={0x3C,0x02,0x02,0x02,0x02,0x3C,0x02,0x02,0x02,0x02,0x3C};
- char number_4[]={0x00,0x42,0x42,0x42,0x42,0x3C,0x02,0x02,0x02,0x02,0x00};
- char number_5[]={0x3C,0x40,0x40,0x40,0x40,0x3C,0x02,0x02,0x02,0x02,0x3C};
- char number_6[]={0x3C,0x40,0x40,0x40,0x40,0x3C,0x42,0x42,0x42,0x42,0x3C};
- char number_7[]={0x3C,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x00};
- char number_8[]={0x3C,0x42,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x42,0x3C};
- char number_9[]={0x3C,0x42,0x42,0x42,0x42,0x3C,0x02,0x02,0x02,0x02,0x3C};
- /*左侧表情数据*/
- char face_smile[]={0x07,0xF0,0x08,0x08,0x10,0x04,0x20,0x02,0x20,0x02,0x40,0x01,0x4C,0x19,0x40,0x01,0x40,0x01,0x40,0x01,0x22,0x22,0x21,0xC2,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00};
- char face_ou[]={0x07,0xF0,0x08,0x08,0x10,0x04,0x20,0x02,0x20,0x02,0x40,0x01,0x4C,0x19,0x4C,0x19,0x40,0x01,0x40,0x01,0x21,0xC2,0x22,0x22,0x11,0xC4,0x08,0x08,0x07,0xF0,0x00,0x00};
- char face_laugh[]={0x07,0xF0,0x08,0x08,0x10,0x04,0x20,0x02,0x20,0x02,0x4F,0xF9,0x5F,0x7D,0x6E,0x3B,0x40,0x01,0x40,0x01,0x20,0x02,0x24,0x12,0x13,0xE4,0x08,0x08,0x07,0xF0,0x00,0x00};
- char face_sad[]={0x07,0xF0,0x08,0x08,0x10,0x04,0x20,0x02,0x20,0x02,0x4A,0x29,0x44,0x11,0x4A,0x29,0x40,0x01,0x40,0x01,0x21,0xC2,0x22,0x22,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00};
- /*雷区图形数据*/
- char pic_blank[]={0xA8,0x50,0xA8,0x50,0xA8};
- char pic_black[]={0xF8,0xF8,0xF8,0xF8,0xF8};
- char pic_mine[]={0xA8,0x70,0xF8,0x70,0xA8};
- char pic_mark[]={0x00,0x08,0x10,0xA0,0x40};
- char pic_cross[]={0x88,0x50,0x20,0x50,0x88};
- char pic_1[]={0x20,0x20,0x20,0x20,0x20};
- char pic_2[]={0x70,0x10,0x70,0x40,0x70};
- char pic_3[]={0x70,0x10,0x70,0x10,0x70};
- char pic_4[]={0x50,0x50,0x70,0x10,0x10};
- char pic_5[]={0x70,0x40,0x70,0x10,0x70};
- char pic_6[]={0x70,0x40,0x70,0x50,0x70};
- char pic_7[]={0x70,0x10,0x10,0x10,0x10};
- char pic_8[]={0x70,0x50,0x70,0x50,0x70};
- /*热线帮助数据*/
- char HELP[]={"***** 热线帮助 *****====== 挖地雷 ====== --= 规则 =-- 把所有没有地雷的方块挖开则胜;挖到地雷则失败;被挖开方块上的数字表示附近方块中地雷的数目。 --= 游戏界面 =-- 分隔线右边是雷区,左上角显示游戏难度和剩余未标记的数目,左下角为时间。 --= 按键功能 =-- <><><><>移动光标<输入>挖开一个方块 <空格>标记一个方块 <> 连续挖开多个方块<F1>重新开局 --= 声明 =-- 作者:Windy.Bell 日期:2006/12/16 QQ:115150813 = All rights left! ="};
- /*声明全局变量*/
- int Map[21][13];
- int sum,mark;
- /*把数字(8*11)写到缓存坐标 x,y 处*/
- void ShowNumber(int x,int y,int n)
- {
- if(n==0)WriteBlock(x,y,8,11,0,number_0);
- if(n==1)WriteBlock(x,y,8,11,0,number_1);
- if(n==2)WriteBlock(x,y,8,11,0,number_2);
- if(n==3)WriteBlock(x,y,8,11,0,number_3);
- if(n==4)WriteBlock(x,y,8,11,0,number_4);
- if(n==5)WriteBlock(x,y,8,11,0,number_5);
- if(n==6)WriteBlock(x,y,8,11,0,number_6);
- if(n==7)WriteBlock(x,y,8,11,0,number_7);
- if(n==8)WriteBlock(x,y,8,11,0,number_8);
- if(n==9)WriteBlock(x,y,8,11,0,number_9);
- }
- /*将表情(16*16)写到缓存坐标 8,32 处*/
- void Face(int type)
- {
- if(type==SMILE)WriteBlock(8,32,16,16,0,face_smile);
- if(type==OU)WriteBlock(8,32,16,16,0,face_ou);
- if(type==LAUGH)WriteBlock(8,32,16,16,0,face_laugh);
- if(type==SAD)WriteBlock(8,32,16,16,0,face_sad);
- }
- /*把图片(5*5)写到缓存*/
- void ShowPic(int x,int y,int type)
- {
- x=x*6+34;
- y=y*6+2;
- if(type==0)WriteBlock(x,y,5,5,0,pic_blank);
- if(type==1)WriteBlock(x,y,5,5,0,pic_1);
- if(type==2)WriteBlock(x,y,5,5,0,pic_2);
- if(type==3)WriteBlock(x,y,5,5,0,pic_3);
- if(type==4)WriteBlock(x,y,5,5,0,pic_4);
- if(type==5)WriteBlock(x,y,5,5,0,pic_5);
- if(type==6)WriteBlock(x,y,5,5,0,pic_6);
- if(type==7)WriteBlock(x,y,5,5,0,pic_7);
- if(type==8)WriteBlock(x,y,5,5,0,pic_8);
- if(type==MARK)WriteBlock(x,y,5,5,0,pic_mark);
- if(type==CROSS)WriteBlock(x,y,5,5,0,pic_cross);
- if(type==BLACK)WriteBlock(x,y,5,5,0,pic_black);
- if(type==MINE)WriteBlock(x,y,5,5,0,pic_mine);
- }
- /*清屏*/
- void Cls()
- {
- ClearScreen();
- Refresh();
- }
- /*将时间(24*11)写到左下侧(缓存 5,66)*/
- void Timer(int time)
- {
- int a,b,c;
- a=time/100;
- b=(time-a*100)/10;
- c=time-a*100-b*10;
- ShowNumber(5,66,a);
- ShowNumber(13,66,b);
- ShowNumber(21,66,c);
- }
- /*显示剩余地雷数*/
- void MineNum(int i)
- {
- int a;
- a=i/10;
- i=i-a*10;
- ShowNumber(16,17,a);
- ShowNumber(24,17,i);
- }
- /*查看帮助*/
- void Help()
- {
- int key,i;
- char temp[1600];
- GetBlock(0,0,160,80,0,temp);
- Cls();
- SetScreen(0);
- key=0;i=0;
- while(key!=ESC)
- {
- memcpy(_TEXT,HELP+i*20,100);
- UpdateLCD(0);
- key=getchar();
- if(key==KU)i--;
- if(key==KD)i++;
- if(key==KL)i=0;
- if(key==KR)i=19;
- if(key==KPU)i=i-5;
- if(key==KPD)i=i+5;
- if(i>19)i=19;
- if(i<0)i=0;
- }
- WriteBlock(0,0,160,80,0,temp);
- Refresh();
- }
- /*标记(x,y)处方块,已标记则撤消标记*/
- void Mark(int x,int y)
- {
- int i;
- i=Map[x][y];
- if(i<5)
- {
- if(i>1)
- {
- Map[x][y]=i-2;
- ShowPic(x,y,BLACK);
- mark--;
- }
- else
- {
- Map[x][y]=i+2;
- mark++;
- ShowPic(x,y,MARK);
- }
- }
- }
- [color=orangered]/*挖开方块(x,y),扫描(x,y)周围八个方块中的地雷数并显示*/
- void Scan(int x,int y)
- {
- int a,b,i,s;
- s=0;
- for(a=-1;a<2;a++)
- {
- for(b=-1;b<2;b++)
- {
- if(x+a>=0&&y+b>=0&&x+a<21&&y+b<13)
- {
- i=Map[x+a][y+b];
- if(i==1||i==3)s++;
- }
- }
- }
- sum++;
- ShowPic(x,y,s);
- Refresh();
- Map[x][y]=s+10;
- }
- /*从(x,y)处开始搜索可翻开的方块*/
- void Sreach(int x,int y)
- {
- int i;
- int tx,ty;
- int s[8],a[8],b[8];/*八个方向*/
- a[0]=-1;b[0]=-1;
- a[1]=-1;b[1]=0;
- a[2]=-1;b[2]=1;
- a[3]=0;b[3]=1;
- a[4]=1;b[4]=1;
- a[5]=1;b[5]=0;
- a[6]=1;b[6]=-1;
- a[7]=0;b[7]=-1;
- if(Map[x][y]==0)Scan(x,y);
- if(Map[x][y]==10)
- {
- Map[x][y]=19;
- for(i=0;i<8;i++)
- {
- tx=x+a[i];
- ty=y+b[i];
- if(tx>=0&&ty>=0&&tx<21&&ty<13)
- {
- if(Map[tx][ty]==0)Scan(tx,ty);
- if(Map[tx][ty]==10)Sreach(tx,ty);
- }
- }
- }
- }[/color]/*连续翻开(x,y)周围的方块*/
- int Around(int x,int y)
- {
- int tx,ty;
- int a[8],b[8];
- int s[8],s1,s2,i;
- s1=0;s2=0;
- Face(OU);
- Refresh();
- /*定义八个方向向量*/
- a[0]=-1;b[0]=-1;
- a[1]=-1;b[1]=0;
- a[2]=-1;b[2]=1;
- a[3]=0;b[3]=1;
- a[4]=1;b[4]=1;
- a[5]=1;b[5]=0;
- a[6]=1;b[6]=-1;
- a[7]=0;b[7]=-1;
- /*扫描标记总数s1和错误标记数目s2*/
- for(i=0;i<8;i++)
- {
- tx=x+a[i];
- ty=y+b[i];
- if(tx>=0&&tx<21&&ty>=0&&ty<13)
- {
- s[i]=Map[tx][ty];
- if(s[i]==2||s[i]==3)s1++;
- if(s[i]==1)s2++;
- }
- }
- i=FALSE;/*返回值初始化*/
- /*标记总数正确时连续翻开并改变返回值,否则直接返回FALSE*/
- if(s1==Map[x][y]-10)
- {
- for(i=0;i<8;i++)
- {
- tx=x+a[i];
- ty=y+b[i];
- if(tx>=0&&tx<21&&ty>=0&&ty<13)
- {
- if(s[i]==0)Sreach(tx,ty);
- if(s[i]==1)ShowPic(tx,ty,MINE);
- }
- }
- /*有错误标记时返回TURE否则返回FALSE*/
- if(s2)i=TURE;
- else i=FALSE;
- }
- Face(SMILE);
- Refresh();
- return i;
- }
- struct TIME
- {
- int year;
- char month,day,hour,minute,second,week;
- };
- void main()
- {
- int max;
- int x,y;
- int done,lost;
- int i,key;
- int t,h,m,s;
- struct TIME time;
- while(1)
- {
- /*选择游戏难度*/
- i=5;
- key=0;
- Cls();
- Rectangle(56,36,104,44,2);
- Rectangle(50,20,110,47,1);
- Rectangle(51,48,110,49,1);
- Rectangle(111,21,112,49,1);
- TextOut(60,23,"难度:",0);
- while(key!=ENTER)
- {
- Rectangle(i*5+53,38,i*5+57,42,1);
- ShowNumber(92,23,i);
- key=0;
- Refresh();
- key=getchar();
- Rectangle(i*5+53,38,i*5+57,42,0);
- if(key==KR&&i<9)i++;
- if(key==KL&&i>1)i--;
- if(key==ESC)exit(0);
- }
- max=i*10;
- key=0;
- while(key!=ESC)
- {
- /*开新局*/
- Cls();
- TextOut(44,32,"载入中...",0xc0);
- Box(40,28,120,51,0,1);
- Box(41,52,120,53,1,1);
- Box(121,29,122,53,1,1);
- /*绘制游戏界面到缓冲区*/
- TextOut(2,2,"Lv ",0);
- TextOut(2,16,"剩",0);
- TextOut(4,50,"时间",0);
- ShowNumber(16,2,max/10);
- MineNum(max);
- Timer(0);
- Face(SMILE);
- Rectangle(4,64,29,78,1);
- Rectangle(32,1,32,79,1);
- Rectangle(0,0,159,0,1);
- /*刷新雷区*/
- for(y=0;y<13;y++)
- {
- for(x=0;x<21;x++)
- {
- Map[x][y]=0;
- ShowPic(x,y,BLACK);
- }
- }
- /*随机设置地雷位置*/
- x=rand()%21;
- y=rand()%13;
- for(i=0;i<max;i++)
- {
- while(Map[x][y])
- {
- x=rand()%21;
- y=rand()%13;
- }
- Map[x][y]=1;
- }
- Refresh();
- /*初始化游戏参数*/
- x=0;y=0;
- mark=0;
- sum=0;
- done=FALSE;
- lost=FALSE;
- key=getchar();
- if(key==KH)Help();
- GetTime(time);
- h=time.hour;
- m=time.minute;
- s=time.second;
- /*游戏控制部分*/
- while(key!=ESC&&key!=KF1&&lost==FALSE&done==FALSE)
- {
- GetTime(time);
- t=(time.hour-h)*3600+(time.minute-m)*60+(time.second-s);
- if(t>999)t=999;
- Timer(t);
- MineNum(max-mark);
- Refresh();
- Box(x*6+33,y*6+1,x*6+39,y*6+7,1,2);
- key=Inkey();
- if(key)
- {
- if(key==KR)
- {
- x++;
- Delay(100);
- if(x>20)x=0;
- }
- if(key==KL)
- {
- x--;
- Delay(100);
- if(x<0)x=20;
- }
- if(key==KU)
- {
- y--;
- Delay(100);
- if(y<0)y=12;
- }
- if(key==KD)
- {
- y++;
- Delay(100);
- if(y>12)y=0;
- }
- if(key==KH)
- {
- Help();
- Delay(500);
- }
- if(key==KSP)
- {
- Mark(x,y);
- Delay(200);
- }
- if(key==ENTER)
- {
- Face(OU);
- Refresh();
- if(Map[x][y]==0)Sreach(x,y);
- if(Map[x][y]==1)
- {
- lost=TURE;
- ShowPic(x,y,MINE);
- }
- Face(SMILE);
- Refresh();
- }
- if(key==KPU&&Map[x][y]>10)lost=Around(x,y);
- }
- if(sum==273-max)done=TURE;
- ReleaseKey(128);
- }
- /*判断胜负,并显示地雷*/
- /*失败*/
- if(lost)
- {
- Face(OU);
- for(x=0;x<21;x++)
- {
- for(y=0;y<13;y++)
- {
- if(Map[x][y]==1)ShowPic(x,y,MINE);
- if(Map[x][y]==2)ShowPic(x,y,CROSS);
- Refresh();
- }
- }
- Face(SAD);
- Refresh();
- }
- /*胜利*/
- if(done)
- {
- Face(OU);
- for(x=0;x<21;x++)
- {
- for(y=0;y<13;y++)
- {
- if(Map[x][y]==1)ShowPic(x,y,MARK);
- Refresh();
- }
- }
- Face(LAUGH);
- Refresh();
- }
- /*若游戏因得出胜负而结束,则暂停在结束画面*/
- while(key!=ESC&&key!=KF1)
- {
- key=getchar();
- if(key==KH)
- {
- Help();
- Delay(500);
- }
- }
- }
- }
- }
- --------------------------------------------------------------------------
- 回溯如下:
- /*从(x,y)处开始搜索可翻开的方块*/
- void Sreach(int x,int y)
- {
- int i;
- int step;/*步长*/
- int sa,sb,sc,sd,se,sf,sg,sh;/*八个方向*/
- int xx[273],yy[273];
- step=0;
- xx[step]=x;
- yy[step]=y;
- if(Map[x][y]==0)Scan(x,y);
- if(Map[x][y]==10)
- {
- L1:
- xx[step]=x;
- yy[step]=y;
- Map[x][y]=19;
- do
- {
- if(x>0&&y>0)
- {
- sa=Map[x-1][y-1];
- if(sa==0)
- {
- Scan(x-1,y-1);
- sa=Map[x-1][y-1];
- }
- }
- if(x>0)
- {
- sb=Map[x-1][y];
- if(sb==0)
- {
- Scan(x-1,y);
- sb=Map[x-1][y];
- }
- }
- if(x>0&&y<12)
- {
- sc=Map[x-1][y+1];
- if(sc==0)
- {
- Scan(x-1,y+1);
- sc=Map[x-1][y+1];
- }
- }
- if(y<12)
- {
- sd=Map[x][y+1];
- if(sd==0)
- {
- Scan(x,y+1);
- sd=Map[x][y+1];
- }
- }
- if(x<20&&y<12)
- {
- se=Map[x+1][y+1];
- if(se==0)
- {
- Scan(x+1,y+1);
- se=Map[x+1][y+1];
- }
- }
- if(x<20)
- {
- sf=Map[x+1][y];
- if(sf==0)
- {
- Scan(x+1,y);
- sf=Map[x+1][y];
- }
- }
- if(x<20&&y>0)
- {
- sg=Map[x+1][y-1];
- if(sg==0)
- {
- Scan(x+1,y-1);
- sg=Map[x+1][y-1];
- }
- }
- if(y>0)
- {
- sh=Map[x][y-1];
- if(sh==0)
- {
- Scan(x,y-1);
- sh=Map[x][y-1];
- }
- }
- if(x>0&&y>0&&sa==10)
- {
- x--;
- y--;
- step++;
- goto L1;
- }
- if(x>0&&sb==10)
- {
- x--;
- step++;
- goto L1;
- }
- if(x>0&&y<12&&sc==10)
- {
- x--;
- y++;
- step++;
- goto L1;
- }
- if(y<12&&sd==10)
- {
- y++;
- step++;
- goto L1;
- }
- if(x<20&&y<12&&se==10)
- {
- x++;
- y++;
- step++;
- goto L1;
- }
- if(x<20&&sf==10)
- {
- x++;
- step++;
- goto L1;
- }
- if(x<20&&y>0&&sg==10)
- {
- x++;
- y--;
- step++;
- goto L1;
- }
- if(y>0&&sh==10)
- {
- y--;
- step++;
- goto L1;
- }
- step--;
- x=xx[step];
- y=yy[step];
- }
- while (step>0);
- }
- }
复制代码 --------------------------------------------------------------------------
我感觉是递归好些吧 |
|