이야기박스

Java) 하노이의 탑 < 완성본 > 본문

Programming Language/JAVA

Java) 하노이의 탑 < 완성본 >

박스님 2019. 6. 2. 14:51
반응형

드디어!

하노이의 탑을 완성하였습니다! (짝짝짝)

 

미리 설계를 하고 짠게 아니고

마구잡이로 생각나는대로 하다보니까 오히려 시간이 더 걸린거 같네요.. 하하

설계의 중요성을 다시 한번 깨닫게 됩니다.

 

 

간단한 설명을 하겠습니다.

모두가 아시는 하노이의 탑의 UI버젼입니다.

블록의 이동을 버튼을 통해 하나씩 확인할 수 있도록 했습니다.

 

기본적인 동작만 코딩했으므로 예외처리나 리셋 등 기타 옵션들은 없습니다.

 

 

< 사용한 클래스들 >

 

 

위와 같이 6개의 클래스를 사용하였습니다.

 

1. Main 

프로그램을 실행하기 위한 클래스. JFrame을 사용

 

2. Display

기본 UI를 위한 클래스

버튼의 이벤트들을 담당한다

 

3. Logic 

하노이 탑의 로직을 담당

 

4. HanoiData

하노이 탑에서 각 블록의 정보를 담는다.

 

5. Sequence

각 화면의 시퀀스(단계)를 나타낸다.

예를 들어, 3개의 블록을 가진 하노이의 탑에서 하나의 시퀀스는 3개의 블록 데이터의 집합이다.

 

6. DrawPanel

위에서 얻은 정보를 바탕으로 그림을 그린다 ^__^

 

 

 

< 코드 >

 

 

1. Main

 

 

import javax.swing.*;

public class Main{

	public static void main(String[] args) {
		
		JFrame frame = new JFrame();
		
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Display primary = new Display();
		
		frame.getContentPane().add(primary);
		frame.pack();
		frame.setVisible(true);
	}
	
}

 

 

2. Display

 

 

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;

public class Display extends JPanel{
	private Dimension	displaySize;
	private JLabel		lblTitle, lblAsking;
	private JPanel		subOptions;
	private DrawPanel	mainDisplay;
	private JButton		btnNext, btnPrev, btnExe;
	private JTextField	txtInput;
	private HanoiListener listener;
	
	private Logic		logic;
	private int			nInput, nSequence;
	
	private ArrayList sequence;
	
	public Display() {
		displaySize = new Dimension(800,800);
		this.setPreferredSize(displaySize);
		this.setBackground(Color.black);
		this.setLayout(null);
		
		listener = new HanoiListener();
		nSequence = 1;

		// Top side
		lblTitle = new JLabel("Hanoi Top");
		lblTitle.setForeground(Color.white);
		lblTitle.setFont(new Font("Monofour",Font.ITALIC,40));
		lblTitle.setHorizontalAlignment(SwingConstants.CENTER);
		lblTitle.setBounds(0,0,displaySize.width,displaySize.height/8);
		this.add(lblTitle);
				
		// Main - Display
		mainDisplay = new DrawPanel(displaySize);
		this.add(mainDisplay);		
		
		// Bottom side
		subOptions = new JPanel();
		subOptions.setBackground(Color.black);
		subOptions.setBounds(0, displaySize.height*7/8, displaySize.width, displaySize.height*1/8);
		subOptions.setLayout(null);
		this.add(subOptions);
		
		Font fnt = new Font("Monofour",Font.BOLD,20);
		
		lblAsking = new JLabel("Tops");
		lblAsking.setBounds(50,25,100,50);
		lblAsking.setForeground(Color.white);
		lblAsking.setHorizontalAlignment(SwingConstants.CENTER);
		lblAsking.setFont(fnt);
		subOptions.add(lblAsking);
		
		txtInput = new JTextField();
		txtInput.setBounds(150, 25, 100, 50);
		txtInput.setFont(fnt);
		txtInput.addActionListener(listener);
		subOptions.add(txtInput);
		
		btnExe = new JButton("Confirm");
		btnExe.setBounds(250,25,100,50);
		btnExe.addActionListener(listener);
		subOptions.add(btnExe);
		
		btnPrev = new JButton("Prev");
		btnPrev.setBounds(500,25,100,50);
		btnPrev.addActionListener(listener);
		btnPrev.setEnabled(false);
		subOptions.add(btnPrev);
		
		btnNext = new JButton("Next");
		btnNext.setBounds(600,25,100,50);
		btnNext.addActionListener(listener);
		btnNext.setEnabled(false);
		subOptions.add(btnNext);
	}	// Display()
	
	
	
	private class HanoiListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Object obj = e.getSource();
			
