【Java+swing】实现自动演示的汉诺塔小游戏

目录

1 算法与问题描述

1.1 问题描述

1.2 递归算法

1.3 非递归算法

2 游戏程序的总体设计

2.1 HannoiWindow类设计

2.2 Tower类设计

2.3 Disc类设计

2.4 TowerPoint类设计

2.5 HandleMouse类设计

2.6  AutoMoveDisc类

3 运行界面展示

4 总结


1 算法与问题描述

1.1 问题描述

图1-1 汉诺塔

假设有三个命名为a(TOWER 1),b(TOWER 2),c(TOWER 3)的塔座如图1-1所示,在塔座X上有n个直径大小各不相同,依次从小到大编号为1,2,3,...,n的圆盘。现要求将a塔座上的n个圆盘移到c塔座上并按同样顺序叠排, 圆盘移动时必须遵循下列规则:

(1)每次只能移动一个圆盘;

(2)圆盘可以插在a,b,c中的任意塔座上;

(3)任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

1.2 递归算法

定义N为圆盘数量:

当N=1时,A>C;

当N=2时,A>B | |  A>C  | | B>C;

当N=3时,A>C,A>B,C>B  | |  A>C  | |  B>A,B>C,A>C;

...

代码及代码思路: 

	public static void hanoi(int n,char a,char b,char c ) {
		if(n==1) System.out.println(a+">"+c);
		else {
			//1
			hanoi(n-1,a,c,b);
			//2
			System.out.println(a+">"+c);
			//3
			hanoi(n-1,b,a,c);
		}
	}

利用了分治法的思想

第一步  对于执行最大盘(N)到C的操作之前,即把盘(N-1)从A到B操作;

第二步  执行最大盘(N) 到C的操作;

第三步 对于执行最大盘(N)到C的操作之后,即把盘(N-1)从B到C操作;

每次只关心上一层,上上层是到了上一层才考虑的事------递归

1.3 非递归算法

非递归方式即找规律:

A号柱有n 个盘子,叫做源柱.移往C 号柱,叫做目的柱.B 号柱叫做中间柱.
全部移往C 号柱要f(n) =(2^n)- 1 次.
最大盘n 号盘在整个移动过程中只移动一次,n-1 号移动2 次,i 号盘移动
2^(n-i)次.
1 号盘移动次数最多,每2 次移动一次.
第2k+1 次移动的是1 号盘,且是第k+1 次移动1 号盘.
第4k+2 次移动的是2 号盘,且是第k+1 次移动2 号盘.

第(2^s)k+2^(s-1)次移动的是s 号盘,这时s 号盘已被移动了k+1 次.
每2^s 次就有一次是移动s 号盘.
第一次移动s 号盘是在第2^(s-1)次.
第二次移动s 号盘是在第2^s+2^(s-1)次.
第k+1 次移动s 号盘是在第k*2^s+2^(s-1)次.


A-->B,B-->C,C-->A叫做顺时针方向,A-->C,C-->B,B-->A叫做逆时针方向.
最大盘n 号盘只移动一次:A-->C它是逆时针移动.
n-1 移动2 次:A-->B,B-->C,是顺时针移动.

代码及代码思路: 

public static void hanoi_f(int n) {
		int s;// 从上到下几号盘
		long i, t, k;
		long res = (1 << n) - 1;
		for (i = 1; i <= res; i++) {
			for (t = 2, s = 1; s <= n; s++, t *= 2)
				if (i % t == t / 2)
					break;//找 第i步移动的s号盘
			k = i / t;// 获得第s盘 第几次移动
			if (n % 2 == s % 2) {// 逆时针
				if ((k + 1) % 3 == 0)
					System.out.println(s + " from B to A");
				if ((k + 1) % 3 == 1)
					System.out.println(s + " from A to c");
				if ((k + 1) % 3 == 2)
					System.out.println(s + " from C to B");
			} else {// 顺时针
				if ((k + 1) % 3 == 0)
					System.out.println(s + " from C to A");
				if ((k + 1) % 3 == 1)
					System.out.println(s + " from A to B");
				if ((k + 1) % 3 == 2)
					System.out.println(s + " from B to C");
			}
		}

	}

枚举 1, 2, 3, 4·····i,  i+1, i+2, ·····步。

第一步  先获取第i步移动的几号盘,根据 (2^s)k+2^(s-1)=i,转化一下,满足  i%(2^s) =2^(s-1)  ,令t=2^s;则有i%t=t/2;

