在前面的單元中,我們完成了遊戲視窗與 3x3 棋盤按鈕的靜態外觀。今天我們要迎來最關鍵的互動邏輯——ActionListener讓玩家能夠點擊格子,並實現 X 與 O 的輪流下棋機制!
tile.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
// 1. 取得被點擊的按鈕來源
JButton tile = (JButton)e.getSource();
// 2. 防呆機制:確保格子是空的(還沒被下過)才能填入
if (tile.getText() == ""){
// 將按鈕文字設為當前玩家(X 或 O)
tile.setText(currentPlayer);
// 3. 切換玩家回合(三元運算子:如果是 X 就換 O,反之換 X)
currentPlayer = currentPlayer == playerX ? playerO : playerX;
// 4. 更新頂部標題文字,提示下一個玩家的回合
textLabel.setText(currentPlayer + "'s turn.");
}
}
});
說明:
* e.getSource() 與強制轉型:當任何一個按鈕被點擊時,ActionEvent 會捕捉到這個事件。我們透過 e.getSource() 拿到觸發事件的元件,並將它強制轉型為 JButton,以便對它進行文字修改。
* 防呆檢查 if (tile.getText() == ""):確保玩家不能重複點擊已經有棋子的格子,避免已經下過的 X 或 O 被蓋掉。
* 三元運算子切換回合:currentPlayer = currentPlayer == playerX ? playerO : playerX; 簡潔地實現了每次點擊後在兩位玩家之間交替。
* 即時更新頂部標題:透過 textLabel.setText(...),讓頂部文字從一開始的遊戲名稱變成動態的 O's turn. 或 X's turn.,大幅提升遊戲體驗。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TicTacToe {
int boardWidth = 600;
int boardHeight = 650; //50px for the text panel on top
JFrame frame = new JFrame("Tic-Tac-Toe");
JLabel textLabel = new JLabel();
JPanel textPanel = new JPanel();
JPanel boardPanel = new JPanel();
JButton[][] board = new JButton[3][3];
String playerX = "X";
String playerO = "O";
String currentPlayer = playerX;
TicTacToe(){
frame.setVisible(true);
frame.setSize(boardWidth, boardHeight);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
textLabel.setBackground(Color.darkGray);
textLabel.setForeground(Color.white);
textLabel.setFont(new Font("Arial", Font.BOLD, 50));
textLabel.setHorizontalAlignment(JLabel.CENTER);
textLabel.setText("Tic-Tac-Toe");
textLabel.setOpaque(true);
textPanel.setLayout(new BorderLayout());
textPanel.add(textLabel);
frame.add(textPanel, BorderLayout.NORTH);
boardPanel.setLayout(new GridLayout(3, 3));
boardPanel.setBackground(Color.darkGray);
frame.add(boardPanel);
for (int r = 0; r < 3; r++){
for (int c = 0; c < 3; c++){
JButton tile = new JButton();
board[r][c] = tile;
boardPanel.add(tile);
tile.setBackground(Color.darkGray);
tile.setForeground(Color.white);
tile.setFont(new Font("Arial", Font.BOLD, 120));
tile.setFocusable(false);
tile.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
JButton tile = (JButton)e.getSource();
if (tile.getText() == ""){
tile.setText(currentPlayer);
currentPlayer = currentPlayer == playerX ? playerO : playerX;
textLabel.setText(currentPlayer + "'s turn.");
}
}
});
}
}
}
}
跑出來長這樣:
參考教學影片:https://youtu.be/Nc77ymnm8Ss?si=PC8nENyFWeLg1lDg