java实现贪吃蛇

JFrame窗体

import com.sun.xml.internal.ws.handler.HandlerException;

import javax.swing.*;

public class MainFrame extends JFrame {
    public MainFrame() throws HandlerException{
        //初始化窗口参数
        initFrame();
    }
    //初始化窗口参数
    private void initFrame() {
        //设置岩体高地
        setSize(610,640);
        //设置窗体位置
        setLocation(400,400);
        //设置关闭按钮(退出)
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗体大小不可变
        setResizable(false);
    }

    public static void main(String[] args) {
        //创建窗体对象,显示窗体
        new MainFrame().setVisible(true);
    }
}

JPanel面板 创建游戏棋盘

创建食物

import java.util.Random;

/*
节点: 每一条蛇是由若干节点组成,每个节点(食物)都有横纵坐标确定位置
 */
public class Node {
    private int x;
    private int y;

    public Node() {
    }

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

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
    //随机生成食物位置
    public void random(){
        //创建对象
        Random r=new Random();
        //随机生成横坐标
        this.x=r.nextInt(40);
        //随机生成纵坐标
        this.y = r.nextInt(40);
    }
}

创建蛇

import java.util.LinkedList;

/*
每个节点用LinkedList集合储存Node节点,蛇出生有6个节点
 */
public class snake {
    //蛇身体
    private LinkedList<Node> body;
    public snake(){
        //初始化蛇身体
        initsnake();
    }

    private void initsnake() {
        //创建集合
        body=new LinkedList<>();
        //创建6个节点作为蛇身体
        body.add(new Node(16,20));
        body.add(new Node(17,20));
        body.add(new Node(18,20));
        body.add(new Node(19,20));
        body.add(new Node(20,20));
        body.add(new Node(21,20));
    }

    public LinkedList<Node> getBody() {
        return body;
    }

    public void setBody(LinkedList<Node> body) {
        this.body = body;
    }
}

完整代码

主函数:MainFrame

import com.sun.xml.internal.ws.handler.HandlerException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;

public class MainFrame extends JFrame {
    private snake snake;
    private JPanel jPanel;//游戏棋盘
    private Timer timer;//定时器 在指定时间调用蛇移动的方法
    private Node food;//食物

    public MainFrame() throws HandlerException{
        //初始化窗口参数
        initFrame();
        //初始化游戏棋盘
        initGamePanel();
        //初始化蛇
        initsnake();
        //初始化食物
        initFood();
        //初始化定时器
        initTimer();
        //设置键盘监听,让蛇随着键盘方向移动
        setKeyListener();
    }
      //初始化食物
    private void initFood() {
        food=new Node();
        food.random();//调用Random方法 随机生成食物
    }

    private void setKeyListener() {
        addKeyListener(new KeyAdapter() {
            @Override
            //pressed按下 当键盘按下时,会自动调用此方法
            public void keyPressed(KeyEvent e) {
                //键盘中每一个键都有编号 获取编号
                switch (e.getKeyCode()){
                    case KeyEvent.VK_UP:  //上键
                        //修改蛇的运动方向
                        //当向上走的时候,做判断 如果蛇的运动方向不是下,才能走
                        if (snake.getDirection()!=Direction.DOWN){
                         snake.setDirection(Direction.UP);
                    }
                        //snake.setDirection(Direction.UP);
                        break;
                    case KeyEvent.VK_DOWN:  //下键
                        if (snake.getDirection()!=Direction.UP){
                            snake.setDirection(Direction.DOWN);
                        }
//                        snake.setDirection(Direction.DOWN);
                        break;
                    case KeyEvent.VK_LEFT:  //左键
                        if (snake.getDirection()!=Direction.RIGHT){
                            snake.setDirection(Direction.LEFT);
                        }
//                        snake.setDirection(Direction.LEFT);
                        break;
                    case KeyEvent.VK_RIGHT:  //右键
                        if (snake.getDirection()!=Direction.LEFT){
                            snake.setDirection(Direction.RIGHT);
                        }
//                        snake.setDirection(Direction.RIGHT);
                        break;
                }
            }
        });
    }

    //初始化定时器
    private void initTimer() {
        timer=new Timer();
        //初始化定时任务
        TimerTask timerTask = new TimerTask(){
            @Override
            public void run() {
              snake.nove();
                //判断蛇吃食物 蛇头与食物重合
                Node head = snake.getBody().getFirst();
                if (head.getX()==food.getX()&&head.getY()==food.getY()){
                    snake.eat(food);
                    food.random();
                }
                //每次移动都重绘游戏棋盘(刷新)
                jPanel.repaint();
            }
        };
        //每一百毫米执行一次任务   0秒开始执行(延迟) 过程为100毫秒
        timer.scheduleAtFixedRate(timerTask,0,120);
    }
    //初始化蛇
    private void initsnake() {
        snake=new snake();
    }