第二步 再获得第S盘 第几次移动 ,根据  (2^s)k+2^(s-1)=i,  k=i/(2^s) ,即 k=i/t;

第三步 最后根据周期T 与奇偶性 确定具体移动的步骤

2 游戏程序的总体设计

在设计hannoi塔时,需编写6个java源文件:HannoiWindow.java、Tower.java、TowerPoint.java、Disc.java、HandleMouse.java和AutoMoveDisc.java。

Hannoi塔除了要编写的6个Java源文件所给出的类外,还需要Java系统提供的一些重要的类,如JMenuBar、JMenu、JMenuItem和JButton。Hannoi塔所用到的一些重要的类以及之间的组合关系如图2-1所示:

 图2-1 类之间的组合联系

2.1 HannoiWindow类设计

HannoiWindow类负责创建Hannoi塔的主窗口,该类含有main方法,Hannoi塔从该类开始执行。

HannoiWindow类的成员变量中有五种重要类型的对象、一个int基本型数据和一个char型数组。五种类型的对象分别是:Tower、JMenuBar、JMenu、JMenuItem和JButton对象。

事件实现窗口间的变化,根据变量amountOfDisc的不同更换游戏级别,即disc的个数;

代码:

package hannuota;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;


public class HannoiWindow extends JFrame implements ActionListener {
	Tower tower = null;
	int amountOfDisc = 3;
	char[] towerName = { 'A', 'B', 'C' };
	JMenuBar bar;
	JMenu menuGrade;
	JMenuItem oneGradeItem, twoGradeItem, threeGradeItem;
	JButton renew = null;
	JButton autoButton = null;
	JPanel center = new JPanel();

	HannoiWindow() {
		tower = new Tower(towerName);
		tower.setAmountOfDisc(amountOfDisc);
		tower.setMaxDiscWidth(120);
		tower.setMinDiscWidth(50);
		tower.setDiscHeight(16);
		tower.putDiscOnTower();
		add(tower, BorderLayout.CENTER);
		bar = new JMenuBar();
		menuGrade = new JMenu("选择级别");
		oneGradeItem = new JMenuItem("初级");
		twoGradeItem = new JMenuItem("中级");
		threeGradeItem = new JMenuItem("高级");
		menuGrade.add(oneGradeItem);
		menuGrade.add(twoGradeItem);
		menuGrade.add(threeGradeItem);
		bar.add(menuGrade);
		setJMenuBar(bar);
		oneGradeItem.addActionListener(this);
		twoGradeItem.addActionListener(this);
		threeGradeItem.addActionListener(this);
		renew = new JButton("重新开始");
		renew.addActionListener(this);
		autoButton = new JButton("自动演示");
		autoButton.addActionListener(this);
		JPanel north = new JPanel();
		north.add(renew);
		north.add(autoButton);
		String mess = "将全部盘子从" + towerName[0] + "座搬运到" + towerName[1] + "座或" + towerName[2] + "座";
		JLabel hintMess = new JLabel(mess, JLabel.CENTER);
		north.add(hintMess);
		add(north, BorderLayout.NORTH);
		setResizable(false);
		setVisible(true);
		setBounds(60, 60, 460, 410);
		//确保组件具有有效的布局
		validate();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == oneGradeItem) {
			amountOfDisc = 3;
			tower.setAmountOfDisc(amountOfDisc);
			tower.putDiscOnTower();
		} else if (e.getSource() == twoGradeItem) {
			amountOfDisc = 4;
			tower.setAmountOfDisc(amountOfDisc);
			tower.putDiscOnTower();
		} else if (e.getSource() == threeGradeItem) {
			amountOfDisc = 5;
			tower.setAmountOfDisc(amountOfDisc);
			tower.putDiscOnTower();
		} else if (e.getSource() == renew) {
			tower.setAmountOfDisc(amountOfDisc);
			tower.putDiscOnTower();
		} else if (e.getSource() == autoButton) {
			tower.setAmountOfDisc(amountOfDisc);
			tower.putDiscOnTower();
			int x = this.getBounds().x + this.getBounds().width;
			int y = this.getBounds().y;
			tower.getAutoMoveDisc().setLocation(x, y);
			tower.getAutoMoveDisc().setSize(280, this.getBounds().height);
			tower.getAutoMoveDisc().setVisible(true);
		}
		validate();
	}

	public static void main(String args[]) {
		new HannoiWindow();
	}
}

