`

俄罗斯方块javafx版

阅读更多
package fx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.URL;


public class Main extends Application {


    private void initMainStage(Stage mainStage) throws IOException {
        URL location = getClass().getResource("/main.fxml");
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(location);
        fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
        Parent root = fxmlLoader.load();
        mainStage.setTitle("俄罗斯方块");
        mainStage.setScene(new Scene(root, 420, 520));
        mainStage.getIcons().add(new Image("/timg.jpg"));
        MainController mainController = fxmlLoader.getController();   //获取Controller的实例对象
        mainController.init(mainStage.getScene());
        mainStage.setResizable(false);
        mainStage.show();
    }



    @Override
    public void start(Stage mainStage) throws IOException {
        initMainStage(mainStage);
    }

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




}

 

package fx;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import model.abs.ABSModel;
import util.AlertUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class MainController {

    private ABSModel absModel;
    private ABSModel nextModel;
    private List<Node> tipList;
    //方块边长
    public static final int BLEN = 25;
    //分数
    public static int FRACTION = 0;
    //游戏状态
    public volatile static int GAME_STATUS = 0;//0 ready 1 running -1 over -2 pause

    //每满multiple个100,速度就减50
    private int MULTIPLE = 0;

    private Scene scene;

    @FXML
    private Button restartBtn;

    @FXML
    private Label fractionLab;

    @FXML
    private TextField speedTxt;

    @FXML
    private CheckBox downEndChk;

    @FXML
    private CheckBox downSpeedChk;

    @FXML
    private CheckBox showGrid;

    @FXML
    private CheckBox showShadow;

    @FXML
    private Pane mainMask;


    public void init(Scene scene) {
        this.scene = scene;
        addAllGrid();
    }

    @FXML
    public void onShowGridChecked(ActionEvent event) {
        showAllGrid(showGrid.isSelected());
    }

    @FXML
    public void onShowShadowChecked(ActionEvent event) {
        if (absModel == null) {
            return;
        }
        if (showShadow.isSelected()) {
            absModel.moveShadowRect();
            ((AnchorPane) scene.getRoot()).getChildren().addAll(absModel.getShadowList());
        }else{
            ((AnchorPane) scene.getRoot()).getChildren().removeAll(absModel.getShadowList());
        }
    }

    @FXML
    public void onRestart(ActionEvent event) {
        switch (GAME_STATUS) {
            case 0://ready
                startGame();
                break;
            case 1://running
                absModel.destory();
                resetGameBox();
                break;
            case -1://over
                absModel.clearClass();
                absModel = null;
                nextModel = null;
                resetGameBox();
                startGame();
        }
        if (GAME_STATUS != -2) {
            GAME_STATUS = 1;
        }
    }

    private void startGame() {
        try {
            if (speedTxt.getText().trim().equals("") || Integer.parseInt(speedTxt.getText().trim()) < 50) {
                speedTxt.setText("50");
            }
        } catch (Exception e) {
            speedTxt.setText("50");
        }
        speedTxt.setDisable(true);
        restartBtn.setText("重新开始");
        newModel();
    }

    private void resetGameBox() {
        showAllGrid(showGrid.isSelected());
        removeListByType(getAllRect());
        FRACTION = 0;
        MULTIPLE = 0;
        fractionLab.setText("0");
        if (speedTxt.getText().trim().equals("")) {
            speedTxt.setText("500");
        }
        mainMask.setVisible(false);
        ABSModel.clear();
    }

    private void removeListByType(List<Node> allRect) {
        for (Node next : allRect) {
            ((AnchorPane) scene.getRoot()).getChildren().remove(next);
        }
    }

    private void showAllGrid(boolean val) {
        ((AnchorPane) scene.getRoot()).getChildren().stream().filter(
                next -> next instanceof Line).forEach(node -> {
            node.setVisible(val);
        });
    }

    private void addAllGrid() {
        for (double y = 10 + BLEN; y < 10 + BLEN * 20; y += BLEN) {
            Line line = new Line();
            line.setStartX(0);
            line.setEndX(BLEN * 10);
            line.setStartY(y);
            line.setEndY(y);
            line.setAccessibleText("sysRect");
            line.setStroke(Color.valueOf("#333333"));
            ((AnchorPane) scene.getRoot()).getChildren().add(line);
        }
        for (double x = BLEN; x < BLEN * 10; x += BLEN) {
            Line line = new Line();
            line.setStartX(x);
            line.setEndX(x);
            line.setStartY(10);
            line.setEndY(10 + BLEN * 20);
            line.setAccessibleText("sysRect");
            line.setStroke(Color.valueOf("#333333"));
            ((AnchorPane) scene.getRoot()).getChildren().add(line);
        }
    }

    private List<Node> getAllRect() {
        List<Node> list = ((AnchorPane) scene.getRoot()).getChildren().stream().filter(
                next -> next instanceof Rectangle && !"sysRect".equals(next.getAccessibleText())
        ).collect(Collectors.toList());
        return list;
    }


    public void newModel() {
        absModel = nextModel != null ? nextModel : ABSModel.rand();
        nextModel = ABSModel.rand();
        absModel.moveShadowRect();
        showRectAndNext();
        autoDown();
    }

    /**
     * 显示当前和下一个提示
     */
    private void showRectAndNext() {
        ((AnchorPane) scene.getRoot()).getChildren().addAll(absModel.getList());
        if (showShadow.isSelected()) {
            ((AnchorPane) scene.getRoot()).getChildren().addAll(absModel.getShadowList());
        }
        if (tipList != null) {
            removeListByType(tipList);
        }
        tipList = new ArrayList<>();
        for (Rectangle rect : nextModel.getList()) {
            Rectangle rect2 = nextModel.makeRect(rect.getLayoutX() + BLEN * 8, rect.getLayoutY() + BLEN * 2);
            rect2.setAccessibleText("sysRect");
            ((AnchorPane) scene.getRoot()).getChildren().add(rect2);
            tipList.add(rect2);
        }

    }

    private void autoDown() {
        ScheduledService.newTask(absModel, Integer.parseInt(speedTxt.getText()));
        new Thread(() -> {
            while (true) {
                if (absModel.isGameOver()) {
                    ScheduledService.cancel();
                    Platform.runLater(() -> {
                        String title = "Game Over";
                        String content = "游戏结束了,您的分数为" + FRACTION;
                        speedTxt.setDisable(false);
                        if ("500".equals(speedTxt.getText())) {
                            AlertUtil.errorAlert(title, content, speedTxt);
                        } else {
                            Optional<ButtonType> result = AlertUtil.chooseAlert(title, content + ",请选择下一轮速度", speedTxt.getText());
                            if (result.get() == AlertUtil.buttonTypeOne) {
                                speedTxt.setText("500");
                            }
                        }
                        GAME_STATUS = -1;
                    });
                    break;
                } else if (absModel.isModelOver()) {
                    ScheduledService.cancelModel();
                    Platform.runLater(() -> solitaire());
                    break;
                }
            }
        }).start();
    }


    /**
     * 接龙
     */
    public void solitaire() {
        if (absModel != null && !absModel.getShadowList().isEmpty()) {
            ((AnchorPane) scene.getRoot()).getChildren().removeAll(absModel.getShadowList());
            absModel.getShadowList().clear();
        }
        if (absModel.LINE > 0) {
            removeRect();//消行
            addFraction();//加分
        }
        newModel();
    }

    private void removeRect() {
        List<Node> list;
        List<Node> removeList = new ArrayList<>();
        List<Node> downList = new ArrayList<>();
        for (Double lineY : absModel.DESTORY_Y_LIST) {
            list = getAllRect();
            for (Node next : list) {
                if (lineY.equals(next.getLayoutY())) {
                    removeList.add(next);
                } else if (next.getLayoutY() < lineY) {
                    downList.add(next);
                }
            }
        }
        LinearGradient linearGradient1 = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, new Stop[]{
                new Stop(0, Color.WHITESMOKE),
                new Stop(1, Color.valueOf("#00ff00"))
        });
        new Thread(() -> {
            ScheduledService.pause();
            for (int i = 0; i < 4; i++) {
                for (Node next : removeList) {
                    if (i % 2 == 0) {
                        ((Rectangle) next).setFill(null);
                    } else {
                        ((Rectangle) next).setFill(linearGradient1);
                    }
                }
                try {
                    Thread.sleep(90);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (Node next : removeList) {
                Platform.runLater(() -> ((AnchorPane) scene.getRoot()).getChildren().remove(next));
            }
            for (Node next : downList) {
                next.setLayoutY(next.getLayoutY() + BLEN);
            }
            ScheduledService.resume();
        }).start();
    }


    public void addFraction() {
        switch (absModel.LINE) {
            case 1:
                FRACTION += 10;
                break;
            case 2:
                FRACTION += 30;
                break;
            case 3:
                FRACTION += 50;
                break;
            case 4:
                FRACTION += 100;
                break;
        }
        if (downSpeedChk.isSelected()) {
            int period = Integer.parseInt(speedTxt.getText());
            int nowMultiple = FRACTION / 100;
            if (MULTIPLE < nowMultiple) {
                period -= 50;
                if (period < 50) {
                    period = 50;
                }
                MULTIPLE = nowMultiple;
            }
            speedTxt.setText(period + "");
        }
        fractionLab.setText(String.valueOf(FRACTION));
    }

    @FXML
    public void keyDown(KeyEvent event) {
        ScheduledService.pause();
        if (GAME_STATUS == 1) {
            call(event.getCode());
        } else if (GAME_STATUS == -2) {
            switch (event.getCode()) {
                case ENTER:
                    GAME_STATUS = 1;
                    mainMask.setVisible(false);
            }
        }
    }

    @FXML
    public void keyUp(KeyEvent event) {
        ScheduledService.resume();
    }

    private void call(KeyCode code) {
        switch (code) {
            case UP:
                absModel.up();
                break;
            case LEFT:
                absModel.left();
                break;
            case RIGHT:
                absModel.right();
                break;
            case DOWN:
                absModel.down(downEndChk.isSelected() ? -1 : 1);
                break;
            case ENTER:
                GAME_STATUS = -2;
                mainMask.setVisible(true);
                mainMask.toFront();
        }
    }


}

 

package fx;

import model.abs.ABSModel;

import java.util.Timer;
import java.util.TimerTask;

import static fx.MainController.GAME_STATUS;

public class ScheduledService {
    private static Timer scheduledService;
    private static TimerTask task;
    private static volatile boolean pause;


    public static void newTask(ABSModel model, int period) {
        if (scheduledService == null){
            scheduledService = new Timer(true);;
        }
        scheduledService.schedule(task = new TimerTask() {
            @Override
            public void run() {
                if (GAME_STATUS == 1 && !pause) {
                    model.down(1);
                }
            }
        }, 500, period);
    }


    public static void cancelModel() {
        task.cancel();
        scheduledService.purge();
    }

    public static void cancel() {
        scheduledService.cancel();
        scheduledService.purge();
        scheduledService = null;
    }

    public static void pause() {
        pause = true;
    }

    public static void resume() {
        pause = false;
    }

}

 

package model.abs;

import javafx.application.Platform;
import javafx.scene.effect.Glow;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeLineCap;
import model.*;

import java.util.*;

import static fx.MainController.BLEN;

public abstract class ABSModel implements Cloneable {
    private final static String[] COLOR = {"#C41F3B", "#A330C9", "#FF7D0A", "#ABD473", "#69CCF0", "#00FF96", "#F58CBA", "#FFFFFF", "#FFF569", "#0070DE", "#9482C9", "#C79C6E"};
    private static List<Rectangle> POINT_RECT_LIST = new ArrayList<>();
    public volatile List<Double> DESTORY_Y_LIST = new ArrayList<>();//待消除的行坐标
    public int LINE = 0;//当前消了几行
    protected List<Rectangle> list = new ArrayList<>();
    protected List<Rectangle> shadowList = new ArrayList<>();
    protected volatile boolean pause;
    protected volatile boolean modelOver;
    protected volatile boolean gameOver;
    private volatile int now = 1;//1 up 2 right 3 down 4 left
    private double XXBottom = BLEN * 9;
    private double YYBottom = 10 + BLEN * 19;
    private String myFillColor;

    public static ABSModel rand() {
        ABSModel model = getRandModel();
//        ABSModel model = new OModel();
        return model;
    }

    public static void clear() {
        POINT_RECT_LIST = new ArrayList<>();
    }

    private static ABSModel getRandModel() {
        int ra = new Random().nextInt(7);
//        System.out.print(ra);
//        System.out.print("\t");
        switch (ra) {
            case 0:
                return new IModel();
            case 1:
                return new JModel();
            case 2:
                return new LModel();
            case 3:
                return new OModel();
            case 4:
                return new SModel();
            case 5:
                return new TModel();
            case 6:
                return new ZModel();
        }
        return null;
    }

    public Rectangle makeRect(double x, double y) {
        Rectangle rect = new Rectangle(BLEN, BLEN);
        rect.setStrokeLineCap(StrokeLineCap.BUTT);
        rect.setStroke(Color.valueOf("#cccccc"));
        rect.setLayoutX(x);
        rect.setLayoutY(y);
        rect.setArcWidth(5);
        rect.setArcHeight(5);
        LinearGradient linearGradient1 = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, new Stop[]{
                new Stop(0, Color.WHITESMOKE),
                new Stop(1, Color.valueOf(getRandColor()))
        });
        rect.setFill(linearGradient1);
        Glow glow = new Glow();
        rect.setEffect(glow);
        return rect;
    }

    public static Rectangle makeShadowRect(double x, double y) {
        Rectangle rect = new Rectangle(BLEN, BLEN);
        rect.setStrokeLineCap(StrokeLineCap.BUTT);
        rect.setStroke(Color.valueOf("white"));
        rect.setLayoutX(x);
        rect.setLayoutY(y);
        rect.setArcWidth(5);
        rect.setArcHeight(5);
        Glow glow = new Glow();
        rect.setEffect(glow);
        return rect;
    }

    public String getRandColor() {
        if (myFillColor == null) {
            int ra = new Random().nextInt(COLOR.length);
            myFillColor = COLOR[ra];
        }
        return myFillColor;
    }


    public synchronized void down(int n) {
        if (isPause()) {
            return;
        }
        int step = 1;
        if (!canDown(step)) {
            if (isTop()) {
                gameOver = true;
            } else {
                add2PointRectList();
                modelOver = true;
            }
            return;
        }
        if (modelOver || gameOver) {
            return;
        }
        if (n == -1) {
            step = getStep(step);
        }
        for (int i = 0; i < list.size(); i++) {
            move(i, 0, BLEN * step);
        }
        //show shadow
        moveShadowRect();
        if (n == -1) {
            add2PointRectList();
            modelOver = true;
        }
    }

    private int getStep(int step) {
        while (canDown(step + 1)) {
            step++;
        }
        return step;
    }


    private void add2PointRectList() {
        Set<Double> ySet = new TreeSet<>();//此处必须用treeSet,意在使消除的行按Y轴升序排,这样移掉的时候就不影响
        for (Rectangle rect : list) {
            POINT_RECT_LIST.add(rect);
            ySet.add(rect.getLayoutY());
        }
        Rectangle oneRect;
        LINE = 0;
        List<Rectangle> destoryRectList;
        for (Double y : ySet) {
            destoryRectList = new ArrayList<>();
            for (double x = 0; x < BLEN * 10; x += BLEN) {
                oneRect = getOneRect(POINT_RECT_LIST, x, y);
                if (oneRect != null) {
                    destoryRectList.add(oneRect);
                } else {
                    break;
                }
            }
            if (destoryRectList.size() == 10) {
                POINT_RECT_LIST.removeAll(destoryRectList);
                DESTORY_Y_LIST.add(y);
                LINE++;
            }
        }
    }


    private Rectangle getOneRect(List<Rectangle> pointRectList, Double x, Double y) {
        for (Rectangle rect : pointRectList) {
            if (x.equals(rect.getLayoutX()) && y.equals(rect.getLayoutY())) {
                return rect;
            }
        }
        return null;
    }


    public boolean canDown(int step) {
        for (int i = 0; i < list.size(); i++) {
            if (!move(true, i, 0, BLEN * step)) {
                return false;
            }
        }
        return true;
    }

    public synchronized void up() {
        int num = now + 1 == 5 ? 1 : now + 1;
        if (modelOver || !flipTest(num)) {
            return;
        }
        now = num;
        flip(now);
    }

    public synchronized void left() {
        lateralMove(-BLEN);
    }

    public synchronized void right() {
        lateralMove(BLEN);
    }

    private void flip(int num) {
        flip(false, num);
        moveShadowRect();
    }

    public void moveShadowRect() {
        int step = getStep(1);
        if (shadowList.isEmpty()) {
            for (int i = 0; i < list.size(); i++) {
                shadowList.add(makeShadowRect(list.get(i).getLayoutX(), list.get(i).getLayoutY() + BLEN * step));
            }
        } else {
            if (step == 1){
                for (int i = 0; i < list.size(); i++) {
                    shadowList.get(i).setLayoutX(list.get(i).getLayoutX());
                    shadowList.get(i).setLayoutY(list.get(i).getLayoutY());
                    final int n=i;
                    Platform.runLater(()->{
                        shadowList.get(n).toBack();
                        shadowList.get(n).setStroke(Color.valueOf("white"));
                    });

                }
            }else {
                for (int i = 0; i < list.size(); i++) {
                    shadowList.get(i).setLayoutX(list.get(i).getLayoutX());
                    shadowList.get(i).setLayoutY(list.get(i).getLayoutY() + BLEN * step);
                    final int n=i;
                    Platform.runLater(()->{
                        shadowList.get(n).toFront();
                        if (step<=3) {
                            shadowList.get(n).setStroke(Color.valueOf("red"));
                        }
                    });
                }
            }
        }
    }

    private boolean flipTest(int num) {
        return flip(true, num);
    }

    public void lateralMove(int size) {
        if (modelOver || gameOver) {
            return;
        }
        if (move(true, 0, size, 0)
                && move(true, 1, size, 0)
                && move(true, 2, size, 0)
                && move(true, 3, size, 0)
        ) {
            move(0, size, 0);
            move(1, size, 0);
            move(2, size, 0);
            move(3, size, 0);
            moveShadowRect();
        }
    }


    public void move(int index, int x, int y) {
        move(false, index, x, y);
    }

    public boolean move(boolean isTry, int i, int x, int y) {
        double xx = list.get(i).getLayoutX() + x;
        double yy = list.get(i).getLayoutY() + y;
        if (isTry) {
            if (isPointRect(xx, yy)) {//如果位移位置属于已落方块范畴,则位移无效
                return false;
            }
            return boxCheck(xx, yy);
        }
        list.get(i).setLayoutX(xx);
        list.get(i).setLayoutY(yy);
        //move2(list.get(i), x, y);
        return true;
    }


    protected boolean isPointRect(Double xx, Double yy) {
        for (Rectangle rect : POINT_RECT_LIST) {
            if (xx.equals(rect.getLayoutX()) && yy.equals(rect.getLayoutY())) {
                return true;
            }
        }
        return false;
    }

    protected boolean boxCheck(double xx, double yy) {
        return xx >= 0 && xx <= XXBottom && yy >= 10 && yy <= YYBottom;
    }


    public List<Rectangle> getList() {
        return list;
    }

    public List<Rectangle> getShadowList() {
        return shadowList;
    }

    public boolean isModelOver() {
        return modelOver;
    }

    public void setModelOver(boolean modelOver) {
        this.modelOver = modelOver;
    }

    public void setGameOver(boolean gameOver) {
        this.gameOver = gameOver;
    }

    protected abstract boolean flip(boolean test, int num);


    public void destory() {
        list.clear();
        POINT_RECT_LIST.clear();
        modelOver = true;
    }

    public ABSModel clone() {
        ABSModel obj = null;
        try {
            obj = (ABSModel) super.clone();
        } catch (CloneNotSupportedException ex) {
            ex.printStackTrace();
        }
        return obj;
    }

    private boolean isTop() {
        for (int i = 0; i < 4; i++) {
            if (list.get(i).getLayoutY() == 10) {
                return true;
            }
        }
        return false;
    }

    public boolean isGameOver() {
        return gameOver;
    }

    public boolean isPause() {
        return pause;
    }

    public void clearClass() {
        POINT_RECT_LIST.clear();
    }
}

 

package model;

import javafx.scene.shape.Rectangle;
import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 * ────
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class IModel extends ABSModel {

    public IModel() {
        for (int i = 0; i < 4; i++) {
            Rectangle rect = makeRect(i * BLEN + 75, 10);
            list.add(rect);
        }
    }

    public boolean flip(boolean isTry, int num) {
        switch (num) {
            case 2://right
            case 4://left
                return move(isTry, 0, BLEN, -BLEN)
                        && move(isTry, 2, -BLEN, BLEN)
                        && move(isTry, 3, -BLEN * 2, BLEN * 2);
            case 3://down
            case 1://up
                return move(isTry, 0, -BLEN, BLEN)
                        && move(isTry, 2, BLEN, -BLEN)
                        && move(isTry, 3, BLEN * 2, -BLEN * 2);
        }
        return false;

    }


}

 

package model;

import javafx.scene.shape.Rectangle;
import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 * └──
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class JModel extends ABSModel {

    public JModel() {
        list.add(makeRect(75, 10));
        for (int i = 0; i < 3; i++) {
            Rectangle rect = makeRect(i * BLEN + 75, BLEN + 10);
            list.add(rect);
        }
    }

    public boolean flip(boolean isTry, int num) {
        switch (num) {
            case 2://right
                return move(isTry, 0, BLEN * 2, 0)
                        && move(isTry, 1, BLEN, -BLEN)
                        && move(isTry, 3, -BLEN, BLEN);
            case 3://isTry,down
                return move(isTry, 0, 0, BLEN * 2)
                        && move(isTry, 1, BLEN, BLEN)
                        && move(isTry, 3, -BLEN, -BLEN);
            case 4://isTry,left
                return move(isTry, 0, -BLEN * 2, 0)
                        && move(isTry, 1, -BLEN, BLEN)
                        && move(isTry, 3, BLEN, -BLEN);
            case 1://isTry,up
                return move(isTry, 0, 0, -BLEN * 2)
                        && move(isTry, 1, -BLEN, -BLEN)
                        && move(isTry, 3, BLEN, BLEN);
        }
        return false;
    }


}

 

package model;

import javafx.scene.shape.Rectangle;
import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 * ──┘
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class LModel extends ABSModel {


    public LModel() {
        list.add(makeRect(75 + BLEN * 2, 10));
        for (int i = 2; i >= 0; i--) {
            Rectangle rect = makeRect(i * BLEN + 75, BLEN + 10);
            list.add(rect);
        }
    }

    @Override
    protected boolean flip(boolean isTry, int num) {
        switch (num) {
            case 2://right
                return move(isTry, 0, 0, BLEN * 2)
                        && move(isTry, 1, -BLEN, BLEN)
                        && move(isTry, 3, BLEN, -BLEN);
            case 3://isTry,down
                return move(isTry, 0, -BLEN * 2, 0)
                        && move(isTry, 1, -BLEN, -BLEN)
                        && move(isTry, 3, BLEN, BLEN);
            case 4://isTry,left
                return move(isTry, 0, 0, -BLEN * 2)
                        && move(isTry, 1, BLEN, -BLEN)
                        && move(isTry, 3, -BLEN, BLEN);
            case 1://isTry,up
                return move(isTry, 0, BLEN * 2, 0)
                        && move(isTry, 1, BLEN, BLEN)
                        && move(isTry, 3, -BLEN, -BLEN);
        }
        return false;
    }
}

 

package model;

import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 * 田
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class OModel extends ABSModel {

    public OModel() {
        list.add(makeRect(75 + BLEN, 10));
        list.add(makeRect(75 + BLEN * 2, 10));
        list.add(makeRect(75 + BLEN, 10 + BLEN));
        list.add(makeRect(75 + BLEN * 2, 10 + BLEN));
    }

    @Override
    protected boolean flip(boolean isTry, int num) {
        return true;
    }
}

 

package model;

import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 *  ┌─
 * ─┘
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class SModel extends ABSModel {

    public SModel() {
        list.add(makeRect(75 + BLEN * 2, 10));
        list.add(makeRect(75 + BLEN, 10));
        list.add(makeRect(75 + BLEN, 10 + BLEN));
        list.add(makeRect(75, 10 + BLEN));
    }

    @Override
    protected boolean flip(boolean isTry, int num) {
        switch (num) {
            case 2://right
            case 4://left
                return move(isTry, 0, 0, BLEN * 2)
                        && move(isTry, 1, BLEN, BLEN)
                        && move(isTry, 3, BLEN, -BLEN);
            case 3://down
            case 1://up
                return move(isTry, 0, 0, -BLEN * 2)
                        && move(isTry, 1, -BLEN, -BLEN)
                        && move(isTry, 3, -BLEN, BLEN);

        }
        return false;
    }
}

 

package model;

import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 * ─┴─
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class TModel extends ABSModel {

    public TModel() {
        list.add(makeRect(75+BLEN, 10));
        list.add(makeRect(75, 10 + BLEN));
        list.add(makeRect(75+BLEN, 10 + BLEN));
        list.add(makeRect(75+BLEN*2, 10 + BLEN));
    }

    @Override
    protected boolean flip(boolean isTry, int num) {
        switch (num) {
            case 2://right
                return move(isTry, 0, BLEN, BLEN)
                        && move(isTry, 1, BLEN, -BLEN)
                        && move(isTry, 3, -BLEN, BLEN);
            case 3://isTry,down
                return move(isTry, 0,-BLEN, BLEN)
                        && move(isTry, 1, BLEN, BLEN)
                        && move(isTry, 3, -BLEN, -BLEN);
            case 4://isTry,left
                return move(isTry, 0, -BLEN,  -BLEN)
                        && move(isTry, 1, -BLEN, BLEN)
                        && move(isTry, 3, BLEN, -BLEN);
            case 1://isTry,up
                return move(isTry, 0, BLEN, -BLEN)
                        && move(isTry, 1, -BLEN, -BLEN)
                        && move(isTry, 3, BLEN, BLEN);
        }
        return false;
    }
}

 

package model;

import model.abs.ABSModel;

import static fx.MainController.BLEN;

/**
 * ─┐
 *  └─
 *
 * @Author: jdkleo
 * @Date: 2020-06-19
 * @Version: 1.0
 */
public class ZModel extends ABSModel {

    public ZModel() {
        list.add(makeRect(75 + BLEN, 10));
        list.add(makeRect(75 + BLEN*2, 10));
        list.add(makeRect(75 + BLEN*2, 10 + BLEN));
        list.add(makeRect(75 + BLEN*3, 10 + BLEN));
    }

    @Override
    protected boolean flip(boolean isTry, int num) {
        switch (num) {
            case 2://right
            case 4://left
                return move(isTry, 0, BLEN * 2,0 )
                        && move(isTry, 1, BLEN, BLEN)
                        && move(isTry, 3, -BLEN, BLEN);
            case 3://down
            case 1://up
                return move(isTry, 0, -BLEN * 2, 0)
                        && move(isTry, 1, -BLEN, -BLEN)
                        && move(isTry, 3, BLEN, -BLEN);

        }
        return false;
    }
}

 

package util;

import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Control;

import java.util.Optional;

public class AlertUtil {

    public static ButtonType buttonTypeOne = new ButtonType("默认速度500ms");
    public static ButtonType buttonTypeTwo;

    public static void errorAlert(String title, String content, Control control) {
        errorAlert(title, null, content, control);
    }


    public static void errorAlert(String title, String header, String content, Control control) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle(title);
        alert.setHeaderText(header);
        alert.setContentText(content);
        alert.showAndWait();
        control.requestFocus();
    }


    public static Optional<ButtonType> chooseAlert(String title, String content,String nowSpeed) {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle(title);
        alert.setHeaderText(null);
        alert.setContentText(content);
        buttonTypeTwo = new ButtonType("当前速度"+nowSpeed+"ms");
        alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo);
        return alert.showAndWait();
    }


}

 

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onKeyPressed="#keyDown" onKeyReleased="#keyUp" prefHeight="600" prefWidth="428.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fx.MainController">
   <children>
      <Rectangle id="mainBox" fx:id="mainBox" accessibleText="sysRect" arcHeight="5.0" arcWidth="5.0" height="504" layoutX="0.0" layoutY="8.0" stroke="BLACK" strokeType="INSIDE" width="252" />
      <Label layoutX="277.0" layoutY="155.0" text="分数">
         <font>
            <Font size="18.0" />
         </font></Label>
      <Label fx:id="fractionLab" layoutX="319.0" layoutY="140.0" text="0" textAlignment="CENTER" textFill="#dd480d" textOverrun="LEADING_WORD_ELLIPSIS" wrapText="true">
         <font>
            <Font name="Tempus Sans ITC" size="38.0" />
         </font>
      </Label>

      <Label layoutX="382.0" layoutY="195.0" text="ms">
         <font>
            <Font size="18.0" />
         </font></Label>
      <Label layoutX="266.0" layoutY="8.0" text="下一个"> <font>
      <Font size="18.0" />
      </font></Label>
      <Rectangle id="nextBox" accessibleText="sysRect" arcHeight="5.0" arcWidth="5.0" height="91.0" layoutX="265.0" layoutY="40.0" stroke="#70801c" strokeLineCap="ROUND" strokeType="OUTSIDE" strokeWidth="5.0" width="118.0" />
      <CheckBox fx:id="downSpeedChk" layoutX="266.0" layoutY="225.0" mnemonicParsing="false" selected="true" text="随分数加快下降速度" />
      <CheckBox fx:id="downEndChk" layoutX="266.0" layoutY="251.0" mnemonicParsing="false" selected="true" text="下降键一键到底" />
      <CheckBox fx:id="showGrid" layoutX="266.0" layoutY="275.0" mnemonicParsing="false" onAction="#onShowGridChecked" selected="true" text="显示网格" />
      <CheckBox fx:id="showShadow" layoutX="343.0" layoutY="275.0" mnemonicParsing="false" onAction="#onShowShadowChecked" selected="true" text="显示倒影" />
      <Button fx:id="restartBtn" blendMode="EXCLUSION" layoutX="266.0" layoutY="319.0" mnemonicParsing="false" onAction="#onRestart" prefHeight="34.0" prefWidth="112.0" text="开始游戏" textOverrun="CLIP">
         <font>
            <Font size="16.0" />
         </font>
      </Button>
      <Text layoutX="266.0" layoutY="386.0" text="上:翻转" />
      <Text layoutX="326.0" layoutY="386.0" text="回车:暂停/继续" />
      <Text layoutX="266.0" layoutY="408.0" text="下:下降一格或到底" />
      <Text layoutX="266.0" layoutY="431.0" text="左:向左移动一格" />
      <Text layoutX="266.0" layoutY="456.0" text="右:向右移动一格" />
      <Text layoutX="266.0" layoutY="482.0" text="1行:10分 2行:30分" />
      <Text layoutX="266.0" layoutY="509.0" text="3行:50分 4行:100分" />
      <Pane fx:id="mainMask" layoutX="0.0" layoutY="8.0" prefHeight="504.0" prefWidth="421.0" style="-fx-border-radius:8px;-fx-opacity: 0.4;-fx-background-color: green ;-fx-z-index: 9998;"  visible="false">
         <Text fill="#f5efef" layoutX="78.0" layoutY="254.0" style="-fx-z-index: 9999;" text="PAUSE">
            <font>
               <Font size="30.0" />
            </font></Text>
      </Pane>
      <Label layoutX="262.0" layoutY="199.0" text="起始速度" />
      <TextField fx:id="speedTxt" layoutX="315.0" layoutY="196.0" prefHeight="23.0" prefWidth="62.0" text="500" />
   </children>
</AnchorPane>

 

 

0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics