貪吃蛇

貪吃蛇

Cell 是數據格子,是數據結構
Worm 是核心數據和算法的封裝,包括爬行,碰撞,吃食物等
TestCase 是核心業務數據的測試案例,必須嚴格實現通過
Wormstage  1 是蛇的繪製面板,還充當了軟件流程控制器的
    作用:控制定時任務處理,和鍵盤輸入流程控制creepTo()!
Jframe 只是窗口容器。將Wormstage 顯示出來。

源代碼下載: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;
    }

}

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);
    }
}

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、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

    }
}

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);
    }
}

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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章