回 帖 发 新 帖 刷新版面

主题:【原创】非递归汉诺塔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
*/

/***********************************************************/

写的有些乱

(刚发帖,还不会用颜色什么的。给大家带来的阅读不变,请谅解,谢谢。哈哈

回复列表 (共9个回复)

沙发

指教一下啦。

(我还有另一个算法。还有着两个算法编写 的 移动 步骤演示DEMO。怎么发呢?)

以后 就 在  这个 编程爱好者 论坛 混了!!

不在其他地方 灌 纯净水了。

我 是 北京 某 高校 本科 学 计算机 的 , 都大三了,

哎, 我怎么 现在 才发现这个 论坛呢?

哎~~~~

([color=FF0000]唉,大学也不是白上了,起码昨天发帖,今天就会用颜色了,[/color]
[color=FF0000]嗯,这个大学没白上!!~~~  苦笑~~~[/color]
)

板凳

我最爱

3 楼

哥们,

“我最爱”是啥意思?

莫非你最爱TC3.0?

4 楼

你要什么指教呀?

5 楼

北京,看你这么强,该不会就是清华的吧[em14]

6 楼


我初来乍到得,发了这个帖子。

“执教”是大家可以随便说说得意思。有啥感觉不好得,可以指点。小D这里细心听取了。

[em2]

7 楼

“强”不敢当。算法没有经过数学证明,要证明一个算法是正确的非常麻烦,编程序试验了没错,……

呵呵。不是清华的。

清华的学生也不一定很强吧?学计算机的大都是混的。

8 楼

楼上的各位高手能不能教一下小弟我。我是新手。如有好意见请发E-mail给小弟我。E-mail:qqrrrttt@21cn.con.谢谢!!

9 楼

你很强啊,
不过我还没调试过,不知道能否运行~~~

我来回复

您尚未登录,请登录后再回复。点此登录或注册