이전 글: Java Swing 예제: 다차원 배열 표시하기 (기초 설정 방법, for문으로 swing 요소 반복 등)

for문으로 생성한 컴포넌트에 대한 접근 방법은 다음과 같습니다.

1. 컴포넌트들의 배열을 뽑아 인덱스 번호로 접근하는 방법
JPanel nineRoom = new JPanel();
(...)
  for(int i = 0; i < 9; i++) {
    JButton tempButton = new JButton("");
    tempButton.setFont(new Font("Impact", Font.PLAIN, 22));
    nineRoom.add(tempButton);
  }
    
(...)
String btnText1 = ((JButton)nineRoom.getComponent(0)).getText();
String btnText2 = ((JButton)nineRoom.getComponent(1)).getText();
(...)

 

2. 마우스 클릭 이벤트를 각 버튼마다 부여해 클릭한 위치값으로 컴포넌트를 얻어내는 방법
MouseListener ml = new MouseAdapter() {
  @Override
  public void mouseClicked(MouseEvent e) {
    JButton tempButton = (JButton)e.getComponent();
    tempButton.setText("바꿀 텍스트");
(...)
  }
}

 

* 이벤트 부여 방법
for(Component c : nineRoom.getComponents()) {
  c.addMouseListener(ml);
}

 


예제: 틱택토(Tic Tac Toe)

틱택토라고 3칸오목짜리 게임이 있는데 프로그래밍 예제로 많이 만드는 편입니다. 이 예제는 인공지능 컴퓨터와 대결하는 것은 아니고 아직은 한 사람이 일인이역으로 클릭하는 수준입니다.


package blog.gui.tictactoe;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TicTacToe1 extends JFrame {
private static final long serialVersionUID = 1L;
JLabel title = new JLabel("TicTacToe | ");
JLabel dispCurrentPlayer = new JLabel("Player 0");
private int score1 = 0;
private int score2 = 0;
JLabel scoreLabel = new JLabel(" | " + score1 + " : " + score2);
JButton startNewGame = new JButton("새 게임 시작");
JPanel titleBar = new JPanel();
JPanel nineRoom = new JPanel();
private final int START_PLAYER = 1;
private boolean isGameEnd = false;
TicTacToeCore ttt = new TicTacToeCore(START_PLAYER);
public TicTacToe1(){
super("TicTacToe");
this.setSize(400,300);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.drawWindow();
this.setVisible(true);
}
public void drawWindow() {
titleBar.add(title);
titleBar.add(dispCurrentPlayer);
titleBar.add(scoreLabel);
titleBar.add(startNewGame);
dispCurrentPlayer.setText("Player " + START_PLAYER);
add(titleBar, BorderLayout.NORTH);
nineRoom.setLayout(new GridLayout(3,3));
for(int i = 0; i < 9; i++) {
JButton tempButton = new JButton("");
tempButton.setFont(new Font("Impact", Font.PLAIN, 22));
nineRoom.add(tempButton);
}
add(nineRoom, BorderLayout.CENTER);
MouseListener ml = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
JButton tempButton = (JButton)e.getComponent();
// System.out.println(ttt.getCurrentPlayerNum());
if(isGameEnd) {
return;
}
if(tempButton.getText().equals("O") || tempButton.getText().equals("X")) {
JOptionPane.showMessageDialog(nineRoom, "이미 둔 곳입니다.");
return;
}
else if(ttt.getCurrentPlayerNum() == 1) {
tempButton.setText("O");
dispCurrentPlayer.setText("Player " + 2);
} else {
tempButton.setText("X");
dispCurrentPlayer.setText("Player " + 1);
}
ttt.changeTurn();
System.out.print("(" + e.getX() + ", " + e.getY() + ") ");
int[][] ticArr = new int[3][3];
for(int i = 0; i < ticArr.length; i++) {
for(int j = 0; j < ticArr[0].length; j++) {
String pl = ((JButton)nineRoom.getComponent(j + i * 3)).getText();
if(pl.equals("O")) ticArr[i][j] = 1;
else if(pl.equals("X")) ticArr[i][j] = 2;
else ticArr[i][j] = 0;
}
}
int result = ttt.inputCurrentStage(ticArr);
System.out.println("result: " + result);
if(result == 1 || result == 2) {
JOptionPane.showMessageDialog(nineRoom, "플레이어 " + result + "의 승리입니다.");
if(result == 1) {
score1++;
} else {
score2++;
}
scoreLabel.setText(" | " + score1 + " : " + score2);
isGameEnd = true;
} else if (result == 99) {
JOptionPane.showMessageDialog(nineRoom, "비겼습니다.");
isGameEnd = true;
}
}
};
for(Component c : nineRoom.getComponents()) {
c.addMouseListener(ml);
}
startNewGame.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ttt.resetGame(START_PLAYER);
isGameEnd = false;
for(int i = 0; i < nineRoom.getComponents().length; i++) {
((JButton)nineRoom.getComponent(i)).setText("");
}
}
});
}
public static void main(String[] args) {
// 그래픽 전용 thread 사용하기
SwingUtilities.invokeLater(new Thread()
{
public void run() {
new TicTacToe1();
}
});
}
}

