活在控制台的贪吃蛇游戏

活在控制台的贪吃蛇游戏

忽然想写个贪吃蛇小游戏。
实现起来很简单,用队列保存小蛇的身体座标。在位置座标中小蛇头部的下一步位置激活,尾部位置取消激活实现小蛇移动,实现捕食效果则尾部不取消激活小蛇长度增加。

import java.util.Scanner;

public class SnakeTest {

    private Scanner sc;

    private int r;// 随机数值
    private int d;// 输入的数字
    private int[][] dir = { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };// 方向数组,下,左,上,右

    private final int width = 5;// 宽
    private final int height = 5;// 高
    private int[][] pos;// 位置数组

    private int head_x, head_y;// 头部座标
    private int snake_length = 2;// 初始场长度
    private int cur_dir;// 当前方向

    private int food_x, food_y;// 食物座标

    MyLink link;// 队列对象

    public static void main(String[] args) {
        System.out.println("【贪吃蛇】");
        SnakeTest st = new SnakeTest();
        st.initGame();
        st.runGame();
    }

    private void initGame() {

        sc = new Scanner(System.in);// 实例化输入类

        // 随机初始化起源点及方向
        r = (int) (Math.random() * (width * height));
        head_x = r % width;
        head_y = r / width;
        cur_dir = (int) (Math.random() * 4);

        // 初始化座标数组以及实例化自定义的队列类
        pos = new int[width][height];
        link = new MyLink(width, height);

        // 将第一个座标放进队列并激活位置座标
        link.in(head_y, head_x);
        pos[head_y][head_x] = 1;

        // 根据起源座标直线延伸至设定长度,因此最大长度为width或height
        for (int i = 1; i < snake_length; i++) {
            head_x += dir[cur_dir][1];
            head_y += dir[cur_dir][0];
            // 检查并处理数组以及游戏边界
            check();
            link.in(head_y, head_x);
            pos[head_y][head_x] = 1;// 激活
        }

        // 初始化食物座标
        randomFood();
    }

    private void runGame() {
        while (true) {

            draw();// 打印在控制台

            d = sc.nextInt();

            // 0 1 2 3 下 上 右 左
            control(d);

            head_x += dir[cur_dir][1];
            head_y += dir[cur_dir][0];

            // 检查并处理数组以及游戏边界
            check();

            // 如果咬到自己游戏失败
            if (pos[head_y][head_x] == 8) {// 吃到东西 长度+1
                snake_length++;
                link.in(head_y, head_x);// 把头部座标塞进队列
                pos[head_y][head_x] = 1;// 将头部座标激活

                // 是否大满贯
                if (snake_length == width * height) {
                    draw();
                    System.out.println("胜利!");
                    return;
                }
                randomFood();// 随机生成食物座标
            } else {// 否则队列操作,实现小蛇移动
                int[] tail = link.out();// 队列将尾部座标移除;
                pos[tail[0]][tail[1]] = 0;// 取消激活尾部座标
                if (pos[head_y][head_x] == 1) {
                    System.out.println("咬到自己啦!\n小蛇长度:"+snake_length);
                    return;
                }
                link.in(head_y, head_x);// 把头部座标塞进队列
                pos[head_y][head_x] = 1;// 将头部座标激活
            }
        }
    }

    private void control(int d) {
        if (cur_dir != 2 && d == 0)// 当前方向不允许为向上情况允许向下转弯,下同
            cur_dir = 0;
        else if (cur_dir != 3 && d == 1)
            cur_dir = 1;
        else if (cur_dir != 0 && d == 2)
            cur_dir = 2;
        else if (cur_dir != 1 && d == 3)
            cur_dir = 3;
    }

    private void check() {
        if (head_x < 0)
            head_x = width - 1;
        else if (head_x == width)
            head_x = 0;
        if (head_y < 0)
            head_y = height - 1;
        else if (head_y == height)
            head_y = 0;
    }

    private void draw() {
        System.out.println("数字: [0]下,[1]左,[2]上,[3]右");
        System.out.printf("头部座标:第%d行,第%d列\n", head_y + 1, head_x + 1);
        System.out.print("当前方向为:");
        switch (cur_dir) {
        case 0:
            System.out.println("下");
            break;
        case 1:
            System.out.println("左");
            break;
        case 2:
            System.out.println("上");
            break;
        case 3:
            System.out.println("右");
        }

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                System.out.printf("%-2s", pos[i][j]);
            }
            System.out.println();
        }
    }

    private void randomFood() {
        while (pos[food_y][food_x] != 0) {
            r = (int) (Math.random() * (width * height));
            food_y = r / width;
            food_x = r % width;
        }
        pos[food_y][food_x] = 8;
    }

}

class MyLink {
    private int[][] link;
    private int head_index;
    private int tail_index;

    public MyLink(int x, int y) {
        link = new int[x * y][2];
    }

    public void in(int x, int y) {
        link[head_index][0] = x;
        link[head_index][1] = y;
        head_index++;
        head_index %= link.length;
    }

    public int[] out() {
        int[] index = { link[tail_index][0], link[tail_index][1] };
        tail_index++;
        tail_index %= link.length;
        return index;
    }
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章