窗体贪吃蛇_手把手教你写贪吃蛇游戏

8adeb6297c34b103b3fcfc8d09e6c2de.png

创建窗体

创建一个MainFrame类继承JFrame,表示主窗体。

public class MainFrame extends JFrame {    //创建窗体对象时,初始化船体参数    public MainFrame(){        initFrame();    }}

MainFrame类中写一个initFrame方法,初始化窗体参数

//1.初始化窗体参数private void initFrame() {    //设置窗体标题    setTitle("黑马贪吃蛇");    //设置窗体大小    setSize(610, 640);    //设置窗体位置    setLocation(400, 400);    //设置窗体大小不能改变    setResizable(false);    //设置窗体关闭按钮的作用,是正常退出    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}

在MainFrame中添加一个main方法,创建窗体并运行,就可以看到窗体了

//主方法public static void main(String[] args) {    //创建窗体,并显示在屏幕上    new MainFrame().setVisible(true);}

创建游戏棋盘

在JFrame类中写一个initGamePanel方法,初始化游戏棋盘

//初始化游戏面板private void initGamePanel() {    JPanel jPanel = new JPanel() {        //paint是用来绘制面板中的内容        @Override        public void paint(Graphics g) {            //设置画笔颜色            g.setColor(Color.black); //设置画笔颜色是黑色            //绘制40条横线(起点横坐标,起点纵坐标,终点横坐标,终点纵坐标)            for(int i=1;i<=40;i++){                g.drawLine(0,15*i,600,15*i);            }​            //绘制40条竖线            for (int i=1;i<=40;i++){                g.drawLine(15*i,0,15*i,600);            }        }    };    add(jPanel);}

创建蛇的节点

创建一个Node类表示节点,一条蛇有若干个节点组成,每一个节点其实就是一个小方格,我们用行和列来定义节点在棋盘中的位置。

public class Node {    private int x; //横坐标    private int 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;    }}

创建蛇身

创建Snake类表示蛇,一条蛇有多个节点使用LinkedList集合存储Node节点,蛇出生的时候 有3个节点。

public class Snake {    //body    private LinkedList body;        //创建蛇对象时,初始化蛇身    public Snake() {        initSnake();    }​    //初始化蛇身 3个节点    public void initSnake(){        //创建蛇的躯体        body=new LinkedList<>();        //给蛇添加3个节点,在棋盘的中心位置横向排列        body.add(new Node(20,20));        body.add(new Node(21,20));        body.add(new Node(22,20));    }      //获取蛇蛇身    public LinkedList getBody(){        return body;    }}

把蛇绘制到棋盘上

在MainFrame中添加一个创建Snake的成员变量,表示窗体中有一条蛇

public class MainFrame extends JFrame {    //定义成员变量    private Snake snake=new Snake();    ....}

在绘制棋盘的paint方法中,添加下面的代码绘制把蛇绘制到棋盘上

//绘制横线...//绘制竖线...​//绘制蛇,根据每一个节点的坐标在棋盘上绘制矩形for (Node node : snake.getBody()) {    //每一个节点的宽度和高度是15    g.fillRect(node.getX()*15,node.getY()*15,15,15);} 

再次运行,就可以看到有一条蛇静静的躺在棋盘中间了

让蛇移动

定义一个枚举类型,表示运动的4个方向

public enum  Direction {    UP,DOWN,LEFT,RIGHT}

在Snake类中定义一个移动方向的变量成员变量,和move方法。

public class Snake{    //蛇头运动的方向    private Direction direction;        //移动的方法: 每次移动在蛇头运动方向添加一个节点,再删除最后一个节点    public void move(){        //获取蛇头的节点        Node head = body.getFirst();        //新的蛇头节点        Node newHead=null;        //检查移动的方向        switch (direction){            //如果向左移动            case LEFT:                //创建一个新的蛇头节点                 newHead=new Node(head.getX()-1,head.getY());                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                //删除蛇尾                body.removeLast();                break;            case RIGHT:                //创建一个新的蛇头节点                newHead=new Node(head.getX()-1,head.getY());                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                //删除蛇尾                body.removeLast();                break;            case UP:                //创建一个新的蛇头节点                newHead=new Node(head.getX(),head.getY()-1);                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                //删除蛇尾                body.removeLast();                break;            case DOWN:                //创建一个新的蛇头节点                newHead=new Node(head.getX(),head.getY()+1);                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                //删除蛇尾                body.removeLast();                break;        }    }}

在MainFrame类中,创建一个定时器每100毫秒,重绘游戏棋盘

public class MainFrame extends JFrame {    ...    //游戏棋盘面板    JPanel jPanel=null;    //定义定时器    private Timer timer;        public MainFrame() throws HeadlessException {        //初始化窗体参数        initFrame();        //初始化窗体中的游戏面板        initGamePanel();        //初始化定时器        initTimer();    }        //2.初始化游戏棋盘    private void initGamePanel() {         jPanel = new JPanel() {            //paint是用来绘制面板中的内容            @Override            public void paint(Graphics g) {//每次重绘时清空面板中的内容                g.clearRect(0,0,getWidth(),getHeight());               ....            }        };        add(jPanel);    }    //3.初始化定时器    private void initTimer() {        TimerTask task=new TimerTask() {            @Override            public void run() {                //调用蛇移动的方法                snake.move();                //每次移动重绘游戏棋盘,会自动调用jPanel的paint方法                jPanel.repaint();            }        };        timer=new Timer();        timer.scheduleAtFixedRate(task,0,100);    }}

添加键盘监听

在MainFrame类中,添加一个setKeyListener的方法,监听上下左右四个键

public class MainFrame extends JFrame {    ...    public MainFrame() throws HeadlessException {       ...        //添加键盘监听        setkeyListener();    }        //添加键盘监听    private void setkeyListener() {        //对上下左右键进行监听        addKeyListener(new KeyAdapter() {            @Override            public void keyPressed(KeyEvent e) {                switch (e.getKeyCode()){                    //按下上键                    case KeyEvent.VK_UP:                        //蛇头方向改为上                        snake.setDirection(Direction.UP);                        break;                    //按下下键                    case KeyEvent.VK_DOWN:                        //蛇头方向改为下                        snake.setDirection(Direction.DOWN);                        break;                    //按下左键                    case KeyEvent.VK_LEFT:                        //蛇头方向改为左                        snake.setDirection(Direction.LEFT);                        break;                    //按下右键                    case KeyEvent.VK_RIGHT:                        //蛇头方向改为右                        snake.setDirection(Direction.RIGHT);                        break;                }            }        });    }}

到此蛇就可以跟随键盘移动了

添加边界处理

当蛇移动到边界处就游戏结束,把标记改为false

public class Snake{    ...    //定义一个标记true表示蛇是活的,可以运动    private boolean isLive=true;        //检查蛇是否碰壁    private void checkOver() {        //获取蛇头        Node head = body.getFirst();        int x=head.getX();        int y=head.getY();        if(x<0||y<0||x>=40||y>=40){            isLive=false;        }    }}

在定时器中调用checkOver()方法

//3.初始化定时器private void initTimer() {    TimerTask task=new TimerTask() {        @Override        public void run() {            //移动            snake.move();            //检查是否碰壁            snake.checkOver();        }    };    timer=new Timer();    timer.scheduleAtFixedRate(task,0,100);}

把食物绘制到棋盘上

创建一个Food类表示食物,其实食物也是一个节点,所以让Food继承Node

public class Food extends Node {    //创建食物的时候,随机产生一个位置    public Food() {        reset();    }    //随产生位置    public void reset(){        //随机生成食物的坐标        Random r=new Random();        setX(r.nextInt(40));        setY(r.nextInt(40));    }}

在MainFrame中定义一个成员Food表示食物,并把食物绘制到棋盘上

public class MainFrame extends JFrame {    //定义食物    private Node food=new Node();        public MainFrame() throws HeadlessException {        //初始化窗体参数        initFrame();        //初始化窗体中的游戏面板        initGamePanel();        //初始化定时器        initTimer();        //添加键盘监听        setkeyListener();    }        //2.初始化游戏棋盘    private void initGamePanel() {         jPanel = new JPanel() {            //paint是用来绘制面板中的内容            @Override            public void paint(Graphics g) {                //清空棋盘                g.clearRect(0,0,600,600);                                //绘制横线、绘制竖线、绘制蛇                //绘制食物                g.fillRect(food.getX()*15,food.getY()*15,15,15);            }        };        add(jPanel);    }}

吃食物

在Snake类中添加一个eatFood方法

//吃食物public void eatFood() {    //获取蛇头    Node head = body.getFirst();    //如果蛇头和食物的位置重合,就在蛇头添加一个元素  if(head.getX()==MainFrame.food.getX()     &&head.getY()==MainFrame.food.getY()){        //沿着蛇头运动方向创建一个节点        //新的蛇头节点        Node newHead=null;        //检查移动的方向        switch (direction){                //如果向左移动            case LEFT:                //创建一个新的蛇头节点                newHead=new Node(head.getX()-1,head.getY());                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                break;            case RIGHT:                //创建一个新的蛇头节点                newHead=new Node(head.getX()+1,head.getY());                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                break;            case UP:                //创建一个新的蛇头节点                newHead=new Node(head.getX(),head.getY()-1);                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                break;            case DOWN:                //创建一个新的蛇头节点                newHead=new Node(head.getX(),head.getY()+1);                //把心得蛇头节点添加到body的第一个元素                body.addFirst(newHead);                break;        }        //每次吃完食物,让食物重置        MainFrame.food.reset();    }}

在定时器中调用吃食物的方法

//2.初始化游戏棋盘private void initGamePanel() {    jPanel = new JPanel() {        //paint是用来绘制面板中的内容        @Override        public void paint(Graphics g) {            //清空棋盘            g.clearRect(0,0,600,600);            //绘制横线、绘制竖线、绘制蛇            //绘制食物            g.fillRect(food.getX()*15,food.getY()*15,15,15);        }    };    add(jPanel);}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值