view raw

TicTacToe1.java

hosted with ❤ by GitHub


package blog.gui.tictactoe;
public class TicTacToeCore {
private int currentPlayerNum;
private boolean isGameOver = false;
private int[][] endStage;
private int currentTurn = 1;
public TicTacToeCore(int currentPlayerNum) {
this.currentPlayerNum = currentPlayerNum;
}
public void changeTurn() {
currentPlayerNum = (currentPlayerNum == 1) ? 2 : 1;
}
public int getCurrentPlayerNum() {
return currentPlayerNum;
}
public void setCurrentPlayerNum(int currentPlayerNum) {
this.currentPlayerNum = currentPlayerNum;
}
public int[][] getEndStage() {
return endStage;
}
/**
*
* @param currentStage
* @return -99: 게임종료됨, 1: 플레이어 1 승리, 2: 플레이어 2 승리, 0: 진행중, 99: 비김(draw)
*/
public int inputCurrentStage(int[][] currentStage) {
// 게임이 끝났다면 더 이상 진행하는 의미가 없으므로 판단 중단
if(isGameOver) {
return -99;
}
for(int i = 0; i < currentStage.length; i++) {
String rowStr = "";
String colStr = "";
String diagStr1 = "";
String diagStr2 = "";
for(int j = 0; j < currentStage[i].length; j++) {
rowStr += (currentStage[i][j] + "");
colStr += (currentStage[j][i] + "");
}
for(int j = 0; j < currentStage.length; j++) {
diagStr1 += currentStage[j][j];
diagStr2 += currentStage[j][2 – j];
}
// 가로 판단
if(isThisPlayerWin(2, rowStr, colStr, diagStr1, diagStr2)) {
isGameOver = true;
endStage = currentStage;
return 2;
} else if(isThisPlayerWin(1, rowStr, colStr, diagStr1, diagStr2)) {
isGameOver = true;
endStage = currentStage;
return 1;
} else if(currentTurn == 9) {
return 99;
} else {
continue;
}
}
currentTurn++;
return 0;
}
private boolean isThisPlayerWin(int playerNum, String rowFrag, String colFrag, String diagFrag1, String diagFrag2) {
String p = String.valueOf(playerNum);
boolean result = false;
String[] arr = {rowFrag, colFrag, diagFrag1, diagFrag2};
for(int i = 0; i < arr.length; i++) {
result = !arr[i].contains("0") && arr[i].equals(p + p + p);
if (result) return result;
}
return result;
}
public void resetGame(int currentPlayerNum) {
this.isGameOver = false;
this.currentPlayerNum = currentPlayerNum;
this.endStage = null;
this.currentTurn = 1;
}
}

틱택토 예제