2.2 Tower类设计

Tower类是javax.swing包中Jpanel容器的子类,创建的容器被添加到HannoiWindow窗口的中心。

Tower类的成员变量中有四种重要类型的对象、一个int基本型数据和一个char型数组。四种类型的对象分别是:Disc、TowerPoint、HandleMouse、和AutoMoveDisc对象。

代码:

package hannuota;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

public class Tower extends JPanel {
	int amountOfDisc = 3;
	Disc[] disc;
	int maxDiscWidth, minDiscWidth, discHeight;
	char[] towerName;
	TowerPoint[] pointA, pointB, pointC;
	HandleMouse handleMouse;
	AutoMoveDisc autoMoveDisc;

	Tower(char[] towerName) {
		handleMouse = new HandleMouse(this);
		this.towerName = towerName;
		setLayout(null);
		setBackground(new Color(200, 226, 226));
	}

	public void setAmountOfDisc(int number) {
		if (number <= 1)
			amountOfDisc = 1;
		else
			amountOfDisc = number;
	}

	public void setMaxDiscWidth(int m) {
		maxDiscWidth = m;
	}

	public void setMinDiscWidth(int m) {
		minDiscWidth = m;
	}

	public void setDiscHeight(int h) {
		discHeight = h;
	}

	public AutoMoveDisc getAutoMoveDisc() {
		return autoMoveDisc;
	}

	public void putDiscOnTower() {
		removeDisk();
		int n = (maxDiscWidth - minDiscWidth) / amountOfDisc;
		disc = new Disc[amountOfDisc];
		for (int i = 0; i < disc.length; i++) {
			disc[i] = new Disc();
			disc[i].setNumber(i);
			int diskwidth = minDiscWidth + i * n;//下面的disc 更宽
			disc[i].setSize(diskwidth, discHeight);
			disc[i].addMouseListener(handleMouse);
			disc[i].addMouseMotionListener(handleMouse);
		}
		pointA = new TowerPoint[amountOfDisc];
		pointB = new TowerPoint[amountOfDisc];
		pointC = new TowerPoint[amountOfDisc];
		int vertialDistance = discHeight;
		for (int i = 0; i < pointA.length; i++) {
			pointA[i] = new TowerPoint(maxDiscWidth, 100 + vertialDistance);
			vertialDistance = vertialDistance + discHeight;
		}
		vertialDistance = discHeight;
		for (int i = 0; i < pointB.length; i++) {
			pointB[i] = new TowerPoint(2 * maxDiscWidth, 100 + vertialDistance);
			vertialDistance = vertialDistance + discHeight;
		}
		vertialDistance = discHeight;
		for (int i = 0; i < pointC.length; i++) {
			pointC[i] = new TowerPoint(3 * maxDiscWidth, 100 + vertialDistance);
			vertialDistance = vertialDistance + discHeight;
		}
		for (int i = 0; i < pointA.length; i++) {
			pointA[i].putDisc(disc[i], this);
		}
		handleMouse.setPointA(pointA);
		handleMouse.setPointB(pointB);
		handleMouse.setPointC(pointC);
		autoMoveDisc = new AutoMoveDisc(this);
		autoMoveDisc.setTowerName(towerName);
		autoMoveDisc.setAmountOfDisc(amountOfDisc);
		autoMoveDisc.setPointA(pointA);
		autoMoveDisc.setPointB(pointB);
		autoMoveDisc.setPointC(pointC);
		validate();
		repaint();
	}

	public void removeDisk() {
		if (pointA != null) {
			for (int i = 0; i < pointA.length; i++) {
				pointA[i].removeDisc(pointA[i].getDiscOnPoint(), this);
				pointB[i].removeDisc(pointB[i].getDiscOnPoint(), this);
				pointC[i].removeDisc(pointC[i].getDiscOnPoint(), this);
			}
		}
	}

