我正在嘗試用 java 中的 GUI 撰寫一個跳棋 AI 程式。到目前為止,我已經成功地初始化并填充了電路板(暫時寫為“B”和“W”)。我為電路板創建了一個 2D JButton 面板。
我不知道移動碎片時如何進行。我當前的問題是我需要玩家選擇一個預先存在的棋子(動作 1),然后選擇一個空白空間來放置所選棋子(動作 2)。當然,這些操作是依賴的,我需要先執行操作 1。
這是我到目前為止所得到的:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class Checkers implements ActionListener{
private static final int BOARD_SIZE = 8;
Random random = new Random();
JFrame frame = new JFrame();
JPanel title_panel = new JPanel();
JPanel button_panel = new JPanel();
JLabel textfield = new JLabel();
JButton[][] buttons = new JButton[BOARD_SIZE][BOARD_SIZE];
Checkers(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,800);
frame.getContentPane().setBackground(new Color(50, 50, 50));
frame.setLayout(new BorderLayout());
frame.setVisible(true);
textfield.setBackground(new Color(25,25,25));
textfield.setForeground(new Color(25, 255, 0));
textfield.setFont(new Font("Arial", Font.BOLD, 75));
textfield.setHorizontalAlignment(JLabel.CENTER);
textfield.setText("Checkers");
textfield.setOpaque(true);
title_panel.setLayout(new BorderLayout());
title_panel.setBounds(0,0,800, 100);
button_panel.setLayout(new GridLayout(BOARD_SIZE,BOARD_SIZE));
button_panel.setBackground(new Color(150,150,150));
for (int i=0; i<BOARD_SIZE; i ){
for (int j=0; j<BOARD_SIZE; j ){
buttons[i][j] = new JButton();
button_panel.add(buttons[i][j]);
buttons[i][j].setFont(new Font("Arial",Font.BOLD, 30));
buttons[i][j].setFocusable(false);
buttons[i][j].addActionListener(this);
}
}
title_panel.add(textfield);
frame.add(title_panel, BorderLayout.NORTH);
frame.add(button_panel);
initialiseBoard(buttons);
}
@Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < BOARD_SIZE; i ) {
for (int j = 0; j < BOARD_SIZE; j ) {
if (e.getSource() == buttons[i][j]) {
String moving_piece = buttons[i][j].getText();
}
}
}
}
// method that fills the initial board.
public void initialiseBoard(JButton[][] buttons){
for (int i=0; i<BOARD_SIZE; i ){
for (int j=0; j<BOARD_SIZE; j ){
if (i<3){
if (i%2==0){
if (j%2 != 0){
buttons[i][j].setText("W");
}
}
else {
if (j%2==0){
buttons[i][j].setText("W");
}
}
}
if (i>=BOARD_SIZE-3){
if (i%2 == 0){
if (j%2 != 0){
buttons[i][j].setText("B");
}
}
else {
if (j%2==0){
buttons[i][j].setText("B");
}
}
}
}
}
}
}
uj5u.com熱心網友回復:
正如我在評論中提到的,解決方案的關鍵是將程式的偵聽器基于“狀態相關行為”,這意味著偵聽器的行為將取決于程式的狀態。
例如,如果你給你的程式一個實體欄位,比如說,selectedButton它包含對最后選擇的按鈕的參考,那么任何 ActionListener 的回應都可能會根據該欄位所包含的內容而有所不同。第一次按下任何 JButton 時,該欄位將保持不變,null因為之前沒有按下任何 JButton,因此 ActionListener 會將這個按鈕分配給該欄位。第二次呼叫 ActionListener(第二次按下 JButton),該欄位將保存一個值,因此,使用 if / else 塊檢查該欄位的狀態,偵聽器的行為可能會有所不同:
public class Checkers2 {
private static final int BOARD_SIZE = 8;
// .....
private JButton[][] buttons = new JButton[BOARD_SIZE][BOARD_SIZE];
private JButton selectedButton = null;
public Checkers2() {
buttonPanel.setLayout(new GridLayout(BOARD_SIZE, BOARD_SIZE));
for (int i = 0; i < buttons.length; i ) {
for (int j = 0; j < buttons[i].length; j ) {
buttons[i][j] = new JButton(" ");
buttonPanel.add(buttons[i][j]);
buttons[i][j].setFont(BTN_FONT);
buttons[i][j].setPreferredSize(BTN_SIZE);
buttons[i][j].addActionListener(e -> btnsActionPerormed(e));
}
}
// ...
}
private void btnsActionPerormed(ActionEvent e) {
JButton source = (JButton) e.getSource();
// if selectedButton is null, then this is the first press
if (selectedButton == null) {
if (source.getText().trim().isEmpty()) {
return; // no button text means that there is no piece here. Exit method
} else {
// first set the selectedButton's value
selectedButton = source;
// change its appearance so we know that it has been pressed
source.setForeground(Color.RED);
source.setBackground(Color.LIGHT_GRAY);
}
} else {
// else, if selectedButton is NOT null, then this is the second press
// only do things if this current button is empty, if it has no text
if (source.getText().trim().isEmpty()) {
selectedButton.setForeground(Color.BLACK);
selectedButton.setBackground(null);
source.setText(selectedButton.getText());
selectedButton.setText("");
// the code below is of key importance
selectedButton = null;
}
}
}
顯示的最后一段代碼也很關鍵——第二次按下 JButton 時,我們將 selectedButton 重新設定為 null,以便程式的狀態被設定回其初始狀態,并且偵聽器的初始行為可以重復。
一個簡單的示例程式演示了這一點,如下所示。該程式仍然沒有包含真正的 Checker 游戲邏輯,程式確定移動是否真正合法:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class Checkers2 {
private static final int BOARD_SIZE = 8;
private static final Font BTN_FONT = new Font("Arial", Font.BOLD, 30);
private static final Dimension BTN_SIZE = new Dimension(100, 100);
private JPanel buttonPanel = new JPanel();
private JButton[][] buttons = new JButton[BOARD_SIZE][BOARD_SIZE];
private JButton selectedButton = null;
public Checkers2() {
buttonPanel.setLayout(new GridLayout(BOARD_SIZE, BOARD_SIZE));
for (int i = 0; i < buttons.length; i ) {
for (int j = 0; j < buttons[i].length; j ) {
buttons[i][j] = new JButton(" ");
buttonPanel.add(buttons[i][j]);
buttons[i][j].setFont(BTN_FONT);
buttons[i][j].setPreferredSize(BTN_SIZE);
buttons[i][j].addActionListener(e -> btnsActionPerormed(e));
}
}
// Place "W" and "B" text in appropriate locations:
for (int i = 0; i < 12; i ) {
int wI = (2 * i) / BOARD_SIZE;
int wJ = (2 * i) % BOARD_SIZE ((wI % 2 == 1) ? 0 : 1);
buttons[wI][wJ].setText("W");
buttons[BOARD_SIZE - wI - 1][BOARD_SIZE - wJ - 1].setText("B");
}
}
private void btnsActionPerormed(ActionEvent e) {
JButton source = (JButton) e.getSource();
// if selectedButton is null, then this is the first press
if (selectedButton == null) {
if (source.getText().trim().isEmpty()) {
return; // no button text means that there is no piece here. Exit method
} else {
// first set the selectedButton's value
selectedButton = source;
// change its appearance so we know that it has been pressed
source.setForeground(Color.RED);
source.setBackground(Color.LIGHT_GRAY);
}
} else {
// else, if selectedButton is NOT null, then this is the second press
// only do things if this current button is empty, if it has no text
if (source.getText().trim().isEmpty()) {
selectedButton.setForeground(Color.BLACK);
selectedButton.setBackground(null);
source.setText(selectedButton.getText());
selectedButton.setText("");
// the code below is of key importance
selectedButton = null;
}
}
}
public JPanel getButtonPanel() {
return buttonPanel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Checkers2 checkers = new Checkers2();
JFrame frame = new JFrame("Checkers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(checkers.getButtonPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
我希望展示如何在編輯中加入程式邏輯。為此,我建議使用“模型-視圖-控制器”或 MVC 程式結構。
uj5u.com熱心網友回復:
您需要記住和管理一件作品的選擇。你可以這樣做:
//Introduce a field to store selected button
private JButton selected = null ;
并修改ActionListener:
@Override
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
if(selected != null ){
clicked.setText(selected.getText());
selected.setText("");
selected = null;
}else{
if( ! clicked.getText().isEmpty()) {
selected = clicked;
}
}
}
考慮使用JToggleButtons 而不是JButtons 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/429878.html
上一篇:單擊時按鈕的圖示不更新
