SequentialTransition повторяет больше, чем счет цилиндра - PullRequest
0 голосов
/ 11 декабря 2018

Я бы написал неправильно, но я знаю, что меня собираются забрать в школу с функцией Javafx, о которой я не знал, что она существует.

Когда я использую комбинацию PauseTransition и SequentialTransition, чтобы соединить четыре игры, сделанные из сетки кнопок, всплывающее кнопка за кнопкой.При очень конкретном случае использования у меня очень неожиданный результат.

Вот весь код, необходимый для запуска и репликации ошибки, отредактированной до автономной и минималистской, при сохранении базовой игровой логики.

import javafx.animation.PauseTransition;
import javafx.animation.SequentialTransition;
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ConnectFourApplication extends Application {
    public static final int NUM_COLUMNS = 8;
    public static final int NUM_ROWS = 8;
    private Button[][] buttons;
    private int row =0;
    private int column = 0;
    private PauseTransition buttonGravityPause;
    private Scene scene;
    private BorderPane border;
    private ConnectEnum turnColor=ConnectEnum.RED;

    public enum ConnectEnum{
        RED ("Red"), BLACK ("Black");
        private String turn;
        ConnectEnum( String value) {
            this.turn = value;
        }
    }

    @Override
    public void start(Stage primaryStage) {
        buttons = new Button[NUM_ROWS][NUM_COLUMNS];
        GridPane gridpane = new GridPane();
        Button turn = new Button("Take turn");
        for(int i=0; i<NUM_ROWS; i++){
            for(int j = 0; j<NUM_COLUMNS; j++){
                buttons[i][j] = new Button("Empty");
                buttons[i][j].setMinHeight(20);
                buttons[i][j].setMaxWidth(Double.MAX_VALUE);
                buttons[i][j].setOnAction(new ButtonHandler<>(i,j));
                gridpane.add(buttons[i][j], j, (NUM_ROWS-1)-i);
            }
        }

        buttonGravityPause = new PauseTransition(new Duration(700));
        buttonGravityPause.setOnFinished(event-> {
            if (this.row>0) {
                buttons[this.row - 1][this.column].setStyle("-fx-background-color:blue");
                buttons[this.row][this.column].setStyle("");
                this.row = this.row - 1;
            }else System.out.println("THis should never happen, row is: "+this.row);
        });

        SequentialTransition s = new SequentialTransition(buttonGravityPause);
        s.setOnFinished(floatDown-> {
            System.out.println("The button " +row+ " " +column+" has been chosen");
            buttons[this.row][this.column].setText(""+getTurn());
            buttons[this.row][this.column].setStyle("-fx-background-color:"+getTurn());
            changeTurn();
        });

        turn.setOnAction(e->{
            System.out.println("The button " +row+ " " +column+" has been chosen");
            int i =0;
            while(this.row-i>0 && buttons[this.row-(i+1)][this.column].getText().equals("Empty"))i++;
            s.setCycleCount(i);
            System.out.println("i is: "+i+"  but cycle count is: "+s.getCycleCount());
            if(i>0)s.play(); else{
                System.out.println("The button " +row+ " " +column+" has been chosen");
                buttons[this.row][this.column].setText(""+getTurn());
                buttons[this.row][this.column].setStyle("-fx-background-color:"+getTurn());
                changeTurn();
            }
        });

        border = new BorderPane();
        border.setCenter(gridpane);
        border.setBottom(turn);
        scene = new Scene(border, 510, 380);

        primaryStage.setTitle("Connect Four");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    private ConnectEnum getTurn(){return this.turnColor;}
    private void changeTurn(){this.turnColor = this.turnColor==ConnectEnum.RED? ConnectEnum.BLACK:ConnectEnum.RED;}
    private void setRowColumn(int row, int column){
        this.row=row;
        this.column=column;
    }
    private int getRow(){
        return this.row;
    }
    private int getColumn(){
        return this.column;
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    class ButtonHandler<T extends Event> implements EventHandler<T> {
        private int row;
        private int col;

        ButtonHandler(int row, int column){
            this.row=row;
            this.col=column;
        }

        @Override
        public void handle(T event){
            if (buttons[getRow()][getColumn()].getText().equals("Empty")) buttons[getRow()][getColumn()].setStyle("");
            if (buttons[this.row][this.col].getText().equals("Empty")) {
                setRowColumn(this.row, this.col);
                buttons[row][col].setStyle("-fx-background-color:blue");
            }else System.out.println("This space is occupied");
        }
    }
}

Это работает при любых обстоятельствах правильно, за исключением случая, когда я 1. выбираю кнопку, которая находится непосредственно над уже размещенной кнопкой, а затем 2. следующий выбор, если она находится над несколькими пустыми точкамиприведет к следующему выводу консоли (включая первые несколько хороших и ожидаемых операторов):

The button2 1has been chosen
i is: 2  but cycle count is: 2
The button 0 1 has been chosen
false
The button1 1has been chosen
i is: 0  but cycle count is: 0
false
The button4 2has been chosen
i is: 4  but cycle count is: 4
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
THis should never happen, row is: 0
...
...
The button 0 2 has been chosen

Чтобы воспроизвести состояние ошибки / гонки: 1. Выберите любую кнопку, нажмите по очереди.2. Нажмите кнопку сразу над теперь окрашенной кнопкой, нажмите по очереди.3. Выберите кнопку, которой нет в нижнем ряду кнопок, и наблюдайте, как происходит волшебство.

Ранее это приводило к тому, что массив выходил за пределы, но я добавил оператор if, чтобы избежать ошибок и попытаться пролить свет на происходящее.

Если у кого-то есть опыт работы с этой областью JavaFX, я буду очень признателен, поскольку я в растерянности.

1 Ответ

0 голосов
/ 11 декабря 2018

Создание поля SequentialTransition s и создание нового (а не повторное использование одного и того же экземпляра) при нажатии turn решает проблему:

    turn.setOnAction(e->{
        int i = 0;
        while(row-i>0 && buttons[row-(i+1)][column].getText().equals("Empty")) {
            i++;
        }

        if(i>0) {
            s = new SequentialTransition(buttonGravityPause);
            s.setAutoReverse(false);
            s.setOnFinished(floatDown-> {
                buttons[row][column].setText(""+getTurn());
                buttons[row][column].setStyle("-fx-background-color:"+getTurn());
                changeTurn();
            });
            s.setCycleCount(i);
            s.play();
        } else{
            buttons[row][column].setText(""+getTurn());
            buttons[row][column].setStyle("-fx-background-color:"+getTurn());
            changeTurn();
        }
    });

Я не уверен, почему повторное использованиеSequentialTransition экземпляр вызывает проблему.Надеюсь, кто-то, кто знает больше об этом, может добавить объяснение.Рабочий демонстрационный код можно скопировать с здесь

...