	//awt 中画板
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		int x1, y1, x2, y2;
		x1 = pointA[0].getX();
		y1 = pointA[0].getY() - discHeight / 2;
		x2 = pointA[amountOfDisc - 1].getX();
		y2 = pointA[amountOfDisc - 1].getY() + discHeight / 2;
		g.drawLine(x1, y1, x2, y2);//划线
		x1 = pointB[0].getX();
		y1 = pointB[0].getY() - discHeight / 2;
		x2 = pointB[amountOfDisc - 1].getX();
		y2 = pointB[amountOfDisc - 1].getY() + discHeight / 2;
		g.drawLine(x1, y1, x2, y2);
		x1 = pointC[0].getX();
		y1 = pointC[0].getY() - discHeight / 2;
		x2 = pointC[amountOfDisc - 1].getX();
		y2 = pointC[amountOfDisc - 1].getY() + discHeight / 2;
		g.drawLine(x1, y1, x2, y2);
		g.setColor(Color.blue);
		x1 = pointA[amountOfDisc - 1].getX() - maxDiscWidth / 2;
		y1 = pointA[amountOfDisc - 1].getY() + discHeight / 2;
		x2 = pointC[amountOfDisc - 1].getX() + maxDiscWidth / 2;
		y2 = pointC[amountOfDisc - 1].getY() + discHeight / 2;
		int length = x2 - x1, height = 6;
		g.fillRect(x1, y1, length, height);//填充矩形
		int size = 5;
		for (int i = 0; i < pointA.length; i++) {
			//缩短 width和height  画点
			g.fillOval(pointA[i].getX() - size / 2, pointA[i].getY() - size / 2, size, size);
			g.fillOval(pointB[i].getX() - size / 2, pointB[i].getY() - size / 2, size, size);
			g.fillOval(pointC[i].getX() - size / 2, pointC[i].getY() - size / 2, size, size);
		}
		//画字符串
		g.drawString(towerName[0] + "座", pointA[amountOfDisc - 1].getX(), pointA[amountOfDisc - 1].getY() + 50);
		g.drawString(towerName[1] + "座", pointB[amountOfDisc - 1].getX(), pointB[amountOfDisc - 1].getY() + 50);
		g.drawString(towerName[2] + "座", pointC[amountOfDisc - 1].getX(), pointC[amountOfDisc - 1].getY() + 50);
	}
}

2.3 Disc类设计

Disc类是javax.swing包中JButton类的子类,所创建的对象称作Hannoi塔中的“盘子”。

Tower类有Disc类型的数组disc。disc数组的单元是用Disc创建的对象,被放置在Tower所创建的容器tower中,用来表示tower中的盘。

代码:

package hannuota;

import java.awt.Color;

import javax.swing.JButton;

public class Disc extends JButton {
	int number;
	TowerPoint point;

	Disc() {
		setBackground(Color.cyan);
	}

	public void setNumber(int n) {
		number = n;
	}

	public int getNumber() {
		return number;
	}

	public void setPoint(TowerPoint p) {
		point = p;
	}

	public TowerPoint getPoint() {
		return point;
	}
}

2.4 TowerPoint类设计

TowerPoint类负责在Tower中创建表示位置的塔点对象。

TowerPoint所创建的对象将作为Tower类中TowerPoint型数组pointA、pointB和pointC中的元素。

代码:

package hannuota;

import java.awt.Component;
import java.awt.Container;

public class TowerPoint {
	int x, y;
	boolean haveDisc;
	Disc disc = null;

	public TowerPoint(int x, int y) {
		this.x = x;
		this.y = y;
	}

	public boolean isHaveDisc() {
		return haveDisc;
	}

	public void setHaveDisc(boolean boo) {
		haveDisc = boo;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public boolean equals(TowerPoint p) {
		if (p.getX() == this.getX() && p.getY() == this.getY())
			return true;
		else
			return false;
	}

	public void putDisc(Component com, Container con) {
		disc = (Disc) com;
		con.setLayout(null);
		con.add(disc);
		int w = disc.getBounds().width;
		int h = disc.getBounds().height;
		disc.setBounds(x - w / 2, y - h / 2, w, h);
		haveDisc = true;
		disc.setPoint(this);
		con.validate();
	}

	public Disc getDiscOnPoint() {
		return disc;
	}

	//refresh
	public void removeDisc(Component com, Container con) {
		if (com != null)
			con.remove(com);
		con.validate();
	}
}

2.5 HandleMouse类设计

HandleMouse类创建的对象负责处理鼠标事件。

HandleMouse类实现了MouseListener和MouseMotionListener接口,创建的对象handleMouse是tower容器的成员之一,负责监视tower容器中Disc盘子对象上的鼠标事件。

当用户用鼠标单击tower中的盘子,并拖动鼠标时,handleMouse对象负责给出移动盘子的有关算法。重写了mousePressed、mouseDragged、mouseReleased等方法;

代码:

package hannuota;

import java.awt.Container;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

//cxsjjssj程序设计基础设计

public class HandleMouse implements MouseListener, MouseMotionListener {
	TowerPoint[] pointA, pointB, pointC;
	TowerPoint startPoint = null, endPoint = null;
	int leftX, leftY, x0, y0;
	boolean move = false, countTime = false;
	Container con;

