贪吃蛇小游戏的简单实现——Java

贪吃蛇

  • 贪吃蛇
    • 源码:

贪吃蛇

贪吃蛇这一款小游戏,在以前的诺基亚手机中基本都会带有这款,曾经风靡一时。
那么我们如何将这一款小游戏实现出来呢?
在这里,我们会使用到javaFX图形化编程,将图形化界面打印出来,通过用户的实际操作,来控制游戏,如下图:

这就是,游戏最终实现的情况。
我们可以通过蛇的速度来控制游戏难度,通过控制方向左右移动,实现游戏的逻辑,最后完成。
首先我们会导入很多的包,大多数都是javafx的,因为需要图形化界面,我们需要导入它,javafx是jdk自带的。

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.util.Arrays;
import java.util.Random;

我们定义贪吃蛇的身体初始为3,食物随机生成,每次吃完食物速度会增加,同时获得一分,当头部撞墙,或者头部撞到身体后,游戏结束。当游戏结束,按R从新开始游戏。
具体看源码,参照注释阅读:

源码:

public class Point {
     
    public int x;
    public int y;

    public Point(int x, int y) {
     
        this.x = x;
        this.y = y;
    }
}

package snake;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.util.Arrays;
import java.util.Random;

public class SnakeAPP extends Application {
     
    //定义变量
    //游戏区域大小,格子的的宽和高
    private static final int WIDTH = 20;
    private static final int HEIGHT = 20;
    //绘制图形的时候,格子所占的大小
    private static final int GRID_SIZE = 40;
    private static final int CANVAS_WIDTH = WIDTH * GRID_SIZE;
    private static final int CANVAS_HEIGHT = HEIGHT * GRID_SIZE;
    //定义游戏本身
    //移动速度
    //speed,每秒的帧数
    private static int speed;
    //食物
    private static Point food = new Point(-1, -1);
    //蛇,最多长1000节
    private static Point[] snake = new Point[1000];
    //现在多少节
    private static int snakeLength = 0;

    //朝向
    enum Direction {
     
        UP, LEFT, DOWN, RIGHT
    }

    private static Direction direction;
    //随机生成器
    private static Random random = new Random();
    //游戏结束标志
    private static boolean gameOver;

    //初始化游戏数据
    private static void newGame() {
     
        speed = 3;
        //蛇的初始有3节
        Arrays.fill(snake, null);
        snakeLength = 0;
        snake[snakeLength++] = new Point(WIDTH / 2, HEIGHT / 2);
        snake[snakeLength++] = new Point(WIDTH / 2, HEIGHT / 2);
        snake[snakeLength++] = new Point(WIDTH / 2, HEIGHT / 2);
        //生成食物
        newFood();
        direction = Direction.LEFT;
        //游戏未结束
        gameOver = false;
    }

    //在地图上随机生成食物
    private static void newFood() {
     
        //1,不能生成在外面
        //2.不能和蛇的身体碰撞
        int x, y;
        do {
     
            x = random.nextInt(WIDTH);
            y = random.nextInt(HEIGHT);
        } while (isCollision(x, y));

        food.x = x;
        food.y = y;
    }

    private static boolean isCollision(int x, int y) {
     
        //遍历蛇
        //不要用foreach
        for (int i = 0; i < snakeLength; i++) {
     
            Point point = snake[i];
            if (point.x == x && point.y == y) {
     
                return true;
            }
        }
        return false;
    }

    //每一帧做的动作
    private static void frame() {
     
        //移动身体
        for (int i = snakeLength - 1; i >= 1; i--) {
     
            //变成前一个坐标
            snake[i].x = snake[i - 1].x;
            snake[i].y = snake[i - 1].y;
        }
        //移动头
        Point head = snake[0];
        switch (direction) {
     
            case UP:
                head.y--;
                break;
            case DOWN:
                head.y++;
                break;
            case LEFT:
                head.x--;
                break;
            case RIGHT:
                head.x++;
                break;
        }
        //判断头是否出边界
        if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
     
            gameOver = true;
            return;
        }
        //判断是否碰到身体
        for (int i = 1; i < snakeLength; i++) {
     
            Point point = snake[i];
            if (head.x == point.x && head.y == point.y) {
     
                gameOver = true;
                return;
            }
        }
        //判断是否吃到食物
        // 如果吃到食物
        // 1.身体增加1节    2.重新生成食物    3. 速度增加
        if (head.x == food.x && head.y == food.y) {
     
            snake[snakeLength++] = new Point(-1, -1);
            newFood();
            speed++;
        }
    }

    //每一帧绘制工作,渲染
    private static void render(GraphicsContext gc) {
     
        //1.从新绘制背景
        gc.setFill(Color.BLACK);
        gc.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
        //2.蛇的绘制
        for (int i = 0; i < snakeLength; i++) {
     
            Point point = snake[i];
            gc.setFill(Color.GREEN);
            gc.fillRect(point.x * GRID_SIZE + 1, point.y * GRID_SIZE + 1, GRID_SIZE - 2, GRID_SIZE - 2);
        }
        //3.食物的绘制
        gc.setFill(Color.YELLOW);
        gc.fillOval(food.x * GRID_SIZE + 1, food.y * GRID_SIZE + 1, GRID_SIZE, GRID_SIZE);
        //3.进行游戏结束绘制
        if (gameOver) {
     
            gc.setFill(Color.RED);
            gc.setFont(new Font(40));
            gc.fillText("游戏结束,按R继续", 200, 200);
        }

        //得分
        gc.setFill(Color.AQUAMARINE);
        gc.setFont(new Font(20));
        gc.fillText("当前得分"+ (speed-3)+"分", 40, 40);
        //作者
        gc.setFill(Color.AQUA);
        gc.setFont(new Font(15));
        gc.fillText("版本:v1.0    作者:H485301267 ", 20, 740);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
     
        //游戏的初始化
        newGame();
        Pane pane = new Pane();
        Canvas canvas = new Canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
        pane.getChildren().add(canvas);

        Scene scene = new Scene(pane);

        final GraphicsContext gc = canvas.getGraphicsContext2D();
        AnimationTimer timer = new AnimationTimer() {
     
            long lastTiick;

            @Override
            public void handle(long now) {
     
                if (gameOver) {
     
                    return;
                }
                if (lastTiick == 0 || now - lastTiick > 1e9 / speed) {
     
                    lastTiick = now;
                    frame();
                    render(gc);
                }
            }
        };
        timer.start();
        scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
     
            @Override
            public void handle(KeyEvent event) {
     
                switch (event.getCode()) {
     
                    case W:
                    case UP:
                        if (direction != Direction.DOWN) {
     
                            direction = Direction.UP;
                        }
                        break;
                    case A:
                    case LEFT:
                        if (direction != Direction.RIGHT) {
     
                            direction = Direction.LEFT;
                        }
                        break;
                    case S:
                    case DOWN:
                        if (direction != Direction.UP) {
     
                            direction = Direction.DOWN;
                        }
                        break;
                    case D:
                    case RIGHT:
                        if (direction != Direction.LEFT) {
     
                            direction = Direction.RIGHT;
                        }
                        break;
                    case R:
                        if (gameOver) {
     
                            newGame();
                        }
                        break;
                }
            }
        });
        primaryStage.setScene(scene);
        primaryStage.setTitle("贪吃蛇");
        primaryStage.setResizable(false);
        primaryStage.sizeToScene();
        primaryStage.show();
    }

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

你可能感兴趣的:(JavaSE,游戏,贪吃蛇,javafx)