汉诺塔vb.net 汉诺塔问题

编程实现5个盘子的汉诺塔问题;(递归算法)以下是5个盘子的汉诺塔程序,用的是递归算法:
#includefstream
#includeiostream
using namespace std;
ofstream fout("Honnoi.txt");
int num=1;//记录步数
void Move(int n,char x,char y)
{
foutnum":""把"n" 号盘 , 从"x"柱移到"y"号柱"endl;
coutnum":""把"n" 号盘,从"x"柱移到"y"号柱"endl;
num;
}
void Hannoi(int n,char A,char C,char B)
{
if(n==1)
Move(1,A,C);
else
{
Hannoi(n-1,A,B,C);
Move(n,A,C);
Hannoi(n-1,B,C,A);
}
}
int main()
{
Hannoi(5,'A','C','B');
cout"输出完毕!"endl;
cout"一共"num-1"步"endl;
return 0;
}
程序将输出步数、每步操作和总步数
汉诺塔VB的心得体会VB编写益智游戏“汉诺塔”
海粟/文
《软件报》2007年47期 61-74
【编程引子】
“汉诺塔”问题源自印度的一个古老传说 , 对于它的算法比较常见的是应用递归调用 。在本例中,笔者将给大家介绍一种更简单和直观的处理方法 。
【编程分析】
汉诺塔游戏的主要目的是借助B区域,将A区域的五只盘子转移到C区域中,要求每次移动必须从最上层盘子开始,而且必须始终保证小号盘子在大号盘子的上方 。
程序的主要技术点,除了对上述要求的实现外 , 还要考虑到鼠标拖放盘子以及盘子的定位、排序等内容 。在设计初期,笔者首先考虑采用单击选定,再次单击定位的方式来移动盘子 , 但这样做必须要让程序记住谁是活动盘子,而且操作的直观性较差 。所以,最后笔者还是选择了利用鼠标事件来模拟拖动盘子的动作 。
而对于盘子移动后的定位问题,如果单纯靠坐标计算来显然,工作量是非常大的 。所以,笔者在本例中应用了“一个萝卜一个坑”的简单原理,将目标位置提前放置好Image控件 , 这样一来,盘子的移动和定位操作都成了对目标控件属性的控制,处理起来变得十分方便 。
【主要代码】
1.程序初始化
程序初始化操作在窗体加载事件中完成,另外它与“重新开始”功能模块的作用完全相同,所以可以通过调用的方式来共享代码 。代码的主要功能是移动步骤清零、在A区域复位盘子,以及清除B和C两区域盘子等,主要内容如下:
Private Sub Command1_Click()
Label4.Caption = 0’移动步骤清零
For i = 0 To 4
Image1(i).Picture = LoadPicture(App.Path"\p"i".jpg")
Image2(i).Picture = LoadPicture("")
Image3(i).Picture = LoadPicture("")
Next i
Call SortImg(Image1, 1080)’对齐盘子
End Sub
其中子过程SortImg是对指定区域内盘子进行居中对齐操作,后文中会有详细介绍 。
2.转移盘子
该过程是整个程序的核心 , 需要考虑的事件包括从A区至B区和C区、从B区至A区和C区、从C区至A区和B区这样共六种情况,为了简化代码编写 , 笔者在程序中使用了控件数组 。下面是从A区向其它两区转移盘子的代码,其它几种情况与之类似:
Private Sub Image1_MouseUp(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
If Index4 Then If Image1(Index1).Picture0 Then Exit Sub ’移动操作不合法
If X = 2000 And X = 3200 Then
Call MoveImg(Image1, Image2, Index)’从A向B转移
Call SortImg(Image2, 3420) ’对齐盘子3420为区域中心线X值
End If
If X = 4300 And X = 5700 Then
Call MoveImg(Image1, Image3, Index) ’从A向C转移
Call SortImg(Image3, 5760)
End If
End Sub
通过分析可知,如果用户所选盘子的上方还有盘子 , 则不符合游戏规则,会被终止 。另外,程序中使用了类似其它软件中的“热区域”的概念,即当拖动鼠标至我们规定的B区域中时,将引发真正的移动操作(即激活子过程MoveImg),其主要代码如下:
Private Sub MoveImg(SImg As Object, DImg As Object, Idx As Integer)
For i = 0 To 4
If DImg(i).Picture = 0 Then’当前区域有位置
If i0 Then
If SImg(Idx).WidthDImg(i - 1).Width Then’符合上小下大游戏条件
DImg(i).Picture = SImg(Idx).Picture’移动盘子
Exit For
Else
Exit Sub’移动操作不合法则退出
End If
Else
DImg(i).Picture = SImg(Idx).Picture ’向区域最下方移动盘子
Exit For
End If
End If
Next i
If i = 4 Then
SImg(Idx).Picture = LoadPicture("")
Label4.Caption = Label4.Caption1’更新操作步数
End If
End Sub
在移动子过程中,判定位置是否为空的主要依据是目标Image控件的Picture属性是否为0;当获知位置可用时,再进一步判断当前位置的下面位置盘子的尺寸是否大于当前盘子(即对游戏规则的判定),条件满足的话就可以通过传递Picture属性值来完成移动操作了;最后,还要将源位置盘子清空,并且记录操作步数 。
3.对齐盘子
在上述两模块中都涉及了子过程SortImg,其主要功能是对区域内盘子进行居中对齐处理,这是美化程序执行效果的一项重要措施 , 同时在该部分中还加入了游戏胜利过关的判断(即每转移一步判断一次),主要代码如下:
Private Sub SortImg(Img As Object, IntCenter As Integer)
For i = 0 To 4
Img(i).Left = IntCenter - Img(i).Width / 2
Next i
For i = 0 To 4
If Image1(i).Picture0 Then Exit For
If Image2(i).Picture0 Then Exit For
Next i
If i4 Then MsgBox "恭喜:你成功了!", vbOKOnlyvbInformation, "胜利"
End Sub
【编程后记】
面对一些看似复杂的程序功能,仔细研究一下,总会有好的思路和方法闪现出来 。本例实现了汉诺塔游戏的基本设计思路,大家还可以在盘子数量、步数排行榜等方面予以改进 , 以使该程序变得更加丰富、精彩!
什么叫汉诺塔问题?汉诺塔(又称河内塔)问题是印度的一个古老的传说 。开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个?。来蔚先?nbsp;, 庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个 , 而且大的不能放在小的上面 。解答结果请自己运行计算,程序见尾部 。面对庞大的数字(移动圆片的次数)18446744073709551615,看来 , 众僧们耗尽毕生精力也不可能完成金片的移动 。
后来,这个传说就演变为汉诺塔游戏:
1.有三根杆子A,B,C 。A杆上有若干碟子
2.每次移动一块碟子,小的只能叠在大的上面
3.把所有碟子从A杆全部移到C杆上
经过研究发现,汉诺塔的破解很简单 , 就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
此外,汉诺塔问题也是程序设计中的经典递归问题 。
【汉诺塔vb.net 汉诺塔问题】关于汉诺塔vb.net和汉诺塔问题的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息 , 记得收藏关注本站 。

    推荐阅读