[Java+swing] Hanoi tower game for automatic demonstration

Posted by zeb on Sat, 08 Jan 2022 12:41:09 +0100

catalogue

1 algorithm and problem description

1.1 problem description

1.2 recursive algorithm

1.3 non recursive algorithm

2 overall design of game program

2.1 HannoiWindow class design

2.2 Tower design

2.3 Disc design

2.4 design of towerpoint class

2.5 design of HandleMouse class

2.6 AutoMoveDisc class

3. Display of operation interface

4 Summary

1 algorithm and problem description

1.1 problem description

Figure 1-1 Hanoi Tower

Suppose there are three towers named a (tower 1), B (tower 2) and c (Tower 3), as shown in Figure 1-1. There are n towers with different diameters on tower X, numbered 1,2,3, A disk of n. Now it is required to move n discs on tower a to tower c and stack them in the same order. The following rules must be followed when moving the discs:

(1) Only one disc can be moved at a time;

(2) The disc can be inserted on any tower seat in a, B and C;

(3) At no time should a larger disc be pressed against a smaller disc.

1.2 recursive algorithm

Define N as the number of discs:

When N=1, a > C;

When N=2, a > b | a > C | b > C;

When N=3, a > C, a > b, C > b | a > C | b > A, b > C, a > C;

...

Code and code idea:

	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);
		}
	}

Using the idea of divide and conquer

The first step is to operate the disk (N-1) from A to B before performing the operation of the maximum disk (N) to C;

Step 2: execute the operation from the maximum disk (N) to C;

The third step is to operate the disk (N-1) from B to C after performing the operation of the maximum disk (N) to C;

Only care about the upper layer at a time. The upper layer is considered only at the upper layer ----- recursion

1.3 non recursive algorithm

Non recursive method is to find rules:

Column A has n plates, called the source column Move to column C # and call it the destination column Column B is called the middle column
f(n) = (2^n) - 1 time to move all to column C
The maximum disk, disk n, moves only once in the whole moving process, disk n-1 moves twice, and disk i moves
2^(n-i) times
Disk 1 moves the most times, once every 2 times
The 2k+1 movement is disk 1, and the k+1 movement is disk 1
Disk 2 moves 4k+2, and disk 2 moves k+1

The (2^s)k+2^(s-1) th move is disk S. at this time, disk s has been moved k+1 times
Every 2^s times, disk s is moved
The first time disk s was moved was at 2^(s-1)
The second time disk s was moved was at 2^s+2^(s-1)
The k+1 move of disk s is at the k*2^s+2^(s-1)


A -- > b, B -- > C, C -- > A is called clockwise, and a -- > C, C -- > b, B -- > A is called counterclockwise
Maximum disk n disk moves only once: a -- > C it moves counterclockwise
n-1 moves twice: a -- > b, B -- > C, clockwise

Code and code idea:

public static void hanoi_f(int n) {
		int s;// From top to bottom
		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;//Find disk s moved in step i
			k = i / t;// Get the s-th disk and the number of moves
			if (n % 2 == s % 2) {// anti-clockwise
				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 {// Clockwise
				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");
			}
		}

	}

Enumerate steps 1, 2, 3, 4 ······· i, i+1, i+2, ·····.

The first step is to obtain the number of disks moved in step i, and convert it according to (2^s)k+2^(s-1)=i, so that i%(2^s) =2^(s-1) and t=2^s; Then i%t=t/2;

The second step is to obtain the second movement of disk S, according to (2^s)k+2^(s-1)=i, k=i/(2^s), that is, k=i/t;

The third step , finally, determine the specific moving steps according to the period T , and parity ,

2 overall design of game program

When designing hannoi tower, you need to write six java source files: hannoiwindow java,Tower.java,TowerPoint.java,Disc.java,HandleMouse.java and automovedisc java.

In addition to the classes given in the six java source files to be written, Hannoi tower also needs some important classes provided by the Java system, such as JMenuBar, JMenu, JMenuItem and JButton. Some important classes used by Hannoi tower and their combination relationship are shown in Figure 2-1:

Figure 2-1 combined connection between classes

2.1 HannoiWindow class design

The HannoiWindow class is responsible for creating the main window of the Hannoi tower. This class contains the main method. The Hannoi tower executes from this class.

There are five important types of objects, an int base data, and an array of char types in the member variables of the HannoiWindow class. The five types of objects are Tower, JMenuBar, JMenu, JMenuItem, and JButton objects.

The event realizes the change between windows, and changes the game level according to the different variable amountOfDisc, that is, the number of disc;

