Delay JavaFX8人类对AI游戏。允许人为行动的拖延

Delay JavaFX8人类对AI游戏。允许人为行动的拖延,delay,javafx-8,Delay,Javafx 8,我正在写跳棋游戏,正如标题所示,它介于人类玩家和人工智能之间。人类玩家的每个棋盘格都设置了阻力检测。OnDragDetected收集检查器当前位置的坐标。OnDragDrop收集玩家想要放置棋盘格的位置坐标。完成此操作后,将执行一系列其他功能以确保移动有效。如果这个动作有效,那么就轮到AI了。AI移动之后,轮到人类玩家了,等等 我遇到的问题是,我必须以某种方式延迟播放器拖放检查器后发生的所有函数,因为我需要首先收集有关坐标的信息 我尝试过很多事情,但都没有成功。我真的很感激任何指针,因为这是我第

我正在写跳棋游戏,正如标题所示,它介于人类玩家和人工智能之间。人类玩家的每个棋盘格都设置了阻力检测。OnDragDetected收集检查器当前位置的坐标。OnDragDrop收集玩家想要放置棋盘格的位置坐标。完成此操作后,将执行一系列其他功能以确保移动有效。如果这个动作有效,那么就轮到AI了。AI移动之后,轮到人类玩家了,等等

我遇到的问题是,我必须以某种方式延迟播放器拖放检查器后发生的所有函数,因为我需要首先收集有关坐标的信息

我尝试过很多事情,但都没有成功。我真的很感激任何指针,因为这是我第一个使用JavaFX的程序


谢谢。

我不太清楚你说的延迟是什么意思。您只需要使用事件处理程序管理所有内容,并跟踪工件从何处移动到何处。然后,当用户试图完成移动时,通常通过释放拖动来检查有效性

