javafx贪吃蛇游戏

效果图:
在这里插入图片描述
包含: 登录 保存 读取存档 暂停游戏 继续游戏 增加难度 减少难度的功能

目录结构如下:
在这里插入图片描述
部分代码如下:

package save;

import entity.SnakeCell;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SaveGame implements Serializable {

    public SaveCell food;
    public int score;
    public int speed;
    public List<SaveCell> cells;



    public SaveGame(SnakeCell food, int score, int speed, List<SnakeCell> cells){
        this.food = new SaveCell(food.getX(), food.getY(), food.getCellLen(), food.getShade());
        this.score = score;
        this.cells = new ArrayList<>();
        for(SnakeCell cell : cells){
            this.cells.add(new SaveCell(cell.getX(), cell.getY(), cell.getCellLen(), cell.getShade()));
        }
        this.speed = speed;

    }


}

package view;

import constant.Const;
import entity.SnakeCell;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.util.Pair;
import save.SaveCell;
import save.SaveGame;
import task.MoveTask;


import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;


    public class SnakePane extends Pane {
        public MediaPlayer mp;
        private boolean isPaused = false;
        private SnakeCell food;
        private Canvas canvas;
        private GraphicsContext context;
        private List<SnakeCell> cells = Const.SNAKE_CELL_LIST;
        private int maxScore = 0;
        private int score = 0;
        private int speed = 200;
        private Button startButton;
        private Button pauseButton;
        private Button saveButton;
        private Button readButton;
        private Button upBotton;
        private Button downBotton;
        private volatile static boolean isRequestClose = false;
        private MoveTask task;

        public void setSpeed(int speed) {
            this.speed = speed;
        }

        public int getSpeed() {
            return speed;
        }

        public SnakePane() {
            canvas = new Canvas(800, 800);
            context = canvas.getGraphicsContext2D();
            context.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
            context.setStroke(Color.BLACK);
            getInitMaxScore();
            context.strokeRect(50, 50, canvas.getWidth() - 60, canvas.getHeight() - 60);
            context.strokeText("当前分数为:" + score + " 分",50, 16, 200);
            context.strokeText("最高分数为:" + maxScore + " 分",200, 16, 100);
            context.strokeText("当前speed:" + speed + "ms/次",350, 16, 100);

            getChildren().add(canvas);

            startButton = new Button("开始游戏");
            startButton.setLayoutX(100);
            startButton.setLayoutY(20);

            startButton.setOnAction(event -> {
                // 显示登录对话框
                showLoginDialog();
            });

            pauseButton = new Button("暂停游戏");
            pauseButton.setLayoutX(200);
            pauseButton.setLayoutY(20);

            pauseButton.setOnAction(event -> {
                if(!isPaused){
                    isPaused = true;
                    task.setPaused(true);
                    pauseButton.setText("继续游戏");
                    mp.pause();
                }else{
                    isPaused = false;
                    task.setPaused(false);
                    pauseButton.setText("暂停游戏");
                    mp.play();
                }

            });

            saveButton = new Button("保存游戏");
            saveButton.setLayoutX(300);
            saveButton.setLayoutY(20);
            saveButton.setOnAction(event -> {
                SaveGame saveGame = new SaveGame(food, score, speed, cells);
                try {
                    ObjectOutputStream outputStream = new ObjectOutputStream(Files.newOutputStream(Paths.get("saveGame.dat")));
                    outputStream.writeObject(saveGame);
                    outputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

            });

            readButton = new Button("读取存档");
            readButton.setLayoutX(400);
            readButton.setLayoutY(20);
            readButton.setOnAction(event -> {
                File saveFile = new File("saveGame.dat");
                if (saveFile.exists()) {
                    ObjectInputStream inputStream = null;
                    try {
                        context.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                        inputStream = new ObjectInputStream(Files.newInputStream(saveFile.toPath()));
                        SaveGame saveGame = (SaveGame) inputStream.readObject();
                        food.setX(saveGame.food.getX());
                        food.setY(saveGame.food.getY());

                        score = saveGame.score;
                        speed = saveGame.speed;

                        cells.clear();
                        for (SaveCell c : saveGame.cells){
                            cells.add(new SnakeCell(c.getX(), c.getY(), c.getCellLen(), Color.BLACK, c.getShade()));
                        }
                        inputStream.close();
                    } catch (IOException | ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }

                }
            });

            upBotton = new Button("增加难度");
            upBotton.setLayoutX(500);
            upBotton.setLayoutY(20);
            upBotton.setOnAction(event -> {
                if(speed > 50){
                    speed -= 50;
                }
            });

            downBotton = new Button("降低难度");
            downBotton.setLayoutX(600);
            downBotton.setLayoutY(20);
            downBotton.setOnAction(event -> {
                speed += 50;
            });


            getChildren().addAll(startButton, pauseButton, saveButton, readButton, upBotton, downBotton);
            
            mp = new MediaPlayer(new Media("https://prod-1.storage.jamendo.com/?trackid=2016794&format=mp31&from=6Rr2c3RVxoxpElvuWG00DA%3D%3D%7CnhMRidYvNhKs7einivGWJw%3D%3D"));

        }




        private void showLoginDialog() {
            Dialog<Pair<String, String>> dialog = new Dialog<>();
            dialog.setTitle("登录");
            dialog.setHeaderText("请输入您的帐号和密码");

            ButtonType loginButtonType = new ButtonType("登录", ButtonBar.ButtonData.OK_DONE);
            dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);

            GridPane gridPane = new GridPane();
            gridPane.setHgap(10);
            gridPane.setVgap(10);
            gridPane.setPadding(new Insets(20, 150, 10, 10));

            TextField username = new TextField();
            username.setPromptText("帐号");
            PasswordField password = new PasswordField();
            password.setPromptText("密码");

            gridPane.add(new Label("帐号:"), 0, 0);
            gridPane.add(username, 1, 0);
            gridPane.add(new Label("密码:"), 0, 1);
            gridPane.add(password, 1, 1);

            Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
            loginButton.setDisable(true);

            username.textProperty().addListener((observable, oldValue, newValue) -> {
                loginButton.setDisable(newValue.trim().isEmpty() || password.getText().trim().isEmpty());
            });

            password.textProperty().addListener((observable, oldValue, newValue) -> {
                loginButton.setDisable(newValue.trim().isEmpty() || username.getText().trim().isEmpty());
            });

            dialog.getDialogPane().setContent(gridPane);

            Platform.runLater(() -> username.requestFocus());

            dialog.setResultConverter(dialogButton -> {
                if (dialogButton == loginButtonType) {
                    return new Pair<>(username.getText(), password.getText());
                }
                return null;
            });

            Optional<Pair<String, String>> result = dialog.showAndWait();

            result.ifPresent(usernamePassword -> {
                String usernameStr = usernamePassword.getKey();
                String passwordStr = usernamePassword.getValue();
                // 检查用户名和密码是否正确
                boolean isLoginSuccess = checkLogin(usernameStr, passwordStr);
                if (isLoginSuccess) {
                    // 登录成功,开始游戏
                    startGame(usernameStr,passwordStr);
                } else {
                    // 登录失败,显示错误提示
                    Alert alert = new Alert(Alert.AlertType.ERROR);
                    alert.setTitle("错误");
                    alert.setHeaderText("登录失败");
                    alert.setContentText("帐号或密码错误,请重新输入");
                    alert.showAndWait();
                    // 重新显示登录对话框
                    showLoginDialog();
                }
            });
        }


        private boolean checkLogin(String username, String password) {
            // 读取用户信息文件
            File file = new File("user.txt");
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    String[] userInfo = line.split(",");
                    if (userInfo[0].equals(username) && userInfo[1].equals(password)) {
                        // 用户名和密码匹配,登录成功
                        return true;
                    }else if(userInfo[0].equals(username) && !userInfo[1].equals(password)){
                        return false;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 用户不存在,自动创建一个新用户
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, true))) {
                writer.write(username + "," + password + "\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 返回登录成功
            return true;
        }
        public void startGame(String username, String password) {
            boolean isLoginSuccess = checkLogin(username, password);
            if (!isLoginSuccess) {
                // 登录失败,直接返回
                return;
            }
            // 播放音乐
            mp.play();
            preStart();
            food = new SnakeCell(190, 150, 20, Color.GREEN, "rectangle");
            setFood(food);
            task = new MoveTask(this);
            task.setOnCancelled(event -> {
                // 在关闭主窗口会回调这里
                if (MoveTask.isForceCancel) {
                    String msg = "";
                    if (MoveTask.isOverBound)
                        msg = "您已出界!";
                    if (MoveTask.isEatItSelf)
                        msg = "您已经不小心把自己给吃了!";
                    Alert alert = new Alert(Alert.AlertType.NONE, msg + "\n是否重新开局?",
                            new ButtonType("重新开局", ButtonBar.ButtonData.YES), new ButtonType("退出游戏", ButtonBar.ButtonData.NO));
                    alert.setTitle("提示");
                    Optional<ButtonType> buttonType = alert.showAndWait();
                    if (buttonType.isPresent()) {
                        if (buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)) {
                            //todo 重新开局
                            MoveTask.isForceCancel = false;
                            MoveTask.reDetect();
                            startGame(username, password);
                        } else {
                            //todo 退出
                            exit(task);
                            Platform.exit();
                        }
                    }
                }
            });
            new Thread(task).start();

            Task<Integer> task1 = new Task<Integer>() {
                @Override
                protected Integer call() throws Exception {
                    while (!isRequestClose) {
                        if (MoveTask.isEatItSelf || MoveTask.isOverBound) {
                            task.cancel(true);
                            MoveTask.isForceCancel = true;
                            break;
                        }
                    }
                    return null;
                }
            };
            new Thread(task1).start();
        }
        public void exit(MoveTask task) {
            if (task != null) {
                task.cancel();
            }
            isRequestClose = true;
        }
        public void preStart() {
            Const.SNAKE_CELL_LIST.clear();
            SnakeCell cell = new SnakeCell(290, 350, 20, Color.BLACK, "rectangle");
            SnakeCell cell1 = new SnakeCell(310, 350, 20, Color.BLACK, "rectangle");
            SnakeCell cell2 = new SnakeCell(330, 350, 20, Color.BLACK, "rectangle");

            Const.SNAKE_CELL_LIST.add(cell);
            Const.SNAKE_CELL_LIST.add(cell1);
            Const.SNAKE_CELL_LIST.add(cell2);
            setScore(0);
            setSpeed(200);
        }

    public void drawCell(){

        cells.forEach(cell -> {

            context.setFill(cell.getColor());
            context.fillOval(cell.getX(), cell.getY(), cell.getCellLen(), cell.getCellLen());

        });

    }

    public void repaint(){

        context.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        context.setStroke(Color.BLACK);
        context.strokeRect(50, 50, canvas.getWidth() - 60, canvas.getHeight() - 60);
        context.strokeText("当前分数为:" + score + " 分",50, 16, 200);
        context.strokeText("最高分数为:" + maxScore + " 分",200, 16, 100);
        context.strokeText("当前speed:" + speed + " ms/次",350, 16, 200);
        cells.forEach(cell->{
            context.setFill(cell.getColor());
            context.fillOval(cell.getX(), cell.getY(), cell.getCellLen(), cell.getCellLen());
        });
        context.setFill(food.getColor());
        context.fillRect(food.getX(), food.getY(), food.getCellLen(), food.getCellLen());

    }

    public void setScore(int score){
        this.score = score;
    }
    public int getScore(){return score;}
    public void setFood(SnakeCell food){
        this.food = food;
    }

    public int getMaxScore() {
        return maxScore;
    }

    public void setMaxScore(int maxScore) {
        this.maxScore = maxScore;
    }

    public void getInitMaxScore(){
        File file = new File("score.txt");
        if (!file.exists()) {
            try {
                file.createNewFile();
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                maxScore = Integer.parseInt(line);
            }

            } catch (IOException ex) {
            throw new RuntimeException(ex);
        }

    }

    public void saveMaxScore() throws IOException {
        File file = new File("score.txt");
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, false))){
            bufferedWriter.write(String.valueOf(maxScore));
        }


    }

    public SnakeCell getFood(){return food;}

}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值