首页 > 其他 > 详细

是我第22喜欢的贪吃蛇Time

时间:2019-03-05 14:08:25      阅读:207      评论:0      收藏:0      [点我收藏+]

是我第22喜欢的贪吃蛇时间     1759239    金益恒

稍微翻了一下以前学java时做的练习,看到了贪吃蛇的代码。不是很长,也有改进空间,刚好可以拿来用,此篇博文诞生,下面就是心路历程和修改思路:

 

First:这是贪吃蛇的界面,我们先设置窗口的大小和行列数,给到标题“贪吃蛇”和出现位置,面子工程第一步,当然这些参数可以随意一点,这里强迫症发作就把数值保持一致。

 

另:为方便读者阅读已修改绝大多数的变量名(比如说SnakeFrame原来就叫SheGeZi。。。现规范格式,进行统一)

 

 

备注总结彩蛋之类的在篇尾,嗯

 

public class SnakeFrame exten

ds Frame{

    public static final int BLOCK_WIDTH = 15 ;

    public static final int BLOCK_HEIGHT = 15 ;

    public static final int ROW = 40;

    public static final int COL = 40;

    public static void main(String[] args) {

        new SnakeFrame().launch();

    }

    public void launch(){

        this.setTitle("贪恰蛇");

        this.setSize(ROW*BLOCK_HEIGHT, COL*BLOCK_WIDTH);

        this.setLocation(300, 300);

        this.addWindowListener(new WindowAdapter() {

            @Override

            public void windowClosing(WindowEvent e) {

                System.exit(0);

            }

        });

        this.setResizable(false);

        this.setVisible(true);

    }

}

下面我们来画网格线以方便玩家进行定位

起初为了醒目是红线网格,现在看来红线其实并不好,还起到了反效果,故这里修改成了灰色网格,同上进行了变量名修改,往后再不赘述(不全改都跑不通我干嘛要作死好麻烦。。。)

@Override

public void paint(Graphics g) {

    Color c = g.getColor();

    g.setColor(Color.GRAY);

for(int i = 0;i<ROW;i++){

        g.drawLine(0, i*BLOCK_HEIGHT, COL*BLOCK_WIDTH,i*BLOCK_HEIGHT );

    }

    for(int i=0;i<COL;i++){

        g.drawLine(i*BLOCK_WIDTH, 0 , i*BLOCK_WIDTH ,ROW*BLOCK_HEIGHT);

    }

 

    g.setColor(c);

}

 

Part3:用构造方法和Draw方法把蛇画出来,Node类表示蛇的节点,这部分除了修改变量名之外做好统一规范之外,没做修改

 

关于Direction,这是个enum

 

public class Node {

 

    private static final int BLOCK_WIDTH = SnakeFrame.BLOCK_WIDTH;

    private static final int BLOCK_HEIGHT = SnakeFrame.BLOCK_HEIGHT;

    private int row;

    private int col;

    private Direction dir ;

    private Node pre;

    private Node next;

 

    public Node(int row, int col, Direction dir) {

        this.row = row;

        this.col = col;

        this.dir = dir;

    }

 

    public void draw(Graphics g){

        Color c = g.getColor();

        g.setColor(Color.BLACK);

        g.fillRect(col*BLOCK_WIDTH, row*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);

        g.setColor(c);      

    }

}

 

public class Node {

 

    private static final int BLOCK_WIDTH = SnakeFrame.BLOCK_WIDTH;

    private static final int BLOCK_HEIGHT = SnakeFrame.BLOCK_HEIGHT;

    private int row;

    private int col;

    private Direction dir ;

    private Node pre;

    private Node next;

 

    public Node(int row, int col, Direction dir) {

        this.row = row;

        this.col = col;

        this.dir = dir;

    }

 

    public void draw(Graphics g){

        Color c = g.getColor();

        g.setColor(Color.BLACK);

        g.fillRect(col*BLOCK_WIDTH, row*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);

        g.setColor(c);      

    }

}

 

public enum Direction {

    L,U,R,D

}

 

再就是怎么让蛇动起来并恰东西:

首先想到的是这样:其移动是通过在头部添加一个单元格,在尾部删除一个单元格,那么:

就在Snake类中添加一个keyPressed方法

当然,这主要是根据键盘的上下左右键来确定蛇头结点的方向,然后用move方法再根据头结点的方向来在头部加一个格子。

 