code:

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("Select level");
		oneGradeItem = new JMenuItem("primary");
		twoGradeItem = new JMenuItem("intermediate");
		threeGradeItem = new JMenuItem("senior");
		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("restart");
		renew.addActionListener(this);
		autoButton = new JButton("Automatic presentation");
		autoButton.addActionListener(this);
		JPanel north = new JPanel();
		north.add(renew);
		north.add(autoButton);
		String mess = "Remove all the plates from the" + towerName[0] + "Seat handling to" + towerName[1] + "Seat or" + towerName[2] + "Seat";
		JLabel hintMess = new JLabel(mess, JLabel.CENTER);
		north.add(hintMess);
		add(north, BorderLayout.NORTH);
		setResizable(false);
		setVisible(true);
		setBounds(60, 60, 460, 410);
		//Ensure that the components have a valid layout
		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 design

The Tower class is javax The subclass of the Jpanel container in the swing package. The created container is added to the center of the HannoiWindow window window.

There are four important types of objects, an int primitive data and a char array in the member variables of the Tower class. The four types of objects are Disc, TowerPoint, HandleMouse, and AutoMoveDisc objects.

code:

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;//The disc below is wider
			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 middle drawing board
	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);//Scribe
		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);//Fill rectangle
		int size = 5;
		for (int i = 0; i < pointA.length; i++) {
			//Shorten width and height and draw dots
			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);
		}
		//Draw string
		g.drawString(towerName[0] + "Seat", pointA[amountOfDisc - 1].getX(), pointA[amountOfDisc - 1].getY() + 50);
		g.drawString(towerName[1] + "Seat", pointB[amountOfDisc - 1].getX(), pointB[amountOfDisc - 1].getY() + 50);
		g.drawString(towerName[2] + "Seat", pointC[amountOfDisc - 1].getX(), pointC[amountOfDisc - 1].getY() + 50);
	}
}

2.3 Disc design

The Disc class is javax The subclass of JButton class in swing package. The created object is called the "plate" in Hannoi tower.

The tower class has an array disc of type disc. The cells of disc array are objects created with disc, which are placed in the container tower created by tower to represent the disks in tower.

code:

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 design of towerpoint class

The TowerPoint class is responsible for creating a Tower point object representing the location in the Tower.

Objects created by TowerPoint will be used as elements in TowerPoint type arrays pointA, pointB, and pointC in the Tower class.

code:

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 design of HandleMouse class

The object created by the HandleMouse class is responsible for handling mouse events.

The handlemouse class implements the MouseListener and MouseMotionListener interfaces. The created object handlemouse is one of the members of the tower container and is responsible for monitoring mouse events on the Disc object in the tower container.

When the user clicks the tray in the tower and drags the mouse, the handleMouse object is responsible for giving the relevant algorithm for moving the tray. Rewriting mousePressed, mouseDragged, mouseReleased and other methods;

code:

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;

//Basic design of cxsjjssj programming

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;
	}

	//Mouse down
	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;
				}
			}
		}
	}

	//Mouse movement MouseMotionListener
	public void mouseMoved(MouseEvent e) {
	}
	//Drag the MouseMotionListener with the mouse
	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);
	}
	
	//Mouse release
	public void mouseReleased(MouseEvent e) {
		Disc disc = null;
		disc = (Disc) e.getSource();
		//Rectangular class
		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);
	}

	//Mouse entry
	public void mouseEntered(MouseEvent e) {
	}
	//Mouse away
	public void mouseExited(MouseEvent e) {
	}
	//Mouse click
	public void mouseClicked(MouseEvent e) {
	}
}

2.6 AutoMoveDisc class

The object created by the AutoMoveDisc class is responsible for automatically moving dishes from one seat to another.

The automovedisc class implements the ActionListener interface, and the created object automovedisc is one of the members of the Tower.

code:

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("Automatic demonstration of plate handling process");
		this.con = con;
		moveStep = new StringBuffer();
		time = new Timer(100, this);
		time.setInitialDelay(10);
		showStep = new JTextArea(10, 12);
		bStart = new JButton("demonstration");
		bStop = new JButton("suspend");
		bContinue = new JButton("continue");
		bClose = new JButton("close");
		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 + ")from" + cStart + "Move a plate to the seat" + cEnd + "Seat\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 algorithm
	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. Display of operation interface

Figure 3-1 select level interface

 

Figure 3-2 advanced play interface

Figure 3-3 intermediate play automatic demonstration interface

4 Summary

Using Java+swing to realize the interface, you can use mouse events to operate the movement of the plate, and you can also move the plate through automatic demonstration;

Reference tutorial: Python Hanoi Tower rookie tutorial (runoob.com)

Topics: Java swing