基于javase的贪吃蛇小项目

前言:此项目是面向过程思想

一、Node类

package com.example.snack;

import java.awt.*;
import java.util.Objects;

/**
 * 节点类:
 */
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;
    }

    /**
     * 绘制结点
     * @param g
     * 传递一个画笔过来
     */

    public void drawNode(Graphics g,int i){
        if(0==i){
            g.fillOval(this.x,this.y,20-1,20-1);
        }else {
            g.fillRect(this.x, this.y, 20 - 1, 20 - 1);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Node node = (Node) o;
        return x == node.x && y == node.y;
    }

}

二、SnackFrame08类

package com.example.snack;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
 *1.绘制窗体内容
 *展示游戏的主界面
 *Frame->窗体【位置、大小、背景色、标题】
 * 设置窗体可见
 * 关闭窗口的事件监听
 *窗口不能重新设置大小
 *
 * 2.绘制图形
 *
 * 3.绘制蛇的身体
 *
 * 4动起来
 * 1>窗口一直重绘
 * 2>修改坐标
 *
 *5.手动控制方向
 * 1.添加键盘监听事件
 * 2.根据按键修改方向
 *
 * 6.食物
 *主体Node
 * 位置:满足窗体中隐形的格子
 *
 * 7.蛇吃食物
 *  何时吃到食物
 *  蛇的身体加长
 *
 *8.结束游戏
 *  头部碰到边界|头部碰到身体
 */
public class SnackFrame08 extends Frame {
    public static final int WINDOW_X=200;
    public static final int WINDOW_Y=100;
    public static final int WINDOW_W=600;
    public static final int WINDOW_H=500;

    //上 1,下 3;右 0; 左 2
    public static final int UP=1;
    public static final int DOWN=3;
    public static final int RIGHT=0;
    public static final int LEFT=2;

    private int speed =200;



    //程序是否还在运行
    private boolean isRunning =true;
    //上 1,下 3;右 0; 左 2
    private  int direction = 0;

    private Node food =new Node(randomNum(0,WINDOW_W/20-1)*20,randomNum(2,WINDOW_H/20-1)*20);


    //蛇的主体部分
    private Node[] body ={
            new Node(140,100),
            new Node(120,100),
            new Node(100,100),

    };


    //构造器当中初始化窗体
    public SnackFrame08(){
        this.setLocation(WINDOW_X,WINDOW_Y);//窗体位置
        this.setSize(WINDOW_W,WINDOW_H);//窗体的大小
        this.setVisible(true);//设置窗体可见
        this.setResizable(false);//不能改变窗体大小
        this.setTitle("贪吃蛇V1.0");//标题
        this.setBackground(Color.MAGENTA);//背景颜色

        //注册窗口监听
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e){
                System.exit(0);//退出虚拟机
            }
        });
        //注册键盘监听
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //System.out.println(e.getKeyCode());
                //System.out.println(KeyEvent.VK_DOWN);
                //上 1,下 3;右 0; 左 2
                int dir=-1;
                switch (e.getKeyCode()){
                    case KeyEvent.VK_UP://向上走
                        dir=UP;
                        break;
                    case KeyEvent.VK_DOWN://向下走
                        dir =DOWN;
                        break;
                    case KeyEvent.VK_RIGHT://向右走
                        dir=RIGHT;
                        break;
                    case KeyEvent.VK_LEFT://向左走
                        dir =LEFT;
                        break;
                }

                //根据合法性修改方向(不允许在同一条直线修改)
                if(direction%2 != dir%2){
                    direction = dir;
                }

            }
        });
        start();
    }

    /**
     * * 为绘制蛇的主题做准备
     * 窗体显式|更新的时候 会自动调用
     * 绘制图形、线条、文本
     * @param g 画笔
     */
     @Override
    public void paint(Graphics g) {
        g.setColor(Color.ORANGE);
        //绘制蛇的主体部分
       for(int i=0;i<body.length;i++){
           body[i].drawNode(g,i);
       }
       g.setColor(Color.BLUE);
       food.drawNode(g,-1);

       if(isRunning){
           if(isEat()){
               //System.out.println("吃到食物");
               addBody();
           }else{
               move();//修改坐标
           }
           isOver();
       }else {
           //System.out.println("game over");
           g.setColor(new Color(29, 65, 208));
           g.setFont(new Font(null,Font.ITALIC,100));
       g.drawString("gameover",WINDOW_W/2-200-20,WINDOW_H/2);

       }


     }

    /**
     * 游戏是否结束
     * @return true 游戏结束 false 游戏继续
     */
     public void isOver(){
        Node head =body[0];
        //边界
         if(head.getX()<20 || head.getX()>=WINDOW_W-20||head.getY()<30 || head.getY()>=WINDOW_H-20){
             isRunning =false;
         }
         //头碰到身体
         for(int i =1;i<body.length;i++){
             if(head.equals(body[i])){
                 isRunning =false;
             }
         }
     }

    /**
     * 吃到食物了,增加蛇的身体
     *      将食物变为蛇的头部
     *食物重新产生
     *      食物消失
     */
    public void addBody(){
        Node[] temp =new Node[body.length+1];
        temp[0] =food;
        System.arraycopy(body,0,temp,1,body.length);
        body=temp;
        food =null;
        productFood();
    }

    /**
     * 是否吃到食物:下一步的头结点的位置 刚好和食物位置相等
     */
    public boolean isEat(){
        Node newHead =getNewHead();
        if(newHead.equals(food)){
            return true;
        }
            return false;
    }

    /**
     * 随机产生食物
     */
    public void productFood(){
        food=new Node(randomNum(0,WINDOW_W/20-1)*20,randomNum(2,WINDOW_H/20-1)*20);
    }

    /**
     * 通过修改坐标来达到移动的效果
     */
    public void move(){
        //向右移动
        //每一次通过一个新的头节点,去掉尾节点即可
        Node[] temp =new Node[body.length];//创建一个新的数组,里面是空的
        temp[0] =getNewHead();//头部里的第一个结点通过方向确定新节点的位置
        //去掉尾部
        System.arraycopy(body,0,temp,1,body.length-1);
        //把body里面新节点的内容拷贝
        this.body=temp;
    }

    /**
     * 根据方向来确定新的头结点
     * @return
     */
    public Node getNewHead(){
        Node newNode =body[0];
        switch(this.direction){
            //上 1,下 3;右 0; 左 2
            case 0:
                newNode =new Node(newNode.getX()+20,newNode.getY());
                break;
            case 2:
                newNode =new Node(newNode.getX()-20,newNode.getY());
                break;
            case 1:
                newNode =new Node(newNode.getX(),newNode.getY()-20);
                break;
            case 3:
                newNode =new Node(newNode.getX(),newNode.getY()+20);
                break;
        }
        return newNode;
    }


    /**
     * 手动一直重绘窗体
     */
    public void start(){
        while(isRunning){
            super.repaint();
            try {
                Thread.sleep(speed);//暂停事件
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        super.repaint();
    }

    public static int randomNum(int min,int max){
        return (int)(Math.random()*(max-min+1)+min);
    }

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值