这里有一个非常基本的轮廓,一个玩家只是移动棋子。当然,在现实生活中,方态所占据的位置将更为复杂,两个玩家等等,移动验证也是如此。但它应该给你一个想法

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class CheckersExample extends Application {

    private static final int BOARD_SIZE = 10 ;

    private static final int SQUARE_SIZE = 60 ;
    private static final int PIECE_RADIUS = 25 ;

    @Override
    public void start(Stage primaryStage) {

        // Use a GridPane for the board:
        GridPane board = new GridPane();

        // track where move is made from and to
        ObjectProperty<Square> moveFrom = new SimpleObjectProperty<>();
        ObjectProperty<Square> moveTo = new SimpleObjectProperty<>();

        // Create the squares and add views of them to the grid pane:
        for (int y=0; y<BOARD_SIZE; y++) {
            for (int x=0; x<BOARD_SIZE; x++) {
                Square square = new Square(x, y);
                board.add(square.getView(), x, y);

                // alternate squares in last 3 rows are occupied:

                if (y >= BOARD_SIZE-3 && (x + y) % 2 == 1) {
                    square.setOccupied(true);
                }

                // add event handlers for dragging to enable moving pieces:

                setUpDraggingForMove(square, moveFrom, moveTo);
            }
        }

        BorderPane root = new BorderPane(board);
        Scene scene = new Scene(root);
        scene.getStylesheets().add("checkers.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void setUpDraggingForMove(Square square, ObjectProperty<Square> moveFrom,
            ObjectProperty<Square> moveTo) {

        // CSS pseudoclass for highlighting squares before moving to them:
        PseudoClass highlight = PseudoClass.getPseudoClass("highlight");

        // when starting drag, if square has a piece, set the moveFrom:

        square.getView().setOnDragDetected(event -> {
            if (square.isOccupied()) {
                moveFrom.set(square) ;

                // this enables drag events to other nodes (squares):
                square.getView().startFullDrag();
            }
        });

        // if dragging onto a square that's a valid move, highlight it and set the moveTo:

        square.getView().setOnMouseDragEntered(event -> {
            if (moveValid(moveFrom.get(), square)) {
                square.getView().pseudoClassStateChanged(highlight, true);
                moveTo.set(square);
            }
        });

        // when dragging off a square, un-highlight it and unset the moveTo:

        square.getView().setOnMouseDragExited(event -> {
            square.getView().pseudoClassStateChanged(highlight, false);
            moveTo.set(null);
        });

        // when releasing, if the move is valid, set the moveFrom to be unoccupied and the 
        // moveTo to be occupied:

        square.getView().setOnMouseReleased(event -> {
            if (moveValid(moveFrom.get(), moveTo.get())) {
                moveFrom.get().setOccupied(false);
                moveTo.get().setOccupied(true);
            }
            moveFrom.set(null);
            moveTo.set(null);
        });
    }

    // check validity of move:

    private boolean moveValid(Square from, Square to) {
        if (from == null ||                          // no from
            to   == null ||                          // no to
            !from.isOccupied() ||                    // from occupied
            to.isOccupied() ||                       // to occupied
            from.getY() - to.getY() != 1 ||          // not moving forward
            Math.abs(from.getX() - to.getX()) != 1)  // not moving sideways
        {
            return false ;
        } else {
            return true ;
        }

    }


    // represents a square on the board. Encapsulates its position (x and y),
    // whether or not it contains a piece (occupied)
    // and exposes a UI component representing it (view):

    private static class Square {
        private final int x ;
        private final int y ;
        private final BooleanProperty occupied ;

        private final StackPane view ;

        public Square(int x, int y) {
            this.x = x ;
            this.y = y ;
            this.occupied = new SimpleBooleanProperty(this, "occupied", false);

            this.view = createView();
        }

        private StackPane createView() {

            // use a StackPane as the base view:

            StackPane view = new StackPane();
            view.getStyleClass().add("square");

            // pseudoclass to enable alternate color on alternate squares:

            PseudoClass oddClass = PseudoClass.getPseudoClass("odd");

            // fill GridPane cell:

            GridPane.setFillHeight(view, true);
            GridPane.setFillWidth(view, true);

            // fix size:

            view.setMinSize(SQUARE_SIZE, SQUARE_SIZE);
            view.setMaxSize(SQUARE_SIZE, SQUARE_SIZE);

            // set pseudoclass state for "odd" squares:

            if ((x + y) % 2 == 0) {
                view.pseudoClassStateChanged(oddClass, true);
            } 

            // add piece to stack pane...

            Circle piece = new Circle(SQUARE_SIZE/2, SQUARE_SIZE/2, PIECE_RADIUS);
            piece.getStyleClass().add("piece");
            view.getChildren().add(piece);

            // .. but only actually display it if the square is occupied:

            piece.visibleProperty().bind(occupied);

            return view ;
        }

        public Node getView() {
            return view ;
        }

        public int getX() {
            return x ;
        }

        public int getY() {
            return y ;
        }

        public final BooleanProperty occupiedProperty() {
            return this.occupied;
        }

        public final boolean isOccupied() {
            return this.occupiedProperty().get();
        }

        public final void setOccupied(final boolean occupied) {
            this.occupiedProperty().set(occupied);
        }       

    }

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

您应该在捕获玩家移动的事件处理程序中调用玩家移动的验证检查。也许可以看看我的例子。
.root {

    /* and.. breathe... */

    -fx-padding: 40px ;
}

.square {

    /* use a looked-up color for the main background of a square, 
       so it's easy to change */

    -square-background: antiquewhite ;

    /* nest some backgrounds to give the effect of a raised border: */
    -fx-background-color: white, lightgray, darkgray, black, -square-background ;
    -fx-background-insets: 0px, 1px 1px 0px 0px, 2px 2px 1px 1px, 4px 4px 2px 2px, 5px 5px 3px 3px ;
}
.square:odd {
    /* change the main background on "odd" squares: */
    -square-background: cornflowerblue ;
}

.square:highlight {
    /* and change it again for highlighted squares: */
    -square-background: lightgoldenrodyellow ;
 }

.piece {
    /* color for pieces: */
    -fx-fill: steelblue ;
}