public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        switch(key){

        case KeyEvent.VK_LEFT :

            if(head.dir!=Direction.R){

                head.dir = Direction.L;

            }

            break;

        case KeyEvent.VK_UP :

            if(head.dir!=Direction.D){

                head.dir = Direction.U;

            }

            break;

        case KeyEvent.VK_RIGHT :

            if(head.dir!=Direction.L){

                head.dir = Direction.R;

            }

            break;

        case KeyEvent.VK_DOWN :

            if(head.dir!=Direction.U){

                head.dir = Direction.D;

            }

            break;

        }

    }

 

    public void move() {

        addNodeInHead();

        deleteNodeInTail();

    }

 

    private void deleteNodeInTail() {

        Node node = tail.pre;

        tail = null;

        node.next = null;

        tail = node;

    }

 

    private void addNodeInHead() {

        Node node = null;

        switch(head.dir){

        case L:

            node = new Node(head.row,head.col-1,head.dir);

            break;

        case U:

            node = new Node(head.row-1,head.col,head.dir);

            break;

        case R:

            node = new Node(head.row,head.col+1,head.dir);

            break;

        case D:

            node = new Node(head.row+1,head.col,head.dir);

            break;

        }

 

        node.next = head;

        head.pre = node;

        head = node;

 

    }

    public void draw(Graphics g){

        if(head==null){

            return ;

        }

        move();

        for(Node node = head;node!=null;node = node.next){

            node.draw(g);

        }   

}

 

关于蛇吃的蛋:

 

getRect方法:用于碰撞检测

 

reAppear方法:用于重新产生蛋的方法

 

public class Egg {

        private int row;

        private int col;

        private static final int BLOCK_WIDTH = SnakeFrame.BLOCK_WIDTH;

        private static final int BLOCK_HEIGHT = SnakeFrame.BLOCK_HEIGHT;

 

        private static final Random r = new Random();

 

        private Color color = Color.RED;

 

        public Egg(int row, int col) {

            this.row = row;

            this.col = col;

        }

 

        public Egg() {

            this((r.nextInt(SnakeFrame.ROW-2))+2,(r.nextInt(SnakeFrame.COL-2))+2);

        }

        public void reAppear(){

            this.row = (r.nextInt(SnakeFrame.ROW-2))+2;

            this.col = (r.nextInt(SnakeFrame.COL-2))+2;

        }

 

        public void draw(Graphics g){

            Color c= g.getColor();

            g.setColor(color);

            g.fillOval(col*BLOCK_WIDTH, row*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);

            g.setColor(c);

            if(color==Color.RED){

                color = Color.BLUE;

            }

            else{

                color = Color.RED;

            }

 

        }

        public Rectangle getRect(){

            return new Rectangle(col*BLOCK_WIDTH, row*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);

        }

 

    }

 

 

判断蛇是否吃到了蛋:

吃到了,则加长

 

 public Rectangle getRect(){

        return new Rectangle(head.col*BLOCK_WIDTH, head.row*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);

    }

 

    public boolean eatEgg(Egg egg){

 

        if(this.getRect().intersects(egg.getRect())){

            addNodeInHead();

            egg.reAppear();

            return true;

        }

        else{

            return false;

        }

    }

 

 

接下来是增量开发时间:

 

贪吃蛇还能加什么呢,坦白来说没什么好加的了

 

于是我们就给他加了个边框。。。

 

加了个双缓冲。。。。

 

又加了个控制画面。。。。

 

Finally!下面是贴代码time

 

private class MyPaintThread implements Runnable{

    @Override

    public void run() {

        while(true){

            repaint();            

try {

               Thread.sleep(50);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

 

private Image offScreenImage = null;

    @Override

    public void update(Graphics g) {

        if(offScreenImage==null){

            offScreenImage = this.createImage(ROW*BLOCK_HEIGHT, COL*BLOCK_WIDTH);

        }

        Graphics offg = offScreenImage.getGraphics();

        paint(offg);

        g.drawImage(offScreenImage, 0, 0, null);

}

 

private void checkDead() {

        if(head.row<2||head.row>SnakeFrame.ROW||head.col<0||head.col>SnakeFrame.COL){

            this.sf.gameOver();

        }

 

        for(Node node =head.next;node!=null;node = node.next){

            if(head.row==node.row&&head.col == node.col){

                this.sf.gameOver();

            }

        }

    }

 

 

private boolean b_gameOver = false;

 

    public void gameOver(){

        b_gameOver = true;

    }

 

    @Override

    public void update(Graphics g) {

        if(b_gameOver){

            g.drawString("游戏结束!!!", ROW/2*BLOCK_HEIGHT, COL/2*BLOCK_WIDTH);

        }

 

    }

 

这篇博文的重难点在:

 

  1. 看懂自己之前写的是个什么玩意儿

 

  1. 修改一切不规范的变量名力求向正儿八经的程序靠拢

 

  1. 贪吃蛇的增量开发实在有限,想了一阵也只能从边角料入手

 

  1. Bug来说其实是没有的,这个真没有(修改变量名之后搞得跑不起来的那种不算,已经莫得了)

 

那么

 

GAME OVER~~~~撒花撒花撒花~~~~~~游戏结束~~~~~~~~

 

就这么长了毕竟介于“不那么简单也不难”的代码貌似也就这个了呢。。。

 

简要对代码做了写解释(因为莫得备注)

 

那为什么没备注呢(因为当时根本没想到要写备注)

 

至少了解到了备注的重要性,嗯

 

以上。

是我第22喜欢的贪吃蛇Time

原文:https://www.cnblogs.com/danhuabaoyikouyinzi/p/10476353.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!