Java贪吃蛇 (有窗口)

84 阅读5分钟
先画好网格 游戏范围 
public class Grid { //定义网格  public static int rows;  //列数  public static int cols;   //行数  public static int size;  //格子大小  /** * 构造一个网格 * * @param rows 行数 * @param cols 列数 */  public Grid(int rows, int cols, int size) {
        this.rows = rows;
        this.cols = cols;
        this.size = size;
    }

}

再定义节点 根据节点来描述食物和蛇位置

public class Node {  //定义节点  private  int col;  //col 列数  private  int row;  //row 行数  /** * 构造函数(初始化一个节点) * @param row  * @param col  */  public Node(int row,int col){
        this.col = col;
        this.row = row;
    }

    /** * 拷贝构造函数  (用一个已经存在的对象复制出另一个对象) * @param node 待复制的节点 */  public Node(Node node) {
       this.row = node.getRow();
       this.col = node.getCol();
    }

    /** * 判断节点是否相等 * @param p  * @return true-相等   false-不相等 */  public boolean isSame(Node p){
            //  return (p.col ==this.col && p.row ==this.row);

    }

    public int getCol() {
        return col;
    }

    public int getRow() {
        return row;
    }

    public void setCol(int col) {
        this.col = col;
    }

    public void setRow(int row) {
        this.row = row;
    }
}

定义蛇这个类
import java.util.LinkedList;public class Snake { //蛇移动的方向 **public static final byte LEFT = 1; public static final byte RIGHT = -1; public static final byte UP = 2; public static final byte DOWN = -2; public byte direction = RIGHT; //默认初始移动方向 *public byte beforeDirection = RIGHT; private boolean isGrow = false; //默认不成长 public byte getDirection() { return direction; } public void setDirection(byte direction) { this.direction = direction; } private LinkedList snakeBody = new LinkedList<>(); //来一条蛇 / ** 初始化一条蛇 (位于左上角长度为4向右移动的蛇) / public Snake(){ for (int n = 1; n <=4 ; n++) { Node node = new Node(0,4-n); snakeBody.add(node); } direction = RIGHT; } / ** 蛇的移动 */ *public void move(){ / 思路:加头去尾 ** / //加头:(1)复制当前的头 (2)根据方向跳整横坐标或纵坐标 // (3)插入到头部 **Node head = snakeBody.getFirst(); //找到蛇头 **Node newHead = new Node(head); switch (direction){ case LEFT: //键盘改方向使蛇移动 *newHead.setCol(newHead.getCol()-1); break; case RIGHT: newHead.setCol(newHead.getCol()+1); break; case UP: newHead.setRow(newHead.getRow()-1); break; case DOWN: newHead.setRow(newHead.getRow()+1); break; } snakeBody.addFirst(newHead); //移动的时候判断是否需要去尾(是否生长) if (!isGrow){ snakeBody.removeLast(); }else { isGrow = false; } } / ** 蛇的生长 / public void grow(){ isGrow = true; } / ** 判断蛇是否吃到自己 *** @return */ public boolean eatSelf(){ / ** 将蛇身的每个节点和舌头进行比较, ** 只要有一个重合的则说明迟到了自己 */ **Node head = snakeBody.getFirst(); //拿到蛇头 *for (int i =1;i<snakeBody.size();i++){ //遍历循环和身体相比较 if (snakeBody.get(i).isSame(head)){ return true; } } return false; } / ** 判断蛇是否撞到墙 *** @return ***/ **public boolean isCollide(){ if (getSnakeBody().getFirst().getCol()==Grid.cols||getSnakeBody().getFirst().getRow()==Grid.rows ||getSnakeBody().getFirst().getCol()<0||getSnakeBody().getFirst().getRow()<0){ return true; } return false; } public LinkedList getSnakeBody(){ return snakeBody; }}
定义食物这个类

import java.util.LinkedList;

public class Food {  //定义随机食物的点  private Node node;

    public Node getNode() {
        return node;
    }
    private static int x,y;

    // 写一个构造函数  public Food(Grid grid,Snake snake){
       // 思路:(1)随机生成食物的位置(横纵坐标) (2) 判断食物有没有与蛇重叠 //(3)重复以上过程直到确定一个没有重叠的位置   while(true){
            //随机生成一个横纵坐标  x = (int)(Math.random()*Grid.cols);
          y = (int)(Math.random()*Grid.rows);
          Node food = new Node(x,y);

          //判断是否与蛇身重叠 LinkedList<Node> body = snake.getSnakeBody();
        boolean overlap = false; //蛇身与食物是否重叠的标记  for(Node node:body){  //遍历蛇的身体  if(food.equals(node)){
                   overlap = true;
                  break;
              }
           }
           //如果没有重叠,则确定了位置,结束  if(!overlap){
           this.node = food;
           break;   }
         }
       }



    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

定义游戏这个类 来操作游戏里的蛇

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;

public class Game {

    private Frame frame; //定义一个弹框  private Canvas canvas; //定义一个画布  private Graphics graphics; // 定义一个画笔   private Snake snake; //三个属性 成员  private Grid grid;
    private Food food;