    //初始化游戏棋盘
    private void initGamePanel() {
           jPanel = new JPanel(){
            @Override
            //绘制游戏棋盘中的内容
            public void paint(Graphics g) {
                //清空棋盘
                g.clearRect(0,0,600,600);
                //Graphics g可以看做画笔,提供了很多方法绘制基本的图像
                //绘制40调横线  40.fori快速生成
                /*
                第一条:起点(0,0) 终点(600,0)
                第二条:起点(0,15)终点(600,15)
                ....
                第n条:起点(0,n*15)终点(600,n*15)
                 */
                for (int i = 0; i <=40; i++) {
                    g.drawLine(0,i*15,600,i*15);
                }
                //绘制40条竖线
                /*
                第一条:起点(0,0)  终点(0,600)
                第n条:起点(15*n,0)终点(0,600)
                 */
                for (int i = 0; i <=40; i++) {
                   g.drawLine(i*15,0,i*15,600);
                }
                //绘制蛇
                LinkedList<Node> body = snake.getBody();
                for (Node node:body){
                    g.fillRect(node.getX()*15,node.getY()*15,15,15);
                }
                //绘制食物
                g.fillRect(food.getX()*15,food.getY()*15,15,15);
            }
        };
        //把棋盘添加到窗体中
        add(jPanel);
    }

    //初始化窗口参数
    private void initFrame() {
        //设置岩体高地
        setSize(610,640);
        //设置窗体位置
        setLocation(400,400);
        //设置关闭按钮(退出)
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗体大小不可变
        setResizable(false);
    }

    public static void main(String[] args) {
        //创建窗体对象,显示窗体
        new MainFrame().setVisible(true);
    }
}


节点:Node
import java.util.Random;

/*
节点: 每一条蛇是由若干节点组成,每个节点(食物)都有横纵坐标确定位置
 */
public class Node {
    private int x;
    private int y;

    public Node() {
    }

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

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
    //随机生成食物位置
    public void random(){
        //创建对象
        Random r=new Random();
        //随机生成横坐标
        this.x=r.nextInt(40);
        //随机生成纵坐标
        this.y = r.nextInt(40);
    }
}


蛇:snake
import java.util.LinkedList;

/*
每个节点用LinkedList集合储存Node节点,蛇出生有6个节点
 */
public class snake {
    //蛇身体
    private LinkedList<Node> body;
    //蛇的运动方向  默认为左边
    private Direction direction=Direction.LEFT;
    //用于判断蛇是否活着
    private boolean isliving=true;
    public snake(){
        //初始化蛇身体
        initsnake();
    }

    private void initsnake() {
        //创建集合
        body=new LinkedList<>();
        //创建6个节点作为蛇身体
        body.add(new Node(16,20));
        body.add(new Node(17,20));
        body.add(new Node(18,20));
        body.add(new Node(19,20));
        body.add(new Node(20,20));
        body.add(new Node(21,20));
    }
    //蛇沿着蛇头方向移动
    // 控制蛇移动 在蛇头运动的方向添加一个节点  同时在蛇尾的节点删除,实现移动
    public void nove(){
        if (isliving) {
            //获取蛇头
            Node head = body.getFirst();
            switch (direction) {
                case UP://如果向上 则在蛇的上面添加一个节点 横坐标不变,纵坐标-1
                    body.addFirst(new Node(head.getX(), head.getY() - 1));
                    break;
                case DOWN:
                    body.addFirst(new Node(head.getX(), head.getY() + 1));
                    break;
                case LEFT:
                    body.addFirst(new Node(head.getX() - 1, head.getY()));
                    break;
                case RIGHT:
                    body.addFirst(new Node(head.getX() + 1, head.getY()));
                    break;
            }
            //删除蛇尾的节点
            body.removeLast();
            //判断是否撞墙 撞墙则将状态转为false
            head=body.getFirst();
            if (head.getX()<0||head.getY()<0||head.getX()>=40||head.getY()>=40){
                isliving=false;
                 System.out.println("分数:"+ body.size());
            }
            //判断蛇是否吃到自己  用蛇头与身体各位置比较 如果位置相同 就吃到自己
            for (int i=1;i<body.size();i++){  //i=1,不是等于0,等于0直接死
                Node node = body.get(i);
                if (head.getX()==node.getX()&&head.getY()==node.getY()){
                    isliving=false;
                     System.out.println("分数:"+ body.size());
                }
            }
        }
    }