			if((obj == txtInput) || (obj == btnExe)) {
				nInput = Integer.parseInt(txtInput.getText());
				
				logic = new Logic(nInput);	
				btnNext.setEnabled(true);
				txtInput.setText("");
			} else if(obj == btnPrev) {
				nSequence--;
				btnNext.setEnabled(true);
				if(nSequence == 1) {
					btnPrev.setEnabled(false);
				} 
			} else if(obj == btnNext) {
				nSequence++;	
				btnPrev.setEnabled(true);
				if(nSequence == logic.getCount()+1) {
					btnNext.setEnabled(false);
				}
			}
			sequence = logic.getSequence();	
			mainDisplay.setBoard(nSequence-1, logic.getCount());
			mainDisplay.setDataList(sequence.get(nSequence-1).getNowData(),nSequence-1);
						
			mainDisplay.repaint();	
		}	// actionPerformed()	
	}	// HanoiListener class
	
	
}	// Display class

 

 

3. Logic

 

 

import java.util.*;

public class Logic {
	private int count;
	private ArrayList	nowList;	
	private ArrayList		sequence;
	private int	aBar, bBar, cBar;
	
	public Logic(int num) {
		count = 0;
		aBar = num;
		bBar = cBar = 0;
		
	        // initialize Data - nowList
		nowList = new ArrayList();
		for(int i=0; i<num; i++) {
			nowList.add(new HanoiData(i,num));
		}	// for i
		
		// insert to sequence
		ArrayList tmpList = new ArrayList();
		int i=0;
		for(HanoiData data : nowList) {
			tmpList.add(new HanoiData(data, num-i));
			i++;
		}				
		sequence.add(new Sequence(tmpList));
		
		// logic exe
		this.calcHanoi(num,'A','B','C');
	}	// Logic()
	
	public void calcHanoi(int num,char from, char other, char to) {
		
		if (num == 1) {
			++count;
			this.moveBlock(num - 1, from, to);
		} else {
			++count;
			this.calcHanoi(num - 1, from, to, other);
			this.moveBlock(num - 1, from, to);
			this.calcHanoi(num - 1, other, from, to);
		}

	}	// clacHanoi()
	
	public void moveBlock(int position, char from, char to) {
		int tBar;
		
		if(from == 'A') {
			aBar--;
		} else if(from == 'B') {
			bBar--;
		} else  {
			cBar--;
		}
		if(to == 'A') {
			aBar++;
			tBar=aBar;
		} else if(to == 'B') {
			bBar++;
			tBar=bBar;
		} else {
			cBar++;
			tBar=cBar;
		}
		
		for(HanoiData data : nowList) {
			if(data.getPosition() == position) {
				data.changeData(to, tBar);
				break;
			}
		}	// for nowList
		
		
		ArrayList tmpList = new ArrayList();
		for(int i=0; i<nowList.size(); i++){
			tmpList.add(new HanoiData(nowList.get(i),tBar-i));
		}
		sequence.add(new Sequence(tmpList));	
	}	// moveBlock()
	
	public ArrayList	getSequence() { return sequence; }
	public int getCount()	{ return count; }
}	// Logic class

 

 

 

4. HanoiData

 

 

import java.awt.*;


public class HanoiData {
	private Point	ptOne;
	private	int		position, width, height;
	private Color	blockColor;
	private int 	vertic;
	private int		stdx, total, stdPosit;
	private char	location;
	
	public HanoiData(int num, int tot) {
		ptOne = new Point();
		location = 'A';
		
		total = tot;
		position = num;	
		
		stdPosit = total-position;
		
		vertic = 550;
		height = 40;
		
		int r,g,b;
		r = (int)(Math.random()*256);
		g = (int)(Math.random()*256);
		b = (int)(Math.random()*256);
		
		blockColor = new Color(r,g,b);
		
		this.setDatas();
	}	// HanoiData()
	
	public HanoiData(HanoiData data, int x) {
		ptOne = data.getPtOne();
		location = data.getLocation();
		
		total = data.getTotal();
		position = data.getPosition();	

		stdPosit = data.getStdPosit();
		
		vertic = 550;
		height = 40;
		width = data.getWidth();
		blockColor = data.getColor();

		this.setDatas();
	}	// HanoiData()
	
	public void changeData(char change, int bar) {
		location = change;	
		stdPosit = bar;
	}
	
	public void setDatas() {
		int locStd;				
		
		if(location == 'A') {
			locStd = 140;	
		} else if(location == 'B') {
			locStd = 380;	
		} else {
			locStd = 620;	
		}	
		stdx = 90/total;
		
		ptOne.y = vertic - height*stdPosit;
		ptOne.x = locStd - stdx*(position+1);
		width = (locStd - ptOne.x)*2;
	}	// setDatas()
	
	public Point getPtOne()		{ return ptOne; }
	public int getPosition()	{ return position; }
	public int getTotal()		{ return total; }
	public char getLocation()	{ return location; }
	public int getWidth()		{ return width; }
	public int getHeight()		{ return height; }
	public Color getColor()		{ return blockColor; }
	public int getStdPosit()	{ return stdPosit; }
	
}	// HanoiData class

 

 

 

5. Sequence

 

 

import java.util.*;

public class Sequence {
	private ArrayListnow;
	
