汉诺塔移动动画.docx
《汉诺塔移动动画.docx》由会员分享,可在线阅读,更多相关《汉诺塔移动动画.docx(17页珍藏版)》请在冰点文库上搜索。
汉诺塔移动动画
汉诺塔移动动画
///////////////////////////////////////////////////
//程序名称:
汉诺塔移动动画
//编译环境:
VisualC++6.0,EasyX2011惊蛰版
//作 者:
RonaldEmail:
*******************
//最后修改:
2011-5-26
//
#include
#include
#include
#defineMAX64//圆盘的最大数目
#defineNULL0
//定义栈
structSTKNODE
{
inta[4];
};
structSTK
{
STKNODE*stack[MAX];
inttop;
};
//定义全局变量
STKs[3];//声明三个栈,分别代表一号二号三号钢针上圆盘的状态
intv=5;//调整速度
//函数声明
voidInitstk(STK*s);//初始化栈
voidHannoi(intn,chara,charb,charc);//汉诺塔递归
voidstart();//开始画面
voidMove(intn,chara,charb);//移动过程
intswitchab(chara);//返回钢针号
voidadjust();//调整速度暂停
//主函数
voidmain()
{
intn,ta[4]={115,500,285,520};//第一个圆盘的位置
printf("尽量小于16\n");//因为大于十六时就会显示有误,但程序可以正常运行
printf("请输入汉诺塔的层数(1~64):
");
scanf("%d",&n);
STKNODE**p;
p=(STKNODE**)malloc(n*sizeof(STKNODE**));//声明一个元素为n个的动态STKNODE型指针数组
for(inti2=0;i2{
p[i2]=(STKNODE*)malloc(sizeof(STKNODE));//为每一个指针申请空间
}
Initstk(&s[0]);
Initstk(&s[1]);
Initstk(&s[2]);//将三个栈初始化
start();//呈现开始画面
setfillstyle(YELLOW);//圆盘的颜色
for(inti=0;i{
ta[0]+=5;
ta[1]-=20;
ta[2]-=5;
ta[3]-=20;
bar(ta[0],ta[1],ta[2],ta[3]);//画出n个从大到小一次叠放的黄色圆盘
++s[0].top;//进栈
for(inti1=0;i1<4;i1++)
{
p[i]->a[i1]=ta[i1];
s[0].stack[s[0].top]=p[i];//记录每个矩形的位置,top为圆盘的个数
}
}
Hannoi(n,'a','b','c');//汉诺塔递归函数
system("pause");
printf("\t\t\t\tGameOver!
\n");
}
///////////////////////////////////////////////////
//函数定义
//汉诺塔的递归
voidHannoi(intn,chara,charb,charc)
{
if(n==1)
Move(1,a,c);
else
{
Hannoi(n-1,a,c,b);
Move(n,a,c);
Hannoi(n-1,b,a,c);
}
}
//栈的初始化
voidInitstk(STK*s)
{
inti;
s->top=0;
for(i=0;i<=MAX;i++)
s->stack[++s->top]=NULL;
s->top=0;
}
//移动过程
voidMove(intn,chara,charb)
{
inti3,i4=0,i5=0;
i3=b-a;//目的钢针与源钢针的位置差值
i4=switchab(a);//源钢针钢针号
i5=switchab(b);//目的钢针号
STKNODE*q1,*q0;//两个中间结点用于源栈和目的栈间的值得传递,q1为目的栈,q0为源栈
q1=(STKNODE*)malloc(sizeof(STKNODE));
q0=(STKNODE*)malloc(sizeof(STKNODE));
//源栈与目的栈值的传递
q0=s[i4].stack[s[i4].top];
++s[i5].top;//进栈
q1->a[0]=q0->a[0]+i3*200;
q1->a[1]=500-s[i5].top*20;
q1->a[2]=q0->a[2]+i3*200;
q1->a[3]=500-s[i5].top*20+20;
s[i5].stack[s[i5].top]=q1;
--s[i4].top;//出栈
//向上运动
while(q0->a[1]>=100)
{
setfillstyle(YELLOW);
bar(q0->a[0],q0->a[1],q0->a[2],q0->a[3]);
adjust();//调整函数
Sleep(10*v);//暂停(ms)
setfillstyle(WHITE);
bar(q0->a[0],q0->a[1],q0->a[2],q0->a[3]);
setcolor(RED);
line((q0->a[0]+q0->a[2])/2,q0->a[1],(q0->a[0]+q0->a[2])/2,q0->a[3]);//重新画上被擦掉原有的红线
q0->a[1]-=10;
q0->a[3]-=10;
if(s[i4].top==0)//重新画上最后一个矩形块擦掉的底座上的两条红线
{
line(110+i4*200,500,290+i4*200,500);
line(110+i4*200,493,290+i4*200,493);
}
}
//向左或右运动,与i3的正负有关
while(q0->a[2]!
=q1->a[2])
{
setfillstyle(YELLOW);
bar(q0->a[0],q0->a[1],q0->a[2],q0->a[3]);
adjust();
Sleep(10*v);
setfillstyle(WHITE);
bar(q0->a[0],q0->a[1],q0->a[2],q0->a[3]);
if(i3<0)//i3<0向左移
{
q0->a[0]-=20;
q0->a[2]-=20;
}
else//i3>0向右移
{
q0->a[0]+=20;
q0->a[2]+=20;
}
}
//向下运动
while(q0->a[3]<=q1->a[3])
{
setfillstyle(YELLOW);
bar(q0->a[0],q0->a[1],q0->a[2],q0->a[3]);
adjust();
Sleep(10*v);
setfillstyle(WHITE);
bar(q0->a[0],q0->a[1],q0->a[2],q0->a[3]);
setcolor(RED);
if(q0->a[1]>100)//重画被擦掉的红线
{
setcolor(RED);
line((q0->a[0]+q0->a[2])/2,q0->a[1],(q0->a[0]+q0->a[2])/2,q0->a[3]);
}
q0->a[1]+=10;
q0->a[3]+=10;
}
//在目的钢针上的相应位置绘制出黄色矩形块
setfillstyle(YELLOW);
bar(q1->a[0],q1->a[1],q1->a[2],q1->a[3]);
}
//绘制开始界面
voidstart()
{
//初始化画面大小
initgraph(800,650);
//背景设为白色
setbkcolor(WHITE);
//用白色填充整个画面
cleardevice();
//绘制彩虹,形成一道彩虹,摘自easyx帮助文档示例程序
floatH,S,L;
H=0;//色相
S=1;//饱和度
L=0.5f;//亮度
setlinestyle(PS_SOLID,NULL,2);//设置线宽为2
for(intr=600;r>544;r--)
{
H+=5;
setcolor(HSLtoRGB(H,S,L));
circle(750,900,r);
}
//说明
setfont(50,0,"华文楷体");
setcolor(RED);
outtextxy(200,150,"汉诺塔移动动画");
setfont(20,0,"黑体");
outtextxy(600,200,"BY:
Ronald");
outtextxy(500,200,"版本V1.1");
setfont(50,0,"黑体");
setcolor(GREEN);
outtextxy(200,350,"随便按一个键开始吧!
");
//绘制运动的矩形
while
(1)
{
//检测是否有键盘敲击
if(kbhit())
{
break;
}
//向右
inta=40,b=40;//初始位置
while(a<=760)
{
setfillstyle(YELLOW);
bar(a,b,a+10,b+20);
Sleep(10);
setfillstyle(WHITE+a);
bar(a,b,a+10,b+20);
a+=10;
}
if(kbhit())
{
break;
}
//向下
while(b<=610)
{
setfillstyle(RED);
bar(a,b,a+10,b+20);
Sleep(10);
setfillstyle(WHITE-b);
bar(a,b,a+10,b+20);
b+=10;
}
if(kbhit())
{
break;
}
//向左
while(a>=40)
{
setfillstyle(GREEN);
bar(a,b,a+10,b+20);
Sleep(10);
setfillstyle(WHITE-a);
bar(a,b,a+10,b+20);
a-=10;
}
if(kbhit())
{
break;
}
//向上
while(b>=40)
{
setfillstyle(BLUE);
bar(a,b,a+10,b+20);
Sleep(10);
setfillstyle(WHITE+b);
bar(a,b,a+10,b+20);
b-=10;
}
}
//清空开始界面
cleardevice();
//绘制运动画面的的环境
setcolor(RED);
//三根红色线段作为钢针
line(400,110,400,500);
line(600,110,600,500);
line(200,110,200,500);
//长方体形的底座
setfillstyle(LIGHTGRAY);
bar3d(80,500,720,510,10,true);
//暂停按钮
bar(360,540,440,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(370,550,"暂停");
setfont(20,0,"宋体");
setcolor(RED);
outtextxy(300,580,"鼠标暂停后请按空格继续");
//加速按钮
bar(160,540,240,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(170,550,"加速");
setfont(20,0,"宋体");
setcolor(RED);
outtextxy(170,580,"请按d");
//减速按钮
bar(560,540,640,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(570,550,"减速");
setfont(20,0,"宋体");
setcolor(RED);
outtextxy(570,580,"请按a");
//说明
setfont(50,0,"宋体");
setcolor(GREEN);
outtextxy(10,10,"正在进行中请欣赏:
");
}
//判断目的钢针与源钢针的钢针号返回钢针号
intswitchab(chara)
{
switch(a)
{
case'a':
return0;
case'b':
return1;
case'c':
return2;
default:
return0;
}
}
//调整函数,实现加速,减速,暂停
voidadjust()
{
charf;//接收键盘敲进去的按钮和鼠标点击时赋予的变化值
//用f接受键盘的键入值
if(kbhit())
f=getch();
//检测鼠标消息
if(MouseHit()==true)
{
//接收鼠标消息
MOUSEMSGMouse;
Mouse=GetMouseMsg();
//响应鼠标消息
if(Mouse.x>=360&&Mouse.x<=440&&Mouse.y>=540&&Mouse.y<=580&&Mouse.mkLButton)
{
f='';
}
if(Mouse.x>=160&&Mouse.x<=240&&Mouse.y>=540&&Mouse.y<=580&&Mouse.mkLButton)
{
f='d';
}
if(Mouse.x>=560&&Mouse.x<=640&&Mouse.y>=540&&Mouse.y<=580&&Mouse.mkLButton)
{
f='a';
}
}
//作用于动画
switch(f)
{
//暂停
case'':
//用‘继续’覆盖‘暂停’
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(370,550,"继续");
getch();
//继续后变回显示‘暂停’
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(370,550,"暂停");
break;
//减速
case'a':
//当被点击时,‘减速’位置震动一下
setfillstyle(LIGHTGRAY);
bar(560,540,640,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(575,545,"减速");
Sleep(30);
//减速
v++;
//回原位
setfillstyle(LIGHTGRAY);
bar(560,540,640,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(570,550,"减速");
break;
//加速
case'd':
setfillstyle(LIGHTGRAY);
bar(160,540,240,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(165,545,"加速");
Sleep(30);
setfillstyle(LIGHTGRAY);
bar(160,540,240,580);
setfont(30,0,"黑体");
setcolor(GREEN);
outtextxy(170,550,"加速");
//加速
v--;
//v最小为1
if(v<=0)
{
v=1;
}
break;
default:
break;
}
f='r';//f初始化为r
FlushMouseMsgBuffer();//清空鼠标消息
}