	HandleMouse(Container con) {
		this.con = con;
	}

	public void setPointA(TowerPoint[] pointA) {
		this.pointA = pointA;
	}

	public void setPointB(TowerPoint[] pointB) {
		this.pointB = pointB;
	}

	public void setPointC(TowerPoint[] pointC) {
		this.pointC = pointC;
	}

	//鼠标按下
	public void mousePressed(MouseEvent e) {
		move = false;
		Disc disc = null;
		disc = (Disc) e.getSource();
		startPoint = disc.getPoint();
		x0 = e.getX();
		y0 = e.getY();
		int m = 0;
		for (int i = 0; i < pointA.length; i++) {
			if (pointA[i].equals(startPoint)) {
				m = i;
				if (m > 0 && (pointA[m - 1].isHaveDisc() == false)) {
					move = true;
					break;
				} else if (m == 0) {
					move = true;
					break;
				}
			}
		}

		for (int i = 0; i < pointB.length; i++) {
			if (pointB[i].equals(startPoint)) {
				m = i;
				if (m > 0 && (pointB[m - 1].isHaveDisc() == false)) {
					move = true;
					break;
				} else if (m == 0) {
					move = true;
					break;
				}
			}
		}
		
		for (int i = 0; i < pointC.length; i++) {
			if (pointC[i].equals(startPoint)) {
				m = i;
				if (m > 0 && (pointC[m - 1].isHaveDisc() == false)) {
					move = true;
					break;
				} else if (m == 0) {
					move = true;
					break;
				}
			}
		}
	}

	//鼠标移动MouseMotionListener
	public void mouseMoved(MouseEvent e) {
	}
	//鼠标拖动MouseMotionListener
	public void mouseDragged(MouseEvent e) {
		Disc disc = null;
		disc = (Disc) e.getSource();
		leftX = disc.getBounds().x;
		leftY = disc.getBounds().y;
		int x = e.getX();
		int y = e.getY();
		leftX = leftX + x;
		leftY = leftY + y;
		if (move == true)
			disc.setLocation(leftX - x0, leftY - y0);
	}
	
	//鼠标释放
	public void mouseReleased(MouseEvent e) {
		Disc disc = null;
		disc = (Disc) e.getSource();
		//矩形类
		Rectangle rect = disc.getBounds();
		boolean location = false;
		int x = -1, y = -1;
		for (int i = 0; i < pointA.length; i++) {
			x = pointA[i].getX();
			y = pointA[i].getY();
			if (rect.contains(x, y)) {
				endPoint = pointA[i];
				if (i == pointA.length - 1 && endPoint.isHaveDisc() == false) {
					location = true;
					break;
				} else if (i < pointA.length - 1 && pointA[i + 1].isHaveDisc() == true && endPoint.isHaveDisc() == false
						&& pointA[i + 1].getDiscOnPoint().getNumber() > disc.getNumber()) {
					location = true;
					break;
				}
			}
		}
		for (int i = 0; i < pointB.length; i++) {
			x = pointB[i].getX();
			y = pointB[i].getY();
			if (rect.contains(x, y)) {
				endPoint = pointB[i];
				if (i == pointB.length - 1 && endPoint.isHaveDisc() == false) {
					location = true;
					break;
				} else if (i < pointB.length - 1 && pointB[i + 1].isHaveDisc() == true && endPoint.isHaveDisc() == false
						&& pointB[i + 1].getDiscOnPoint().getNumber() > disc.getNumber()) {
					location = true;
					break;
				}
			}
		}
		for (int i = 0; i < pointC.length; i++) {
			x = pointC[i].getX();
			y = pointC[i].getY();
			if (rect.contains(x, y)) {
				endPoint = pointC[i];
				if (i == pointC.length - 1 && endPoint.isHaveDisc() == false) {
					location = true;
					break;
				} else if (i < pointC.length - 1 && pointC[i + 1].isHaveDisc() == true && endPoint.isHaveDisc() == false
						&& pointC[i + 1].getDiscOnPoint().getNumber() > disc.getNumber()) {
					location = true;
					break;
				}
			}
		}
		if (endPoint != null && location == true) {
			endPoint.putDisc(disc, con);
			startPoint.setHaveDisc(false);
		} else
			startPoint.putDisc(disc, con);
	}

