当前位置:   article > 正文

贪吃蛇_贪吃蛇 feng的博客

贪吃蛇 feng的博客

贪吃蛇

Cell 是数据格子,是数据结构
Worm 是核心数据和算法的封装,包括爬行,碰撞,吃食物等
TestCase 是核心业务数据的测试案例,必须严格实现通过
Wormstage  1 是蛇的绘制面板,还充当了软件流程控制器的
    作用:控制定时任务处理,和键盘输入流程控制creepTo()!
Jframe 只是窗口容器。将Wormstage 显示出来。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

源代码下载:http://download.csdn.net/download/u012234452/9327291

结构图

这里写图片描述

1、Cell.java

package com.feike.worm;
/** 一个单元格子 */
public class Cell {
    private int x;
    private int y;
    public Cell() {
    }
    public Cell(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
    public String toString() {
        return "["+x+","+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;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

2、Worm.java

package com.feike.worm;

import java.util.Arrays;

/** 贪吃蛇 */
public class Worm {
    public static final int DEFAULL_LENGTH = 12;
    private Cell[] cells;

    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 currentDirection;
    public Worm() {
        cells = new Cell[DEFAULL_LENGTH];
        for(int i=0;i<cells.length;i++){
            cells[i] = new Cell(i,0);//[0,0][1,0][2,0][3,0]...
        }
        /**给蛇一个默认的爬行方向 */
        currentDirection = DOWN;
    }
    public boolean contains(int x,int y){
        for(int i= 0;i<cells.length;i++){
            Cell node = cells[i];
            if(node.getX()==x && node.getY()==y){
                return true;
            }
        }
        return false;
    }
    /** 
     * 1)计算currentDirection与direction的和,
     *   如果是0表示方向了,就结束方法返回,不进行任何动作
     * 2)currentDirection = Direction 改变当前方向,
     *   作为下次运行的方向
     * 3)判断当前头节点的坐标和食物对象的坐标一致
     *   如果一致说明吃到食物了
     * 4)如果吃到食物,就将cells数组进行扩容
     *   将cells数组内容的每个元素向后移动。
     * 5)将新头节点插入的头位置cells[0] = newHead
     * 6)返回是否吃到食物
     */
    public boolean creep(int direction,Cell food){
        if(currentDirection + direction ==0){
            return false;//反向了,不进行任何动作
        }
        currentDirection = direction;
        Cell head = createHead(direction);
        /*
        boolean eat = false;
        if(head.getX()==food.getX() && 
                head.getY()==food.getY()){
            eat = true;
        }*/
        boolean eat = head.getX()==food.getX() && 
                      head.getY()==food.getY();
        if(eat){
            //如果吃了 就扩容
            cells = Arrays.copyOf(cells, cells.length+1);
        }
        for(int i=cells.length-1;i>=1;i--){
            cells[i] = cells[i-1];
        }
        cells[0] = head;
        return eat;
    }
    /** 重载一下方便使用 看当前方向*/
    public boolean creep(Cell food){
        return creep(currentDirection,food);
    }
    /** 爬 */
    public void creep(){
        for(int i=cells.length-1;i>=1;i--){
            cells[i] = cells[i-1];
        }
        cells[0] = createHead(currentDirection);
    }
    /** 看当前方向是否会碰撞*/
    public boolean hit(){
        return hit(currentDirection);
    }
    /** 检查是否撞墙或撞到自己*/
    public boolean hit(int direction){
        System.out.println("方向(2): "+direction);//检查方向
        Cell head = createHead(direction);
        System.out.println(head);//检查头坐标位置
        if(currentDirection + direction ==0){
            return false;//反向了,不进行任何动作
        }
        if(head.getX()<0 || head.getX()>=WormStage.COLS ||
                head.getY()<0 || head.getY()>WormStage.ROWS){
            //if(true)这撞在墙上了,返回true
            return true;
        }
        for(int i=0;i<cells.length-1;i++){
            Cell node = cells[i];
            if(node.getX()==head.getX() && 
               node.getY()==head.getY()){
                return true;
            }
        }
        return false;
    }
    /** 头节点的移动*/
    private Cell createHead(int direction){
        int x = cells[0].getX();
        int y = cells[0].getY();
        switch (direction) {
        case DOWN: y++; break;
        case UP: y--; break;
        case LEFT: x--; break;
        case RIGHT: x++; break;
        }
        return new Cell(x,y);
    }
    /** Worm.java */
    public Cell[] getCells(){
       // return cells;
        //下面这专业点
        return Arrays.copyOf(cells, cells.length);
    }
    public String toString() {
        return Arrays.toString(cells);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127

3、WormStage.java

package com.feike.worm;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.security.PublicKey;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;


public class WormStage extends JPanel{
    /** 行数*/
    public static final int ROWS = 35;
    /** 列数*/
    public static final int COLS = 35;
    /** 格子大小 10个像素大小*/
    public static final int CELL_SIZE = 10;
    private Worm worm;
    private Cell food;
    public WormStage() {
        worm = new Worm();
        food = createFood();
    }
    /** 生成一个食物
     * 1 生成随机数x,y
     * 2 检查蛇是否包含x,y
     *      2.1 如果包含  返回 1
     * 3 创建食物节点。
     *  */
    private Cell createFood(){
        int x;
        int y;
        Random r = new Random();
        do{
        x = r.nextInt(COLS);
        y = r.nextInt(ROWS);
        }while(worm.contains(x,y));
        return new Cell(x,y);
    }
    public String toString(){
        return "worm:"+worm+"\nfood:"+food;
    }
    /** 重写绘图方法*/
    public void paint(Graphics g){
        //填充背景色
        g.setColor(Color.DARK_GRAY);
        g.fillRect(0, 0, getWidth(), getHeight());
        //绘制食物
        g.setColor(Color.RED);
        g.fill3DRect(CELL_SIZE*food.getX(), 
                CELL_SIZE*food.getY(), CELL_SIZE, CELL_SIZE, true);
        //绘制蛇
        g.setColor(Color.GREEN);
        Cell[] cells = worm.getCells();
        for(int i=0;i<cells.length;i++){
            Cell node = cells[i];
            g.fill3DRect(CELL_SIZE*node.getX(),
                    CELL_SIZE*node.getY(), CELL_SIZE, CELL_SIZE, true);
        }
    }

    public static void main(String[] args) {
        //启动软件  WormStage.java
        JFrame frame = new JFrame("贪吃蛇");
        WormStage pane = new WormStage();
        frame.setLayout(null);// 取消窗口的默认布局,取消自动充满
        frame.add(pane);// 窗口添加面板
        pane.setSize(CELL_SIZE*COLS, CELL_SIZE*ROWS);//面板大小
        pane.setLocation(50, 50);//面板位置
        frame.setSize(450, 480);//设置窗口的大小
        pane.setBorder(new LineBorder(Color.black));//添加边框
        frame.setLocationRelativeTo(null);//frame居中
        frame.setVisible(true);//显示窗口
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pane.action();//启动蛇的运行
    }
    /**行为 */
    private void action(){
       /* worm.creep(food);
      swing JPanel 中声明的方法,会尽快的启动重绘功能,
        尽快调用paint(g)方法绘制界面
        repaint();*/
        Timer timer = new Timer();
        timer.schedule(new TimerTask(){
           public void run(){
               //爬行控制逻辑
               if(worm.hit()){
                   worm = new Worm();
                   food = createFood();
               }else{
                   boolean eat = worm.creep(food);
                   if(eat){
                       food = createFood();
                   }
               }
               worm.creep(food);
               repaint();
           }
        }, 0,1000/7);
        //this 就是当前舞台面板
        this.requestFocus();//获得焦点
        this.addKeyListener(new KeyAdapter(){
            public void keyPressed(KeyEvent e){
                //key 代表哪个按键被按下!
                int key = e.getKeyCode();
                switch (key) {
                case KeyEvent.VK_UP: //上箭头按下
                    creepTo(Worm.UP);
                    break;
                case KeyEvent.VK_DOWN: //下箭头按下
                    creepTo(Worm.DOWN);
                    break;
                case KeyEvent.VK_LEFT: //左箭头按下
                    creepTo(Worm.LEFT);
                    break;
                case KeyEvent.VK_RIGHT: //右箭头按下
                    creepTo(Worm.RIGHT);
                    break;
                }
            }
        });//addKeyListener
    }//action()
    /** 爬行控制方法,在按键按下时调用*/
    private void creepTo(int direction){
        if(worm.hit(direction)){
            worm = new Worm();
            food = createFood();
        }else {
            boolean eat = worm.creep(direction,food);
            if(eat){
                food = createFood();
            }
        }
        repaint();
    }
}//wormStage
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

下面代码是用作测试用的

1、TestCase.java

package com.feike.test;
import org.junit.Test;

import com.feike.worm.*;

/**
 * test 测试
 * test 案例
 *
 */
public class TestCase {
    @Test //来自JUnit的注释标记,用于执行测试方法
    public void testWormInit(){
        System.out.println("测试Worm构造器");
        Worm worm = new Worm();
        System.out.println(worm);
    }
    @Test
    public void testWormContains(){
        System.out.println("测试Worm包含算法");
        Worm worm = new Worm();
        System.out.println(worm.contains(2, 0));//true
        System.out.println(worm.contains(5, 6));//false
    }
    @Test
    public void testWormStage(){
        System.out.println("创建舞台实例");
        WormStage stage = new WormStage();
        System.out.println(stage);
    }
    @Test
    public void testCreep(){
        System.out.println("爬行测试");
        Worm worm = new  Worm();
        System.out.println(worm);
        worm.creep();
        System.out.println(worm);
    }
    @Test
    public void testCreepForFood(){
        System.out.println("检查食物的爬行");
        Worm worm = new Worm();
        Cell food = new Cell(1,2);
        System.out.println(worm.creep(Worm.DOWN, food));
        System.out.println(worm);
        System.out.println(worm.creep(Worm.DOWN, food));
        System.out.println(worm);
        System.out.println(worm.creep(Worm.RIGHT, food));
        System.out.println(worm);
    }
    @Test
    public void testHit(){
        System.out.println("碰撞测试");
        Worm worm = new Worm();
        Cell food = new Cell(10,10);
        System.out.println(worm);
        System.out.println(worm.creep(Worm.DOWN, food));
        System.out.println(worm);
        System.out.println(worm.creep(Worm.DOWN, food));
        System.out.println(worm);
        System.out.println(worm.hit(Worm.LEFT));//true
        System.out.println(worm.hit(Worm.RIGHT));//false
        System.out.println(worm.creep(Worm.RIGHT, food));
        System.out.println(worm);
        System.out.println(worm.creep(Worm.RIGHT, food));
        System.out.println(worm);
        System.out.println(worm.creep(Worm.UP, food));
        System.out.println(worm);
        System.out.println(worm.hit(Worm.UP));//true

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

2、Test.java

package com.feike.test;

import com.feike.worm.Worm;
/**
 * 测试默认创建的贪吃蛇对象 
 *
 */
public class Test {
    public static void main(String[] args) {
        Worm worm = new Worm();
        System.out.println(worm);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3、JFrameDemo.java

package com.feike.test;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;// Frame 相框,框架
import javax.swing.JPanel;// panel 面板
import javax.swing.border.LineBorder;

/** 显示窗口 与 绘图 */
public class JFrameDemo {
    public static void main(String[] args) {

        JFrame frame = new JFrame("窗口");
        Stage pane = new Stage();
        frame.setLayout(null);// 取消窗口的默认布局,取消自动充满
        frame.add(pane);// 窗口添加面板
        pane.setSize(10 * 35, 10 * 35);//面板大小
        pane.setLocation(50, 50);//面板位置
        frame.setSize(450, 480);//设置窗口的大小
        pane.setBorder(new LineBorder(Color.black));//添加边框
        frame.setLocationRelativeTo(null);//frame居中
        frame.setVisible(true);//显示窗口
        //在Swing中如下代码可以实现对键盘事件的监听,
        //也就是获得到底那个键盘按键被按下了
        pane.requestFocus();//使pane获取输入“焦点”,
        //也就是使pane变成键盘输入的目标
        //pane.addKeyListener(new KeyListener(){
        //继承KeyAdapter比实现KeyListener 更加简洁。
        //在pane上添加键盘事件的监听,获得到底哪个按键被按下
        pane.addKeyListener(new KeyAdapter(){
            //在按键按下的时候执行的方法
            public void keyPressed(KeyEvent e) {
                System.out.println("hi"+e.getKeyCode());
            }
            /*//在按键释放的时候执行
            public void keyReleased(KeyEvent e) {
            }
            public void keyTyped(KeyEvent e) {
            }*/
        });
    }
}
class Stage extends JPanel{
    /** 重写了 默认的绘图方法*/
    public void paint(Graphics g){//paint
        g.setColor(Color.darkGray);//深灰色
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.RED);
        g.fill3DRect(50, 50, 30, 20, true);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/396526
推荐阅读
相关标签
  

闽ICP备14008679号