    public Game(int rows, int cols, int size) {
        snake = new Snake(); //小程序.蛇  grid = new Grid(rows, cols, size); //网格  food = new Food(grid,snake); //食物   frame = new Frame( "小程序/贪吃蛇" ); //窗口名  frame.setSize(500, 500); //窗口大小  canvas = new Canvas(); //来一个新画布  frame.add(canvas); //把画布放在窗口里  frame.setVisible(true); //true-可见 false - 不可见 drawGrid();  //画出网格线 drawFood();  //画食物 drawSnake(); //画蛇  if (snake.eatSelf() || snake.isCollide()){  //如果蛇吃到自己或者碰到了墙游戏结束  int res=JOptionPane.showConfirmDialog(null, "是否继续游戏" , "游戏结束" , JOptionPane.YES_NO_OPTION);
            if(res==JOptionPane.YES_OPTION){  //点击“是”后执行这个代码块  }else{
                System.exit(1);  //点击“否”后执行这个代码块  return;
            }
        }
        if (isEatFood()){ //如果吃到了食物 蛇就生长 ,食物重新初始化  snake.grow();
            food = new Food(grid,snake);
        }
        snake.move();
        // 键盘事件  用来控制蛇的方向  canvas.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                handleKeyPress(e.getKeyCode());
            }
        });
    }
    /** * 画出网格线 游戏布局 */  public void drawGrid() {
        graphics = canvas.getGraphics();
        graphics.setColor(Color.white);
        graphics.fillRect(0, 0, grid.rows * grid.size, grid.cols * grid.size);
        graphics.setColor(Color.BLACK);

        for (int i=0; i <= grid.rows; i++) {
            graphics.drawLine(0, i * grid.size, grid.rows * grid.size, i * grid.size);
        }
        for (int i = 0; i <= grid.cols; i++) {
            graphics.drawLine(i * grid.size, 0, i * grid.size, grid.cols * grid.size);
        }
    }
    /** * 判断蛇是否吃到食物 * @return 吃到食物 false-没有吃到食物 */  public boolean isEatFood(){
        //拿到蛇的头部节点 Node head = snake.getSnakeBody().getFirst();
        //判断蛇头的节点与食物的节点是否相等  return food.getNode().isSame(head);
     }
    /** * 画食物 */  public void drawFood() {
        drawNode(food.getNode(),Color.BLUE);
       /* graphics = canvas.getGraphics(); graphics.setColor(Color.RED); //拿到食物节点的坐标 graphics.fillRect(food.getX() * grid.size, food.getY() * grid.size, grid.size, grid.size); */ }
    /** * 画蛇 */  public void drawSnake() {
        LinkedList<Node> snakeBody = snake.getSnakeBody();
        graphics = canvas.getGraphics();
        for (int i = 0; i < snakeBody.size(); i++) {
            Node node = snakeBody.get(i);
            drawNode(node,0==i?Color.MAGENTA:Color.CYAN);
          //  if (i == 0) { drawNode(node,Color.CYAN); } else { drawNode(node,Color.cyan); } }
    }

    /** * 绘制节点 * @param node 待绘制的节点 * @param color 待绘制的背景色 */  private void drawNode(Node node,Color color){
        graphics = canvas.getGraphics();
        graphics.setColor(color);
        graphics.fillRect(node.getCol() * grid.size, node.getRow() * grid.size, grid.size, grid.size);
    }

    /** *改变蛇的方向 * @param keyCode 按键键码 */  private void handleKeyPress(int keyCode) {
          int dir =snake.beforeDirection;
        switch (keyCode) {
            case KeyEvent.VK_SPACE:

            case KeyEvent.VK_LEFT:
                if (dir!= snake.RIGHT){
                   snake.setDirection(Snake.LEFT);
                   snake.beforeDirection = snake.getDirection();
                }
                break;
            case KeyEvent.VK_UP: //上  if (dir!= snake.DOWN){
                    snake.setDirection(Snake.UP);
                    snake.beforeDirection = snake.getDirection();
                }
                break;
            case KeyEvent.VK_RIGHT: // 右  if (dir!=snake.LEFT){
                    snake.setDirection(snake.RIGHT);
                    snake.beforeDirection = snake.getDirection();
                }
                break;
            case KeyEvent.VK_DOWN: // 下  if (dir!=snake.UP) {
                    snake.setDirection(snake.DOWN);
                    snake.beforeDirection = snake.getDirection();
                }
                break;
            default:
                break;
        }

    }

    public static void main(String[] args) {
        Game game = new Game(25, 25, 20);
        game.start();
    }
    public void start() {
        new Thread(){
            @Override
            public void run() {
            LinkedList<Node> snakeBody = snake.getSnakeBody();
                while (true) {
                    snake.move(); //移动蛇 //如果蛇吃到自己或者碰到了墙游戏结束  if (snake.eatSelf() || snake.isCollide()){
                        int res=JOptionPane.showConfirmDialog(null, "是否继续游戏" , "游戏结束" , JOptionPane.YES_NO_OPTION);
                        if(res==JOptionPane.YES_OPTION){ //点击“是”后执行这个代码块 System.out.println( "重新2来过" );
                            break;
                        }else{   //点击“否”后执行这个代码块 System.exit(1);
                            return;
                        }
                    }
                    //如果吃到了食物 蛇就生长  if (isEatFood()){
                        snake.grow();
                        food = new Food(grid,snake);
                    }
                    drawGrid();
                    drawFood();
                    drawSnake();

                        try { //线程 延迟五百毫秒  也就是0.5秒动一下  sleep(150);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

        }.start();
    }
}