awt,swing을 이용해 숫자 순서 맞추기 게임을 만들어보자
코드
package com.koreait.layoutTest;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class PuzzleGameActionListener extends JFrame implements ActionListener {
JPanel puzzlePanel = new JPanel(new GridLayout(4, 4)); // 퍼즐 버튼을 올려서 윈도우의 가운데에 배치할 패널
JButton[] puzzleButton = new JButton[16]; // 퍼즐 버튼
String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"}; // 퍼즐에 올릴 숫자
JButton startButton = new JButton("시작"); // 시작(섞기) 버튼
Random random = new Random();
public PuzzleGameActionListener() {
setTitle("ActionListener");
setBounds(1000, 100, 400, 500);
// Frame과 JFrame의 기본 레이아웃은 BorderLayout 이므로 별도로 레이아웃을 지정하지 않아도 상관없다.
setLayout(new BorderLayout());
// 퍼즐 버튼을 BorderLayout의 CENTER에 올리는 메소드를 실행한다.
viewPuzzle();
// 시작 버튼을 BorderLayout SOUTH에 올린다.
startButton.setFont(new Font("궁서체", Font.BOLD, 50));
startButton.setPreferredSize(new Dimension(400, 100));
startButton.addActionListener(this);
add(startButton, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
// 패널에 퍼즐 버튼을 올려서 윈도우의 CENTER에 올려주는 메소드
private void viewPuzzle() {
for (int i = 0; i < puzzleButton.length; i++) {
puzzleButton[i] = new JButton(numbers[i]);
puzzleButton[i].setFont(new Font("Dialog", Font.BOLD, 40));
puzzleButton[i].addActionListener(this);
puzzlePanel.add(puzzleButton[i]);
if (puzzleButton[i].getActionCommand().equals("16")) {
puzzleButton[i].setVisible(false);
}
}
add(puzzlePanel, BorderLayout.CENTER);
}
public static void main(String[] args) {
PuzzleGameActionListener window = new PuzzleGameActionListener();
}
@Override
public void actionPerformed(ActionEvent e) {
// 어떤 버튼에서 ActionListener가 실행되었나 판단해서 적절한 코딩을 한다.
if (e.getActionCommand().equals("시작")) {
// 시작 버튼에서 ActionListener가 실행되면 퍼즐(numbers 배열)을 섞어준다.
for (int i = 0; i < 1000000; i++) {
int r = random.nextInt(15) + 1;
String temp = numbers[0];
numbers[0] = numbers[r];
numbers[r] = temp;
}
} else {
// 퍼즐 버튼에서 ActionListener가 실행되면 ActionListener가 실행된 버튼이 몇번째 버튼인가 판단한다.
int i;
for (i = 0; i < puzzleButton.length; i++) {
// 퍼즐의 i번째 버튼의 ActionCommend와 ActionListener가 실행된 버튼의 ActionCommend를 비교한다.
if (puzzleButton[i].getActionCommand().equals(e.getActionCommand())) {
break;
}
}
// System.out.println(i + "번째 버튼에서 ActionListener가 실행됨");
// ActionListener가 실행된 버튼의 왼쪽이 비어있다면(ActionCommend가 "16"이면) 자리를 바꾼다.
// 퍼즐의 첫 번째 열에 위치한 버튼(0, 4, 8, 12 번째 버튼)에서는 왼쪽과 자리를 바꾸는 동작이 실행되면 안된다.
if (i % 4 != 0) {
if (puzzleButton[i - 1].getActionCommand().equals("16")) {
String temp = numbers[i - 1];
numbers[i - 1] = numbers[i];
numbers[i] = temp;
JButton tempBtn = puzzleButton[i - 1];
puzzleButton[i - 1] = puzzleButton[i];
puzzleButton[i] = tempBtn;
}
}
// ActionListener가 실행된 버튼의 오른쪽이 비어있다면(ActionCommend가 "16"이면) 자리를 바꾼다.
// 퍼즐의 마지막 번째 열에 위치한 버튼(3, 7, 11, 15 번째 버튼)에서는 오른쪽과 자리를 바꾸는 동작이 실행되면 안된다.
if (i % 4 != 3) {
if (puzzleButton[i + 1].getActionCommand().equals("16")) {
String temp = numbers[i + 1];
numbers[i + 1] = numbers[i];
numbers[i] = temp;
JButton tempBtn = puzzleButton[i + 1];
puzzleButton[i + 1] = puzzleButton[i];
puzzleButton[i] = tempBtn;
}
}
// ActionListener가 실행된 버튼의 위쪽이 비어있다면(ActionCommend가 "16"이면) 자리를 바꾼다.
// 퍼즐의 첫 번째 행에 위치한 버튼(0, 1, 2, 3 번째 버튼)에서는 위쪽과 자리를 바꾸는 동작이 실행되면 안된다.
if (i / 4 != 0) {
if (puzzleButton[i - 4].getActionCommand().equals("16")) {
String temp = numbers[i - 4];
numbers[i - 4] = numbers[i];
numbers[i] = temp;
JButton tempBtn = puzzleButton[i - 4];
puzzleButton[i - 4] = puzzleButton[i];
puzzleButton[i] = tempBtn;
}
}
// ActionListener가 실행된 버튼의 아래쪽이 비어있다면(ActionCommend가 "16"이면) 자리를 바꾼다.
// 퍼즐의 마지막 행에 위치한 버튼(12, 13, 14, 15 번째 버튼)에서는 아래쪽과 자리를 바꾸는 동작이 실행되면 안된다.
if (i / 4 != 3) {
if (puzzleButton[i + 4].getActionCommand().equals("16")) {
String temp = numbers[i + 4];
numbers[i + 4] = numbers[i];
numbers[i] = temp;
JButton tempBtn = puzzleButton[i + 4];
puzzleButton[i + 4] = puzzleButton[i];
puzzleButton[i] = tempBtn;
}
}
}
// 컨테이너에 배치한 컴포넌트가 재배치 또는 변경되면 기존의 컴포넌트를 모두 제거하고 다시 넣어준다.
// 컴포넌트가 setVisible(false)가 실행되서 보이지 않는 상태일 경우 remove() 메소드로 제거할 수 없으므로 반드시 setVisible(true)를
// 실행해서 보이는 상태로 변경한 다음 제거해야 한다.
for (int i = 0; i < puzzleButton.length; i++) {
puzzleButton[i].setVisible(true);
puzzlePanel.remove(puzzleButton[i]);
}
viewPuzzle();
revalidate();
// 퍼즐을 맞췄나 검사한다.
/*
int count = 0;
for (int i = 0; i < puzzleButton.length - 1; i++) {
if (i + 1 == Integer.parseInt(puzzleButton[i].getActionCommand())) {
count++;
}
}
if (count == 15) {
JOptionPane.showMessageDialog(null, "맞췄다~~~~~ 축하해~~~~~");
// System.exit(0);
}
*/
good: // 레이블
while (true) {
for (int i = 0; i < puzzleButton.length - 1; i++) {
if (i + 1 != Integer.parseInt(puzzleButton[i].getActionCommand())) {
// break만 사용하면 break가 사용된 반복문이나 switch 명령을 탈출하지만 break 명령에 레이블을 지정하면 지정된
// 레이블에 해당되는 반복을 탈출한다.
break good; // good이라는 레이블이 지정된 반복(while)을 탈출한다.
}
}
JOptionPane.showMessageDialog(null, "맞췄다~~~~~ 축하해~~~~~");
break;
}
}
}
과정
- (PuzzleGameActionListener 클래스)
- 윈도우 가운데에 퍼즐을 맞출 숫자들이 들어갈 패널을 4x4(정사각형) 크기로 생성한다.
- 16개의 퍼즐 버튼 배열을 생성한다.
- 생성된 퍼즐 위에 올릴 숫자를 각 배열에 넣는다.
- 윈도우 하단에 들어갈 시작 버튼을 생성한다.
- 시작 버튼을 누를 때 숫자를 랜덤하게 바꿀 random 객체를 생성한다.
- Title을 PuzzleGame으로 지정하고 윈도우가 생성될 위치와 크기를 지정한다.
- BorderLayout으로 레이아웃을 지정한다. (Frame과 JFrame의 기본 레이아웃은 BorderLayout이므로 생략해도 된다.)
- (viewPuzzle 메소드)
for문을 이용해 puzzleButton의 길이만큼 반복해 패널에 퍼즐 버튼을 차례대로 올려서 윈도우의 CENTER에
올려주는 메서드를 작성한다. - PuzzleGameActionListener 클래스에서 viewPuzzle 메서드를 실행하는 코드를 입력한다.
- 시작버튼을 BorderLayout SOUTH에 올리고 폰트,크기를 지정해 입력한다.
- 창을 닫기 위한 코드를 입력한다.
- setVisible(true) 를 입력한다.
- (@Override)
시작 버튼에서 ActionListener가 실행되면 퍼즐(numbers 배열)을 섞어주는 코드를 입력한다.
퍼즐 버튼에서 ActionListener가 실행되면 실행된 버튼이 몇 번째 버튼인가 판단한다.
퍼즐의 i번째 버츤의 ActionCommend와 ActionListener가 실행된 버튼의 ActionCommend를 비교한다.
ActionListener가 실행된 버튼의 왼쪽이 비어있다면(ActionCommend가 16이면) 자리를 바꾼다.
퍼즐의 첫 번째 열에 위치한 버튼 (0,4,8,12번째 버튼)에서는 왼쪽과 자리를 바꾸는 동작이 실행되면 안된다.
각가 오른쪽,위쪽,아래쪽이 비어있으면 (16을 안보이게 설정하기 때문에 16이 비어있는 버튼이라고 보면 된다)
위치를 바꾸는 코드를 작성한다.
컨테이너에 배치한 컴포넌트가 재배치 또는 변경되면 기존의 컴포넌트를 모두 제거하고 다시 넣어준다.
컴포넌트가 setVisible(false)가 실행되서 보이지 않는 상태일 경우 remove() 메소드로 제거할 수 없으므로 반드시 setVisible(true)를 실행해서 보이는 상태로 변경한 다음 제거해야 한다.
viewPuzzle(); revalidate(); 를 실행한다.
퍼즐을 맞췄는지 검사하는 반복문을 레이블로 작성한다. 맞추면 반복문을 탈출하고 메세지를 출력한다. - main 메서드를 만들고 PuzzleGameActionListener 객체의 window를 생성한다.
결과 화면


'JAVA > GUI' 카테고리의 다른 글
[java/GUI] Window Test (움직이기) (0) | 2022.12.20 |
---|---|
[java/GUI] AWT 이벤트처리 (0) | 2022.12.19 |
[java/GUI] Swing (스윙) (0) | 2022.12.12 |
[java/GUI] Dimension Class (0) | 2022.12.12 |
[java/GUI] AWT (Abstract Window Toolkit) (1) | 2022.12.12 |