01 贪吃蛇

1. 前言 :

这个游戏的经典程度就不用说了吧,相信大家都玩过,而且在学习之初说不定也都还写过呢,
这个实际上写了已经很久了,所以可能注释, 代码风格等信息可能不是那么的好看

设计的思路 : 根据蛇头定时更新蛇的结点, 重绘, 请注意每一个蛇结点方向的控制, 开始界面的闪烁绘制, 涉及线程

元素介绍 :
: 即我们控制的角色
: 障碍物, 蛇装在上面会挂掉
食物 : 蛇的食物, 我们的目标

这里写图片描述

2. 基本的数据结构介绍 :

2.1 Food : 也就是一个基本的位置的封装

package snake;

// 食物
public class Food {
    // 坐标
    private int x;
    private int y;

    // 初始化
    public Food(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Food() {
        super();
    }

    // setter & getter
    // ... 省略
}

2.2 Node : 蛇由结点构成, 封装”蛇结点”

package snake;

// the Node in snake
public class Node {
    // 坐标以及方向
    private int x;
    private int y;
    private int direction;

    // 初始化
    public Node() {
        super();
    }
    public Node(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Node(int x, int y, int direction) {
        this.x = x;
        this.y = y;
        this.direction = direction;
    }

    // setter & getter
    // ... 省略

    // for debug ...
    public String toString(){
        return x+"--"+y+" ";
    }

}

2.3 Snake 封装了蛇的数据结构, 以及动作

package snake;

// the Snake class
public class Snake {
    private LinkedList<Node> nodes;     // all nodes in the snake
    private Node lastNode;      // the lastNode snake moved
    private int direction;      // the direction of snake
    private int lastDirection;  
    private int length;         // the length of snake
    private int initLength = 4; // the default value of snake body length

    private int xMinLimit;      // the min of X position
    private int xMaxLimit;
    private int yMinLimit;
    private int yMaxLimit;

    private boolean isEnd;      // is game end

    public Snake(int x, int y, int panelWidth, int panelHeight){
        nodes = new LinkedList<Node>();

        init(panelWidth, panelHeight);

        xMinLimit = x+MainPanel.WIDTH;
        xMaxLimit = panelWidth-panelWidth%MainPanel.WIDTH-MainPanel.WIDTH;
        yMinLimit = y+MainPanel.HEIGHT;
        yMaxLimit = panelHeight-panelWidth%MainPanel.HEIGHT-MainPanel.HEIGHT;
    }

    // initialization some variable
    public void init(int panelWidth, int panelHeight) {
        int halfWidth = panelWidth/2;
        int halfHeight = panelHeight/2;
        int firstX = halfWidth - halfWidth%MainPanel.WIDTH;
        int firstY = halfHeight - halfHeight%MainPanel.HEIGHT;

        for(int i=0; i<initLength; i++){
            nodes.add(new Node(firstX+MainPanel.WIDTH*i, firstY, 3));
        }

        length = 4;
        direction = 3;
        lastDirection = 3;
        lastNode = null;        
    }

    public Snake(){
        nodes = new LinkedList<Node>();
    }

    // the function control the snake move
    public void move(){

        Node headNode = getHead();
        Node newNode = null;

        switch(direction){
        case 0:
            newNode = moveUp(headNode);
            break;
        case 1:
            newNode = moveRight(headNode);
            break;
        case 2:
            newNode = moveDown(headNode);
            break;
        case 3:
            newNode = moveLeft(headNode);
            break;
        default:
            break;
        }

        if(newNode!=null){
            lastNode = nodes.removeLast();
            if(!containsPosition(newNode)){
            nodes.addFirst(newNode);
            }else{
                isEnd = true;
            }
            updateNodeDirection(direction);     // update the direction of snake body
        }else{
            isEnd = true;
        }
    }

    // update the direction of snake body
    private void updateNodeDirection(int direction) {
        ListIterator it = nodes.listIterator();
        Node nodeNow = null, nodePre = null;
        if(it.hasPrevious()){
            for(int i=0; i<length-1; i++){
                nodeNow = (Node)it.previous();
                if(it.hasPrevious()){
                    nodePre = (Node)it.previous();
                    nodeNow.setDirection(nodePre.getDirection());
                }
            }
        }

        getHead().setDirection(direction);
    }

    // move to specified direction
    private Node moveLeft(Node headNode) {
        if((headNode.getX()-MainPanel.WIDTH)>=xMinLimit){
        return new Node(headNode.getX()-MainPanel.WIDTH, headNode.getY());
        }
        return null;
    }

    private Node moveDown(Node headNode) {
        if((headNode.getY()+MainPanel.HEIGHT)<=yMaxLimit){
        return new Node(headNode.getX(), headNode.getY()+MainPanel.HEIGHT);
    }
        return null;
    }

    private Node moveRight(Node headNode) {
        if((headNode.getX()+MainPanel.WIDTH)<=xMaxLimit){
        return new Node(headNode.getX()+MainPanel.WIDTH, headNode.getY());
    }
        return null;
    }

    private Node moveUp(Node headNode) {
        if((headNode.getY()-MainPanel.HEIGHT)>=yMinLimit){
        return new Node(headNode.getX(), headNode.getY()-MainPanel.HEIGHT);
    }
        return null;
    }

    // add a Node for snake[while snake eat the food]
    public void addNode(int x, int y){
        addNode(new Node(x, y));
        length++;
    }
    public void addNode(Node node){
        nodes.add(node);
    }

    public List<Node> getNodes(){
        return nodes;
    }

    public Node getHead(){
        return nodes.getFirst();
    }

    public Node getTail(){
        return nodes.getLast();
    }

    public Node getBody(int index){
        return nodes.get(index);
    }

    public int getLength(){
        return this.length;
    }

    public void setDirection(int direction){
        this.direction = direction;
    }

    public int getDirection(){
        return this.direction;
    }

    public Node getLastNode(){
        return lastNode;
    }

    public void setLastDirection(int lastDirection){
        this.lastDirection = lastDirection;
    }

    public boolean containsPosition(Node node){
        return containsPosition(node.getX(), node.getY());
    }

    // judge if snake contains the specified position
    public boolean containsPosition(int x, int y){
        for(Node node : nodes){
            if(isNodeEqualWithXY(node, x, y)){
                return true;
            }
        }
        return false;
    }

    public boolean isEatFood(Food food) {
        return isNodeEqualWithXY(getHead(), food.getX(), food.getY());
    }

    // judge if the node's position equals x and y
    public boolean isNodeEqualWithXY(Node node, int x, int y){
        if(node.getX()==x && node.getY()==y){
            return true;
        }
        return false;
    }

    public void addBody(Food food) {
        nodes.addLast(lastNode);
    }

    public boolean isEnd(){
        return isEnd;
    }

    public void setIsEnd(boolean isEnd){
        this.isEnd = isEnd;
    }

    public void endGame() {
        nodes.clear();
    }

}

2.4 至于其他的界面相关的东西, 这里就不在赘述了

3下载链接 [包含图片, 源码] :

http://download.csdn.net/detail/u011039332/8978839
这里写图片描述

运行时截图 :
开始
运行时

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值