	//鼠标进入
	public void mouseEntered(MouseEvent e) {
	}
	//鼠标离开
	public void mouseExited(MouseEvent e) {
	}
	//鼠标单击
	public void mouseClicked(MouseEvent e) {
	}
}

2.6  AutoMoveDisc类

AutoMoveDisc类创建的对象负责自动移动盘子从一个座到另一个座。

AutoMoveDisc类实现了ActionListener接口,创建的对象autoMoveDisc是Tower的成员之一。

代码:

package hannuota;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;

public class AutoMoveDisc extends JDialog implements ActionListener {
	int amountOfDisc = 3;
	TowerPoint[] pointA, pointB, pointC;
	char[] towerName;
	Container con;
	StringBuffer moveStep;
	JTextArea showStep;
	JButton bStart, bStop, bContinue, bClose;
	Timer time;
	int i = 0, number = 0;

	AutoMoveDisc(Container con) {
		setModal(true);
		setTitle("自动演示搬盘子过程");
		this.con = con;
		moveStep = new StringBuffer();
		time = new Timer(100, this);
		time.setInitialDelay(10);
		showStep = new JTextArea(10, 12);
		bStart = new JButton("演示");
		bStop = new JButton("暂停");
		bContinue = new JButton("继续");
		bClose = new JButton("关闭");
		bStart.addActionListener(this);
		bStop.addActionListener(this);
		bContinue.addActionListener(this);
		bClose.addActionListener(this);
		JPanel south = new JPanel();
		south.setLayout(new FlowLayout());
		south.add(bStart);
		south.add(bStop);
		south.add(bContinue);
		south.add(bClose);
		add(new JScrollPane(showStep), BorderLayout.CENTER);
		add(south, BorderLayout.SOUTH);
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		towerName = new char[3];
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				time.stop();
				setVisible(false);
			}
		});
	}

	public void setPointA(TowerPoint[] pointA) {
		this.pointA = pointA;
	}

	public void setPointB(TowerPoint[] pointB) {
		this.pointB = pointB;
	}

	public void setPointC(TowerPoint[] pointC) {
		this.pointC = pointC;
	}

	public void setTowerName(char name[]) {
		if (name[0] == name[1] || name[0] == name[2] || name[1] == name[2]) {
			towerName[0] = 'A';
			towerName[1] = 'B';
			towerName[2] = 'C';
		} else
			towerName = name;
	}

	public void setAmountOfDisc(int n) {
		amountOfDisc = n;
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == time) {
			number++;
			char cStart, cEnd;
			if (i <= moveStep.length() - 2) {
				cStart = moveStep.charAt(i);
				cEnd = moveStep.charAt(i + 1);
				showStep.append("(" + number + ")从" + cStart + "座搬一个盘子到" + cEnd + "座\n");
				autoMoveDisc(cStart, cEnd);
			}
			i = i + 2;
			if (i >= moveStep.length() - 1) {
				time.stop();
			}
		} else if (e.getSource() == bStart) {
			if (moveStep.length() == 0) {
				if (time.isRunning() == false) {
					i = 0;
					moveStep = new StringBuffer();
					setMoveStep(amountOfDisc, towerName[0], towerName[1], towerName[2]);
					number = 0;
					time.start();
				}
			}
		} else if (e.getSource() == bStop) {
			if (time.isRunning() == true)
				time.stop();
		} else if (e.getSource() == bContinue) {
			if (time.isRunning() == false)
				time.restart();
		} else if (e.getSource() == bClose) {
			time.stop();
			setVisible(false);
		}
	}

	//key  算法
	private void setMoveStep(int amountOfDisc, char one, char two, char three) {
		if (amountOfDisc == 1) {
			moveStep.append(one);
			moveStep.append(three);
		} else {
			setMoveStep(amountOfDisc - 1, one, three, two);
			moveStep.append(one);
			moveStep.append(three);
			setMoveStep(amountOfDisc - 1, two, one, three);
		}
	}

	private void autoMoveDisc(char cStart, char cEnd) {
		Disc disc = null;
		if (cStart == towerName[0]) {
			for (int i = 0; i < pointA.length; i++) {
				if (pointA[i].isHaveDisc() == true) {
					disc = pointA[i].getDiscOnPoint();
					pointA[i].setHaveDisc(false);
					break;
				}
			}
		}
		if (cStart == towerName[1]) {
			for (int i = 0; i < pointB.length; i++) {
				if (pointB[i].isHaveDisc() == true) {
					disc = pointB[i].getDiscOnPoint();
					pointB[i].setHaveDisc(false);
					break;
				}
			}
		}
		if (cStart == towerName[2]) {
			for (int i = 0; i < pointC.length; i++) {
				if (pointC[i].isHaveDisc() == true) {
					disc = pointC[i].getDiscOnPoint();
					pointC[i].setHaveDisc(false);
					break;
				}
			}
		}
		TowerPoint endPoint = null;
		int i = 0;
		if (cEnd == towerName[0]) {
			for (i = 0; i < pointA.length; i++) {
				if (pointA[i].isHaveDisc() == true) {
					if (i > 0) {
						endPoint = pointA[i - 1];
						break;
					} else if (i == 0)
						break;
				}
			}
			if (i == pointA.length)
				endPoint = pointA[pointA.length - 1];
		}
		if (cEnd == towerName[1]) {
			for (i = 0; i < pointB.length; i++) {
				if (pointB[i].isHaveDisc() == true) {
					if (i > 0) {
						endPoint = pointB[i - 1];
						break;
					} else if (i == 0)
						break;
				}
			}
			if (i == pointB.length)
				endPoint = pointB[pointB.length - 1];
		}
		if (cEnd == towerName[2]) {
			for (i = 0; i < pointC.length; i++) {
				if (pointC[i].isHaveDisc() == true) {
					if (i > 0) {
						endPoint = pointC[i - 1];
						break;
					} else if (i == 0)
						break;
				}
			}
			if (i == pointC.length)
				endPoint = pointC[pointC.length - 1];
		}
		if (endPoint != null && disc != null) {
			endPoint.putDisc(disc, con);
			endPoint.setHaveDisc(true);
		}
	}
}