	public Sequence(ArrayList tmp) {
		now = tmp;
	}	// Sequence()
	
	public ArrayList getNowData() { 	return now;  }
	
}	// Sequence class

 

 

 

6. DrawPanel

 

 

import javax.swing.*;
import java.awt.*;
import java.util.*;

public class DrawPanel extends JPanel {
	private Dimension	dsize;
	private JLabel		lblStatus, lblA, lblB, lblC;
	private JPanel		bottom;
	private Graphics	page;
	private ArrayList	tmpA;
	
	// size 800, 600
	public DrawPanel(Dimension displaySize) {
		this.setBackground(Color.white);
		this.setBounds(0, displaySize.height/8, displaySize.width, displaySize.height*3/4);
		this.setLayout(null);
		dsize = new Dimension(displaySize.width, displaySize.height*3/4);		
		
		lblStatus = new JLabel();
		lblStatus.setBounds(displaySize.width*7/8,0,100,50);
		lblStatus.setText("");
		lblStatus.setForeground(Color.black);
		lblStatus.setFont(new Font("Monofour",Font.ITALIC,25));
		this.add(lblStatus);		
		
		tmpA = new ArrayList();
		
		bottom = new JPanel();
		bottom.setBounds(0,dsize.height-50,dsize.width,50);
		bottom.setBackground(Color.gray);
		bottom.setLayout(null);
		this.add(bottom);
		
		Font fnt = new Font("Monofour",Font.ITALIC,20);
		
		lblA = new JLabel("A");
		lblA.setBounds(135,0,50,50);
		lblA.setFont(fnt);
		lblA.setForeground(Color.white);
		bottom.add(lblA);
		
		lblB = new JLabel("B");
		lblB.setBounds(375,0,50,50);
		lblB.setFont(fnt);
		lblB.setForeground(Color.white);
		bottom.add(lblB);
		
		lblC = new JLabel("C");
		lblC.setBounds(615,0,50,50);
		lblC.setFont(fnt);
		lblC.setForeground(Color.white);
		bottom.add(lblC);
		
	}	// DrawPanel()

	public void drawTops() {
		for(HanoiData data : tmpA) {
			page.setColor(data.getColor());
			page.fillRect(data.getPtOne().x,data.getPtOne().y,data.getWidth(),data.getHeight());		
		}	// for HanoiData data			
	}	// drawTops()
	
	public void pillar() {
		page.fillRect(120,dsize.height/4,40,dsize.height*3/4-50);
		page.fillRect(360,dsize.height/4,40,dsize.height*3/4-50);
		page.fillRect(600,dsize.height/4,40,dsize.height*3/4-50);
	}	// pillar()
	
	public void paintComponent(Graphics p) {
		super.paintComponent(p);
		page = p;		
		
		this.pillar();
		this.drawTops();
	}	// paintComponent()
	
	public void setDataList(ArrayList nowList, int x) {
		for(HanoiData data : nowList) {
			tmpA.add(new HanoiData(data,x));
		}		
	}	// setDataList()
	
	public void setBoard(int num, int goal) {
		lblStatus.setText(num + " / " + goal);
	}
}	// DrawPanel class

 

코드 설명은 생략하겠습니다!

필요하신분은 각자 분석해서.. ㅎㅎ

질문하신다면 답변은 드리겠습니다.

 

위에서 말했듯이 계획없이 중구난방으로 만든 코드다보니..

난잡합니다 ㅎㅎ;;

 

나름 안쓰는 코드는 지운다고 했는데, 아직 남아있을 수도 있겠네요.

꼼꼼히 확인한건 아니어서.. ㅎㅎ

 

그럼 실행화면을 보여드리겠습니다.

 

< 실행 화면 >

012345678

 

 

 

1. 처음에 블록의 개수를 입력합니다.

 

2. 블록이 생성되고, 오른쪽 상단에  (현재 단계 / 총 단계) 가 표시됩니다. 

( 실제로는 텍스트필드도 사라지게 해놨습니다. - 예시에서는 편의상 다시 써넣어 뒀을뿐입니다. )

 

3. prev / next 버튼을 이용하여 각 단계를 이동합니다. 

( 첫 페이지, 마지막 페이지에서는 각각 prev, next 버튼이 disabled 됩니다. )

 

 

 

< 소감 >

 

이번 프로그램을 만들면서 부족한 코딩실력을 다시 절감하게 됬네요. ㅎㅎ

다음번에는 좀더 나은 설계, 그리고 코딩을 해보도록 하겠습니다.

좀더 발전해야죠 하하..

이상으로 UI로 구현한 하노이의 탑! 이었습니다.

반응형

'Programming Language > JAVA' 카테고리의 다른 글

(작성중) Maven Lifecycle  (0) 2019.11.21
(작성중) Maven Repository  (0) 2019.11.19
Java) 하이로우 게임  (1) 2019.06.02
Effective java 3/E - 직렬화 (item 85~90)  (0) 2019.01.16
Effective java 3/E - 동시성 (item 78~84)  (0) 2019.01.11