<commit_before>---
layout: post_layout
title: ﻿汉诺塔QT/C++实现
time: 2016年3月31日
location: 长春
pulished: true
excerpt_separator: "##"
---

---

汉诺塔问题十分经典，大家都很熟悉，汉诺塔（又称河内塔）问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子，在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定，在小圆盘上不能放大圆盘，在三根柱子之间一次只能移动一个圆盘。
这次数据结构课程设计要求我们做一个图形化界面的汉诺塔演示程序。

# 问题分析

为实现汉诺塔图形界面演示，我采用了C++的QT框架，整个程序界面由继承自QWidget的hanoiPanel展示，界面分为四大部分，顶部是菜单栏，用来控制动画运行和调整参数，中部左方为动画主体，右方为使用迭代算法时栈的实时状态动画，下方则为三个文本框，分别显示盘子的移动，递归的参数，和实时代码。

汉诺塔动画主体用QGraphicsView框架展示，每个盘子都是一个QLabel,将其add到QGraphicsScene中，通过QGraphicsView观察，盘子的移动采用QPropertyAnimation动画的方案，而每次盘子移动后的目的坐标，我们定义了一个diskstack类，将柱子看作一个栈，每个diskstack对象可以看作一根柱子，diskstack的成员有柱子的编号（1，2，3），柱子上的盘子数目，一个存放盘子数据disk的栈，一个存放盘子实例QLabel的栈，(我这里将盘子disk和QLabel分离开是为了减少耦合，将盘子的数据（坐标，颜色，长宽）和盘子实例分离开)，每当算法主体盘子移动后，都调用一次diskstack的成员函数upadata_position()以更新实时数据。而栈的动画与此类似。算法主体和各个部分组件的通信(如同步显示汉诺塔移动和栈的出入等)，采用QT的信号槽机制。


# 程序截图
![汉诺塔1](http://7xlv11.com1.z0.glb.clouddn.com/%E6%B1%89%E8%AF%BA%E5%A1%941.JPG)
![汉诺塔2](http://7xlv11.com1.z0.glb.clouddn.com/%E6%B1%89%E8%AF%BA%E5%A1%942.JPG)
![汉诺塔3](http://7xlv11.com1.z0.glb.clouddn.com/%E6%B1%89%E8%AF%BA%E5%A1%943.JPG)



# 代码

点此下载：

[汉诺塔程序(for windows).zip](http://www.husama.com/%E6%B1%89%E8%AF%BA%E5%A1%94%E7%A8%8B%E5%BA%8F.zip)

[汉诺塔代码.zip](http://www.husama.com/汉诺塔代码.zip)

或者
[我的github](https://github.com/husama/HanoiTower)<commit_msg>Update 2016-03-21-汉诺塔QT-C++实现.md<commit_after>---
layout: post_layout
title: ﻿汉诺塔QT/C++实现
time: 2016年3月31日
location: 长春
pulished: true
excerpt_separator: "##"
---

---

汉诺塔问题十分经典，大家都很熟悉，汉诺塔（又称河内塔）问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子，在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定，在小圆盘上不能放大圆盘，在三根柱子之间一次只能移动一个圆盘。
这次数据结构课程设计要求我们做一个图形化界面的汉诺塔演示程序。

# 问题分析

为实现汉诺塔图形界面演示，我采用了C++的QT框架，整个程序界面由继承自QWidget的hanoiPanel展示，界面分为四大部分，顶部是菜单栏，用来控制动画运行和调整参数，中部左方为动画主体，右方为使用迭代算法时栈的实时状态动画，下方则为三个文本框，分别显示盘子的移动，递归的参数，和实时代码。

汉诺塔动画主体用QGraphicsView框架展示，每个盘子都是一个QLabel,将其add到QGraphicsScene中，通过QGraphicsView观察，盘子的移动采用QPropertyAnimation动画的方案，而每次盘子移动后的目的坐标，我们定义了一个diskstack类，将柱子看作一个栈，每个diskstack对象可以看作一根柱子，diskstack的成员有柱子的编号（1，2，3），柱子上的盘子数目，一个存放盘子数据disk的栈，一个存放盘子实例QLabel的栈，(我这里将盘子disk和QLabel分离开是为了减少耦合，将盘子的数据（坐标，颜色，长宽）和盘子实例分离开)，每当算法主体盘子移动后，都调用一次diskstack的成员函数upadata_position()以更新实时数据。而栈的动画与此类似。算法主体和各个部分组件的通信(如同步显示汉诺塔移动和栈的出入等)，采用QT的信号槽机制。
柱子的数据结构：
```
#ifndef DISKSTACK_H
#define DISKSTACK_H
#include <QDebug>
#include <QRect>
#include <QStack>
#include <QLabel>

#include "disk.h"

class diskstack
{
    public:
        disk *initial;
        QStack <disk> s_stack;
        int s_height; // Height of the stack = number of disks
        int id;//柱子编号
        QStack<QLabel*> labels;

        void update_position();
        void init(int, int);

};

#endif // DISKSTACK_H
```
# 程序截图
![汉诺塔1](http://7xlv11.com1.z0.glb.clouddn.com/%E6%B1%89%E8%AF%BA%E5%A1%941.JPG)
![汉诺塔2](http://7xlv11.com1.z0.glb.clouddn.com/%E6%B1%89%E8%AF%BA%E5%A1%942.JPG)
![汉诺塔3](http://7xlv11.com1.z0.glb.clouddn.com/%E6%B1%89%E8%AF%BA%E5%A1%943.JPG)



# 代码

点此下载：

[汉诺塔程序(for windows).zip](http://www.husama.com/%E6%B1%89%E8%AF%BA%E5%A1%94%E7%A8%8B%E5%BA%8F.zip)

[汉诺塔代码.zip](http://www.husama.com/汉诺塔代码.zip)

或者
[我的github](https://github.com/husama/HanoiTower)
{'fraction_non_alphanumeric': 0.1525476711472335, 'fraction_numerical': 0.04876523913723038, 'mean_word_length': 8.60960960960961, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4030521', 'n_tokens_mistral': 2367, 'n_tokens_neox': 2626, 'n_words': 99}