3 运行界面展示

图3-1 选择级别界面

 

图3-2 高级玩法界面

 图3-3 中级玩法自动演示界面


4 总结

        利用Java+swing实现界面,可利用鼠标事件进行操作盘子的移动,也可通过自动演示进行盘子的移动;

参考教程:Python 汉诺塔 | 菜鸟教程 (runoob.com)

  • 10
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
汉诺塔问题是一个经典的递归问题,使用C语言可以很好地解决。 汉诺塔问题是将若干个圆盘从一个柱子移动到另一个柱子上的问题。规则是每次只能移动一个圆盘,而且大圆盘不能放在小圆盘上面。 解决这个问题的思路是通过递归来实现。我们可以把它分解为三个子问题:将n-1个盘子从起始柱移动到辅助柱,将最大的第n个盘子从起始柱移动到目标柱,最后将n-1个盘子从辅助柱移动到目标柱。然后利用递归调用来分别解决这三个子问题。 下面是一个简单的C语言实现汉诺塔问题的代码: ```c #include <stdio.h> void hanoi(int n, char from, char to, char temp) { if (n == 1) { printf("Move disk 1 from %c to %c\n", from, to); return; } hanoi(n - 1, from, temp, to); printf("Move disk %d from %c to %c\n", n, from, to); hanoi(n - 1, temp, to, from); } int main() { int num_disks = 3; hanoi(num_disks, 'A', 'C', 'B'); return 0; } ``` 上述代码首先定义了一个hanoi函数,该函数接受一个整数n,以及三个字符参数from、to、temp,分别表示起始柱、目标柱和辅助柱。当n等于1时,表示只有一个圆盘需要移动,直接将圆盘从起始柱移动到目标柱即可。否则,使用递归调用先将n-1个盘子从起始柱移动到辅助柱,然后再将最大的盘子从起始柱移动到目标柱,最后再将n-1个盘子从辅助柱移动到目标柱。 在main函数中,我们定义了一个num_disks变量表示总共有几个圆盘需要移动。然后调用hanoi函数传入起始柱为A,目标柱为C,辅助柱为B。 运行上述代码,会将每一步的移动过程打印出来,如下所示: ``` Move disk 1 from A to C Move disk 2 from A to B Move disk 1 from C to B Move disk 3 from A to C Move disk 1 from B to A Move disk 2 from B to C Move disk 1 from A to C ``` 以上就是使用C语言实现汉诺塔问题的简单代码和运行结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值