从数组中的按钮获取文本,然后将所有值连接成一个字符串
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);
}
}
我有一个按钮列表,用作我的井字游戏的方块,我想创建一个方法来检查平局,该方法基本上会检查棋盘是否已满并且没有赢家,然后它是领带。
我想从所有按钮中获取文本并将其全部连接成 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);
}
}