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>
相关推荐
设计一个简化版的俄罗斯方块游戏。游戏窗口大小是 20×10 的方形棋盘格阵列,游戏中出现的方块共有 7 种,每种方块的旋转中心由黑点标出。 具体实现内容和步骤包括: **1.方块/棋盘格和方块向下移动** 创建窗口,...
在本文中,我们将深入探讨如何使用JavaFX技术来实现经典的电子游戏——俄罗斯方块。JavaFX是一个用于构建桌面、移动和嵌入式设备上的富客户端应用程序的Java库。它的强大功能使得开发图形用户界面(GUI)变得简单且...
↓ 方块丢下(方块下落到底) 2、一旦堆到屏幕顶端,游戏结束 3、设计不同的方块 4、设计方块下落的速度 5、设计分数系统 内容详情:https://blog.csdn.net/qq_40869977/article/details/122702076 需要技术指导...
《使用JavaFx实现的俄罗斯方块小游戏》是一个利用Java编程语言和JavaFx图形库开发的桌面版游戏。JavaFx是Oracle公司推出的用于构建桌面、移动和嵌入式系统的富客户端应用平台,它提供了丰富的UI控件和强大的图形处理...
【标题】:“俄罗斯方块java版” 在编程领域,俄罗斯方块是一款经典的休闲游戏,而“俄罗斯方块java版”则是使用Java编程语言实现的这一经典游戏。Java是一种广泛使用的面向对象的编程语言,以其“一次编写,到处...
《Java实现俄罗斯方块初级版详解》 在编程领域,用Java语言开发游戏是一种常见的实践,其中,俄罗斯方块作为一款经典的游戏,是初学者学习游戏编程的理想选择。本项目"java俄罗斯方块初级版"旨在帮助开发者了解如何...
《俄罗斯方块网络版》是一款基于Java编程语言开发的游戏,它不仅包含了经典的单机模式,还创新性地引入了网络多人对战模式,使得玩家可以与来自各地的对手进行实时竞技,大大增加了游戏的趣味性和挑战性。...
在Java中开发俄罗斯方块,开发者通常会利用Java的Swing或JavaFX库来构建用户界面,这些库提供了丰富的组件和图形功能,用于创建游戏的图形界面。游戏的核心逻辑则涉及到数据结构和算法的设计。例如,开发者可能会用...
【JAVA俄罗斯方块单人版】是一个基于Java编程语言实现的经典游戏项目,它允许玩家在自己的设备上体验经典的俄罗斯方块玩法。这个项目是专为单人玩家设计的,因此不涉及多人对战功能。要运行这个程序,首先需要确保你...
NULL 博文链接:https://zoboya.iteye.com/blog/1855398
java程序设计期末课设,使用javafx的俄罗斯方块小游戏.zip java程序设计期末课设,使用javafx的俄罗斯方块小游戏.zip java程序设计期末课设,使用javafx的俄罗斯方块小游戏.zip java程序设计期末课设,使用javafx的...
Java语言实现的俄罗斯方块是一款经典的桌面游戏,它利用了编程的基本概念,如循环、条件判断、对象和类,以及图形用户界面(GUI)的设计。在这个项目中,开发者需要理解以下核心知识点: 1. **Java基础**:Java是...
《Java实现的俄罗斯方块游戏源码解析》 在编程世界中,经典的俄罗斯方块游戏是一种常见的练习项目,它能够帮助开发者巩固基础,提升逻辑思维能力。本篇将深入探讨一个由Java语言编写的俄罗斯方块游戏源码,通过分析...
《俄罗斯方块A3版源码与截图解析》 俄罗斯方块是一款经典的电子游戏,以其简单易懂的规则和无尽的挑战性深受全球玩家喜爱。在这个A3版本中,开发者不仅保留了游戏的核心玩法,还增加了新的功能,提升了游戏体验。...
在编写俄罗斯方块这样的游戏时,Java的Swing或JavaFX库提供了图形用户界面(GUI)的构建模块,如JPanel、JFrame等,用于创建游戏窗口和交互元素。 其次,该程序的核心算法是游戏逻辑。俄罗斯方块的基本元素包括不同...
俄罗斯方块的图形界面通常使用Java的Swing或JavaFX库来构建。Swing提供了丰富的组件和工具,可以方便地创建窗口、按钮、面板等元素。开发者可能使用了`JFrame`作为游戏窗口,`JPanel`作为画布来绘制方块,以及`...
【Java编程实现俄罗斯方块游戏】 在编程领域,创建一个经典游戏如俄罗斯方块是一种常见的学习实践,可以加深对编程语言特性和面向对象设计的理解。在这个案例中,我们看到一个用Java实现的俄罗斯方块游戏。Java作为...