    public LinkedList<Node> getBody() {
        return body;
    }

    public void setBody(LinkedList<Node> body) {
        this.body = body;
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }
    //蛇吃食物 沿着蛇头方向添加一个节点  与移动蛇的代码相同
    public void eat(Node food) {
        Node head = body.getFirst();
        switch (direction) {
            case UP://如果向上 则在蛇的上面添加一个节点 横坐标不变,纵坐标-1
                body.addFirst(new Node(head.getX(), head.getY() - 1));
                break;
            case DOWN:
                body.addFirst(new Node(head.getX(), head.getY() + 1));
                break;
            case LEFT:
                body.addFirst(new Node(head.getX() - 1, head.getY()));
                break;
            case RIGHT:
                body.addFirst(new Node(head.getX() + 1, head.getY()));
                break;
        }
    }
}


枚举:按键 Direction 用Enum建
/*
枚举:几个固定常量,制作按键:来定义控制键
 */
public enum Direction {
    UP,DOWN,LEFT,RIGHT
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以运行! (以下代码只是其中的一个类) package chy.snake.entities; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import chy.snake.listener.SnakeListener; import chy.snake.util.Global; public class Snake { public static final int up = 1; public static final int down = -1; public static final int left = -2; public static final int right = 2; private int oldDirection,newDirection; //newDirection:一次时间 间隔内输入的最后方向 private Point oldTail; private boolean life; //life 为 true或者false,初始为true, 用于118行 private LinkedList<Point> body = new LinkedList<Point> (); //需要经常访问蛇的第一个和最后一个节点,使用链表LinkedList存放蛇的身体节点,因为它有getFirst(),getLast(),removeLast(),方法 private Set<SnakeListener> listeners = new HashSet<SnakeListener>(); public Snake(){ init(); } public void init(){ //初始化 int x = Global.WIDTH/2; int y = Global.HEIGHT/2; for(int i=0;i<3;i++){ //初始长度3 body.addLast(new Point(x-i,y)); //是addLast } oldDirection = newDirection = right; //初始方向 右 life = true; } public void die(){ life = false; } public void move(){ System.out.println("Snake's move"); if (!(oldDirection + newDirection == 0)){ oldDirection = newDirection; } //1.去尾 oldTail = body.removeLast(); int x = body.getFirst().x; int y = body.getFirst().y; //蛇头的x,y坐标 switch(oldDirection){ case up: y--; break; case down: y++; break; case left: x--; break; case right: x++; break; } Point newHead = new Point(x,y); //2.加头 body.addFirst(newHead); } public void changeDirection(int direction){ /*无效方向:在蛇的这一次移动之后和下一次移动之前的 这个时间间隔内输入了多个方向,只有最后一个方向 是 有效方向,其余的都为无效方向*/ System.out.println("Snake's changeDirection"); newDirection = direction; //将一个时间间隔内按得最后方向,赋给 newDirection } public void eatFood(){ System.out.println("Snake's eatFood"); body.addLast(oldTail); //后面的节点不去掉 } public boolean isEatFood(){ System.out.println("Snake's isEatFood"); return false; } public boolean isEatBody(Snake snake){ //比较蛇是否吃到身体 System.out.println("snake's isEatBody"); for(int i= 1;i<body.size();i++){ //i 从蛇头结点的下一个节点开始,排除蛇头结点 if(body.get(i).equals(this.getHead())){ //如果i 的节点 和 头结点 相同 return true; } } return false; } public void drawMe(Graphics g){ System.out.println("Snake's drawMe"); g.setColor(Color.GREEN); //设置蛇的颜色 for(Point p : body){ g.fill3DRect(p.x * Global.CELL_SIZE, p.y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true); } } public Point getHead(){ //得到蛇头节点,判断吃食物 return body.getFirst(); } private class SnakeDriver implements Runnable{ //线程,不停的调用move方法 @Override public void run() { // TODO 自动生成的方法存根 while(life){ // 42和46行,life为true 或者false move(); for(SnakeListener l : listeners){ l.snakeMoved(Snake.this); //循环,依次调用SnakeMoved方法 } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } } public void start(){ new Thread(new SnakeDriver()).start(); //启动线程的方法 } public void addSnakeListener(SnakeListener l){ if(l != null){ this.listeners.add(l); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值