从数组中的按钮获取文本,然后将所有值连接成一个字符串

Getting text from buttons in an array then concating all the values into a string

我有一个按钮列表,用作我的井字游戏的方块,我想创建一个方法来检查平局,该方法基本上会检查棋盘是否已满并且没有赢家,然后它是领带。

我想从所有按钮中获取文本并将其全部连接成 1 个字符串,当该字符串的长度为 9 且没有获胜者时,则为平局。

我当前的方法有效,但我想知道是否有通过使用循环或其他方法来提高效率的方法

游戏初始化代码

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        buttons = new ArrayList<>(Arrays.asList(button1,button2,button3,button4,button5,button6,button7,button8,button9));
        buttons.forEach(button ->{
            setupButton(button);
            button.setFocusTraversable(false);
            button.setText("");
        });
    }

检查平局的代码

line2 = button1.getText() + button2.getText() + button3.getText() + button4.getText() + button5.getText() + button6.getText() + button7.getText() + button8.getText() + button9.getText();

            if ((line2.length()) == 9 && winner == null) {
            ties++;
            tiesText.setText(""+ties);
            disableAllButtons();
            newGame(null);
            }

您可以使用计数器并在单击按钮时递增它。如果计数器是 9,则平局。

如果您想坚持使用按钮文本,您可以使用 foreach 循环,例如:

line2 = "";
foreach (Button button : buttons){
  line2 += button.getText();
}

您可以在串联字符串绑定上创建侦听器,然后使用它来监视所有按钮的串联文本。

例如:

StringExpression state = Bindings.concat(
        board.getChildren().stream()
                .map(node -> ((Button) node).textProperty())
                .toArray()
);
state.addListener((observable, oldState, newState) ->
        handleStateChange(newState)
);

这可能比必要的要复杂一点。对于基本解决方案,最好对按钮点击做出反应并在循环中更新状态(如 ),而不是使用绑定。但是绑定确实提供了另一种解决方案,保留了您最初的连接按钮文本的概念。

代表 newState 的字符串值的一个例子是九个字符的字符串:

"XO  XO  X"

在这个例子中,未下的方格是空格,X刚刚从左上角到右下角的对角线赢了。

上下文中的示例

  • 使用 James 的建议来检查平局检测。
  • 使用 Java 17 个功能。

应用代码

import javafx.application.*;
import javafx.beans.binding.*;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.TilePane;
import javafx.stage.*;

public class NoughtsAndCrosses extends Application {
    private static final int NUM_SQUARES = 9;

    private static final String X = "X";
    private static final String O = "O";
    private static final String TIE = "-";
    private static final String NONE = " ";

    private String nextPlayer = X;

    private Scene scene;

    private static final int[][] LINES = {
            {1,2,3}, {4,5,6}, {7,8,9},  // horizontal
            {1,4,7}, {2,5,8}, {3,6,9},  // vertical
            {1,5,9}, {3,5,7}            // diagonal
    };

    public void start(Stage stage) {
        scene = new Scene(newGame());
        stage.setScene(scene);
        stage.setTitle("Noughts and Crosses");
        stage.show();
    }

    private Parent newGame() {
        TilePane board = createBoard();
        if (scene != null) {
            scene.setRoot(board);
        }

        return board;
    }

    private TilePane createBoard() {
        TilePane board = new TilePane(10, 10);
        board.setStyle("-fx-base: antiquewhite; -fx-font-size: 30; -fx-font-weight: bold;");
        board.setPadding(new Insets(10));
        board.setPrefColumns(3);
        board.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
        board.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);

        for (int i = 0; i < NUM_SQUARES; i++) {
            board.getChildren().add(createSquare());
        }

        StringExpression state = Bindings.concat(
                board.getChildren().stream()
                        .map(node -> ((Button) node).textProperty())
                        .toArray()
        );
        state.addListener((observable, oldState, newState) ->
                handleStateChange(newState)
        );

        return board;
    }

    private Button createSquare() {
        final Button square = new Button(NONE);
        square.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
        square.setPrefSize(65, 65);
        square.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);

        square.setOnAction(e -> takeTurn(square));

        return square;
    }

    private void takeTurn(Button square) {
        square.setText(nextPlayer);
        nextPlayer = X.equals(nextPlayer) ? O : X;
    }

    private void handleStateChange(String state) {
        int nTies = 0;

        for (int[] line : LINES) {
            String result = checkResult(line, state);
            switch (result) {
                case X -> { endGame(X); return; }
                case O -> { endGame(O); return; }
                case TIE -> nTies++;
            }
        }

        if (nTies == LINES.length) {
            endGame(TIE);
        }
    }

    private String checkResult(int[] line, String state) {
        int numX = 0, numO = 0;

        for (int j : line) {
            String cellState = state.substring(j - 1, j);
            switch (cellState) {
                case X -> numX++;
                case O -> numO++;
            }
        }

        if (numX == 3) {
            return X;
        }

        if (numO == 3) {
            return O;
        }

        if (numX > 0 && numO > 0) {
            return TIE;
        }

        return NONE;
    }

    private void endGame(String result) {
        String msg = switch (result) {
            case X -> X + " won";
            case O -> O + " won";
            case TIE -> "Tie";
            default -> "unexpected result";
        };

        Alert resultDialog = new Alert(
                Alert.AlertType.CONFIRMATION,
                """
                Play again?
                
                %s will start first.
                """.formatted(X.equals(nextPlayer) ? O : X)
        );
        resultDialog.setHeaderText(msg);
        resultDialog.setTitle("Game Over");

        resultDialog.initOwner(
                scene.getWindow()
        );

        // we do this in a run later as we want the board state to update for
        // the last interaction before displaying the result dialog.
        Platform.runLater(() ->
            resultDialog.showAndWait()
                    .filter(response -> response == ButtonType.OK)
                    .ifPresentOrElse(
                            response -> newGame(),
                            Platform::exit
                    )
        );
    }

    public static void main(String[] args) {
        launch(args);
    }
}