主题:【原创】非递归汉诺塔70行,请指教(我的第一帖,发现这个网站不错,我怎么才发现阿!)
发个帖子。 第一次 啊!!
是我用TC3.0编写的 非递归 Hanoi,
算法 是 自己 2003.9想出来2003.12优化的
{
总个数确定后,每张盘curDisk的移动方向maybe_To是确定的且唯一的:如共有三个盘时,盘1始终向左移动。
这里,将柱子由左向右看成A(源柱子Source),B(借助的柱子Borrow),C(目标柱子Target).
A的左看成C,B的左看成A,C的左看成B;
A的有看成B,B的右看成C,C的右看成A;
每张盘的移动方法([color=FF0000]因为不可能连续两次移动相同的盘![/color]):
一个盘curDisk现在在 柱子curStick上,那么curDisk[color=FF0000]这次只可能[/color]移向的柱子maybe_To是[color=FF0000]除了[/color]当前柱子curStick和最后一次移动时的目标柱子(LastToStick)的[color=FF0000]另[/color]一个柱子(3个中除了2个的另1个)
只要[color=FF0000]有选择[/color]的选择一个柱子curStick,分析、判断其最上面的盘curDisk的能否向curDisk确定的唯一的方向移动;移动 完后 再 选择 另一个 柱子 分析 判断
就可以完成了
(这个算法特别适合于人玩这个“弱智”(我有同学这么说)游戏,我玩我的文曲星pc1000a上的Hanoi 9层游戏,需要5分钟就可以移动完毕)
}
不算主函数的话有70多行。
{
另一个算法()[color=FF0000]因为不可能连续两次移动相同的盘![/color]):
一个盘curDisk现在在 柱子curStick上,且[color=FF0000]上次[/color]是从curDisk.maybe_To移过来的,那么curDisk[color=FF0000]这次[/color]只可能移向的柱子maybe_To是除了curStick和curDisk.maybe_To的另一个柱子
不算主函数的话有60行
}
初次发帖,指教一下啦(我怎么才发现有这个论坛呢?)
(不能上传文件吗?)
/********************************************************/
#include "STDIO.H"
#include "CONIO.H"
#include "STDLIB.H"
const short MAXDISKNUM=9;
const short Source=1,Borrow=2,Target=3;
const short DirFront=-1,DirNext=1;
struct DiskStatus
{
short DirMove;
}Disk[MAXDISKNUM];
struct StickStatus
{
short Data[MAXDISKNUM+1];
short Num;
short Front;
short Next;
char Name;
}Stick[4];
void Hanoi(short TotalDiskNum)
{
for ( short i=TotalDiskNum,j=1;i>=1;i--,j++ )
{
if ( j%2==0 )
Disk[i].DirMove=DirNext; // 当前盘Disk[i]始终向Next移动
else
Disk[i].DirMove=DirFront; // 当前盘Disk[i]始终向Front移动
Stick[Source].Data[j]=i;
}
Stick[Source].Num=TotalDiskNum;
Stick[Borrow].Num=Stick[Target].Num=0;
Stick[Source].Name='A'; Stick[Source].Next=Borrow; Stick[Source].Front=Target;
Stick[Borrow].Name='B'; Stick[Borrow].Next=Target; Stick[Borrow].Front=Source;
Stick[Target].Name='C'; Stick[Target].Next=Source; Stick[Target].Front=Borrow;
short LastToStick; // 最后一次移动盘的"目标柱子"
short CurStick; // "当前柱子"指针
short curdisk; // CurStick最上面的盘curdisk
short maybe_to; // curdisk可能移向的柱子
short Step; // 步骤
CurStick=Source; // 指定当前柱子为Source
Step=LastToStick=0; // 步骤为0,最后一次移向的柱子也为0
do
{
MoveCurStickAgain: // 'goto' can be replaced by some a do-while sentence
i=Stick[CurStick].Num;// i是当前柱子上盘的个数
if ( i>0 )
{
curdisk=Stick[CurStick].Data[i];// curdisk是当前柱子最上面的盘
if ( Disk[curdisk].DirMove==DirFront )
maybe_to=Stick[CurStick].Front; // curdisk“可能”向Front移动
else
maybe_to=Stick[CurStick].Next; // curdisk“可能”向Next移动
j=Stick[maybe_to].Num; // j为maybe_to上盘的个数
if ( j==0 || curdisk<Stick[maybe_to].Data[j] )
{
// 若maybe_to上没盘;或curDisk的SIZE小于其最上面的盘
// 则“移动”curDisk到maybe_to,并修改标志信息
Stick[CurStick].Num--;
j++;
Stick[maybe_to].Num=j;
Stick[maybe_to].Data[j]=curdisk;
LastToStick=maybe_to;
printf("%5d: Move Disk %2d From %c To %c\n",++Step,curdisk,Stick[CurStick].Name,Stick[maybe_to].Name);
if ( Step%10==0 ) { printf("\n"); getch();}
goto MoveCurStickAgain; // 重新判断curStick上下一个盘
}
}
CurStick=(Source+Borrow+Target)-(CurStick+LastToStick);
// 下次之可能分析判断的柱子(“指针”)是(指向)除了curStick
// 和LastToStick之外的另一个柱子(3个柱子中除了2个的另一个)
}while( Stick[Target].Num!=TotalDiskNum );
}
void main()
{
clrscr();
short num;
printf("\nInput Disk Num [1,%d] :",MAXDISKNUM);
scanf("%d",&num);
if (!(num<=MAXDISKNUM&&num>=1))
{
printf("Input Invalid.");
getch();
exit(0);
}
Hanoi(num);
printf("\n\nPress any key to quit.");
getch(); getch();
}
/**
* @ Title: 非递归的Hanoi.Not.Recursive
* @ Description: 打印输出Hanoi移动步骤
* @ Copyright: this.Author
* @ Author: RiverHorse ( alias TamusKing, yadxbit )
* @ BBS ID: RiverHorse ( 论坛: 电脑爱好者 )
* @ E_Mail: yadxbit@163.com
*
* @ Algorithm Established : 2003.09
* @ Algorithm Optimized : 2003.12
*/
/**
* @ 编译语言: TC3.0
* @ 编写通过环境: WindowsXP
*/
/***********************************************************/
写的有些乱
(刚发帖,还不会用颜色什么的。给大家带来的阅读不变,请谅解,谢谢。哈哈