티스토리 뷰
JAVA의 JFrame class를 사용하여 2차원 매트릭스를 일정한 순서에 따라 채우는 알고리즘을 구현하였다.
최근 한 달 정도 C++ 언어를 통해 OpenGL을 공부하다보니 JAVA가 어색해져버렸다...이런
다시 익숙해지는 차원에서, 그리고 내가 작성한 코드조차 이해하지 못하면 안되므로,
이곳에 정리를 해보고자 한다.
우선 내가 무엇을 구현하였는지 먼저 보도록 하자.
위의 GIF 영상과 같이 사선 방향으로 채워지도록 코딩을 해봤다.
특징을 정리해보면
1. public class Inclined extends JFrame implements Runnable
1) JFrame을 상속받아서 GUI를 나타내었다.
2) Runnable 인터페이스를 implements하여 쓰레드를 돌려 에니메이션 효과를 주었다.
- run()을 override하여 쓰레드.start()로 구현하였다는 뜻.
2. 알고리즘을 pseudo-algorithm으로 나타내면 다음과 같다.
- 우선 간단한 definition
- Width, Height
- Width : 열의 수
- Height : 행의 수
- 칸 번호, 색칠 번호
- 칸 번호는 일반적으로 공책에 필기하는 순서대로 매긴다. 좌에서 우로, 한칸 내리고 다시 좌에서 우..
- 색칠 번호는 위의 GIF 영상과 같이 파란색이 채워지는 순서대로 매긴다.
- 즉, 특정 칸은 고유의 칸 번호와 색칠 번호를 갖게 된다.
- (0,0)칸의 칸 번호는 0, 색칠 번호도 0
- (1,0)칸의 칸 번호는 Width, 색칠 번호는 1.. 이런식으로
- Pseudo-algorithm
0) int 색칠 번호 = 0; 이전 칸의 좌표 (-1, 0);
1) 현재 칸의 열 좌표 = 이전 칸의 열 좌표 + 1;
현재 칸의 행 좌표 = 이전 칸의 행 좌표 - 1;
2) 만약 1)에서 얻어진 현재 칸의 좌표값이 [경계 조건]을 만족하면 그대로 사용
만족하지 못하면 [경계 밖 처리]를 하여 새로운 현재 칸의 좌표값을 얻어냄.
3) 현재 칸의 칸 번호는 = 현재 칸의 행 좌표 * Width + 현재 칸의 열 좌표;
현재 칸에게 색칠 번호를 할당하고 색칠 번호++;
색칠이 되었으므로 다음 턴에서는 현재 칸을 이전 칸이라고 부르도록 함.
4) 마지막 칸 ? end : { 1)으로 돌아감 }
3. 실제 코드를 보며 [경계 조건]과 [경계 밖 처리]를 이해해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | package kr.taewookimmr.fillMatrix; import java.awt.Color; import java.awt.Container; import java.awt.GridLayout; import java.awt.Point; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; public class Inclined extends JFrame implements Runnable{ public Container con; public ArrayList<Integer> list_index; public ArrayList<JButton> list_button; public int width = 10; public int height = 10; public int prev = 0; public int now = 0; public int specialStep = 0; public Point nowPosition = new Point(); public Inclined() { this.setLocation(100,100); this.setSize(500, 500); this.setTitle("inclined1"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); con = this.getContentPane(); con.setLayout(new GridLayout(height, width)); this.setVisible(true); list_index = new ArrayList<>(); list_button = new ArrayList<>(); for(int i = 0; i < width*height; i++) { JButton button = new JButton(); con.add(button); this.setVisible(true); list_button.add(button); } Thread thread = new Thread(this); thread.setDaemon(true); thread.start(); } @Override public void run() { for(int i = 0 ; i < width*height; i++) { prev = i != 0 ? list_index.get(i-1) : -1 ; nowPosition.x = prev%width + 1; nowPosition.y = prev/width - 1; if(nowPosition.y == -1){ nowPosition.y = nowPosition.x; nowPosition.x = 0; if(nowPosition.y > height-1) { nowPosition.y = height-1; nowPosition.x = ++specialStep; } } if(nowPosition.y != -1 && nowPosition.x == width) { nowPosition.y = nowPosition.y + width + 1; nowPosition.x = 0; if(nowPosition.y > height-1) { nowPosition.y = height-1; nowPosition.x = ++specialStep; } } now = i!= 0 ? nowPosition.y * width + nowPosition.x : 0; list_index.add(now); list_button.get(now).setText(i +""); list_button.get(now).setBackground(Color.BLUE); list_button.get(now).setForeground(Color.WHITE); try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();} } } public static void main(String[] args) { Inclined inclined = new Inclined(); } } | cs |
4. 경계 조건과 그에 따른 처리에 대해서 자세하게 알아보도록 합시다.
1) 우선 아래 figure.1의 파란색 부분은 해당 알고리즘을 통해 채울 영역에 해당하는 곳이다.
2) 노란색과 주황색 영역은..
현재 칸의 열 좌표 = 이전 칸의 열 좌표 + 1;
현재 칸의 행 좌표 = 이전 칸의 행 좌표 - 1;
위 연산 결과로 위치할 수 있는 영역에 해당한다.
figure.1
3) 코드 69번 줄 ~ 88번 줄의 이중 if문 2개에 의해 아래 그림과 같이 경계 처리가 된다.
- 매트릭스의 aspect ratio(width/height)에 상관없이 유효하게 작동하는 처리문이다.
- 이중 if문 2개로 하지 않고 단일 if문 3개로 표현할 수 있다.
figure.2
'Programming > Java' 카테고리의 다른 글
[JAVA] 2차원 채움 알고리즘_part2 (0) | 2019.02.26 |
---|