安卓貪吃蛇實現(xiàn)


1. 概述

1.1 項目背景

近年來隨著手機技術的不斷發(fā)展古老的貪吃蛇游戲不能給與廣大青少年的良好游戲體驗盗扒,所以本文再基于古老的貪吃蛇游戲上對游戲進行了改進使得玩法更加多樣有趣。

1.2 研究的主要內(nèi)容

研究的主要內(nèi)容包括對蛇如何進行控制,實現(xiàn)食物的隨機生成,并且對蛇可以進行加速控制橙弱。游戲得分等

2. 相關技術

采用的技術有 多線程 自定義View 以及一個activity

3. 系統(tǒng)分析

此為一個新版的貪吃蛇游戲,設計的游戲需要蛇的移動锅锨、加速敛苇、增長妆绞、死亡功能。程文件主要包括src文件夾(Java源碼)枫攀、res文件夾(資源文件)和AndroidMainfest.xml(程序清單)括饶。軟件主要由Activities,自定義view 組成 View主要用來繪制圖形并進行邏輯的處理来涨。Activity主要實現(xiàn)對蛇的控制和對用戶的交互信息等

4. 系統(tǒng)設計

圖1游戲組成

5. 系統(tǒng)實現(xiàn)

1图焰、游戲界面


圖2開始界面

圖3

圖4暫停界面

圖5結束界面

圖6穿墻界面

實現(xiàn)該模塊的核心代碼如下:

TileView.java

package cn.edu.zust.lihuan;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
public class TileView extends View {
    protected static int mTileSize;
    protected static int mXTileCount;
    protected static int mYTileCount;
    private static int mXOffset;
    private static int mYOffset;
    private Bitmap[] mTileArray;
    private int[][] mTileGrid;
    private final Paint mPaint = new Paint();
    public TileView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);

        mTileSize = a.getInt(R.styleable.TileView_tileSize, 32);

        a.recycle();
    }
    public TileView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public void resetTiles(int tilecount) {
        mTileArray = new Bitmap[tilecount];
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mXTileCount = (int) Math.floor(w / mTileSize);
        mYTileCount = (int) Math.floor(h / mTileSize);

        mXOffset = ((w - (mTileSize * mXTileCount)) / 2);
        mYOffset = ((h - (mTileSize * mYTileCount)) / 2);

        mTileGrid = new int[mXTileCount][mYTileCount];
        clearTiles();
    }
    public void loadTile(int key, Drawable tile) {
        Bitmap bitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tile.setBounds(0, 0, mTileSize, mTileSize);
        tile.draw(canvas);

        mTileArray[key] = bitmap;
    }
    public void clearTiles() {
        for (int x = 0; x < mXTileCount; x++) {
            for (int y = 0; y < mYTileCount; y++) {
                setTile(0, x, y);
            }
        }
    }
    public void setTile(int tileindex, int x, int y) {
        mTileGrid[x][y] = tileindex;
    }
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int x = 0; x < mXTileCount; x += 1) {
            for (int y = 0; y < mYTileCount; y += 1) {
                if (mTileGrid[x][y] > 0) {
                    canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
                            mXOffset + x * mTileSize,
                            mYOffset + y * mTileSize,
                            mPaint);
                }
            }
        }

    }

}

Snake.java

package cn.edu.zust.lihuan;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
public class   Snake extends Activity {
    private SnakeView mSnakeView;
    private Button mBt_up, mBt_down, mBt_left, mBt_right, mBt_home;
    private Vibrator vibrator;
    private Resources r;
    private static String ICICLE_KEY = "snake-view";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(cn.edu.zust.lihuan.R.layout.snake_layout);
        mSnakeView = (SnakeView) findViewById(cn.edu.zust.lihuan.R.id.snake);
        mSnakeView.setTextView((TextView) findViewById(cn.edu.zust.lihuan.R.id.text));
        vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        r = getResources();
        if (savedInstanceState == null) {
            mSnakeView.setMode(SnakeView.READY);
        } else {
            Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
            if (map != null) {
                mSnakeView.restoreState(map);
            } else {
                mSnakeView.setMode(SnakeView.PAUSE);
                mSnakeView.setMODE(SnakeView.PAUSE);
            }
        }
        mBt_up = findViewById(cn.edu.zust.lihuan.R.id.up);
        mBt_down = findViewById(cn.edu.zust.lihuan.R.id.dowm);
        mBt_left = findViewById(cn.edu.zust.lihuan.R.id.left);
        mBt_right = findViewById(cn.edu.zust.lihuan.R.id.right);
        mBt_home = findViewById(cn.edu.zust.lihuan.R.id.home);
        mBt_up.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case ACTION_DOWN:
                        mSnakeView.up();
                        vibrator.vibrate(30);
                        mSnakeView.addBuff();
                        break;
                    case ACTION_UP:
                        mSnakeView.deBuff();
                        break;
                }
                return false;
            }
        });
        mBt_down.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case ACTION_DOWN:
                        mSnakeView.down();
                        vibrator.vibrate(30);
                        mSnakeView.addBuff();
                        break;
                    case ACTION_UP:
                        mSnakeView.deBuff();
                        break;
                }
                return false;
            }
        });
        mBt_left.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case ACTION_DOWN:
                        mSnakeView.left();
                        vibrator.vibrate(30);
                        mSnakeView.addBuff();
                        break;
                    case ACTION_UP:
                        mSnakeView.deBuff();
                        break;
                }
                return false;
            }
        });
        mBt_right.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case ACTION_DOWN:
                        mSnakeView.right();
                        vibrator.vibrate(30);
                        mSnakeView.addBuff();
                        break;
                    case ACTION_UP:
                        mSnakeView.deBuff();
                        break;
                }
                return false;
            }
        });
        mBt_home.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                changeHome();
                mSnakeView.star();
                vibrator.vibrate(300);
            }
        });
    }
    @Override
    protected void onPause() {
        super.onPause();
        // Pause the game along with the activity
        mSnakeView.setMode(SnakeView.PAUSE);
        changeHome();
        mSnakeView.setMODE(SnakeView.PAUSE);
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        //Store the game state
        outState.putBundle(ICICLE_KEY, mSnakeView.saveState());
    }
    public void changeHome() {
        if (r != null) {
            if (mSnakeView.getMODE() == mSnakeView.PAUSE ||
                    mSnakeView.getMODE() == mSnakeView.READY || mSnakeView.getMODE() == mSnakeView.LOSE) {
                mBt_home.setBackground(r.getDrawable(R.drawable.btn_bg_home_selector));
            } else if (mSnakeView.getMODE() == mSnakeView.RUNNING) {
                mBt_home.setBackground(r.getDrawable(R.drawable.btn_bg_home2_selector));
            }
        } else {
        }
    }
}

SnakeView.java

 
package cn.edu.zust.lihuan;

import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Random;

public class SnakeView extends TileView {
    private static final String TAG = "SnakeView";
    private int mMode = READY;
    public static final int PAUSE = 0;
    public static final int READY = 1;
    public static final int RUNNING = 2;
    public static final int LOSE = 3;
    private int mDirection = NORTH;
    private int mNextDirection = NORTH;
    private static final int NORTH = 1;
    private static final int SOUTH = 2;
    private static final int EAST = 3;
    private static final int WEST = 4;
    private static final int APPLE = 1;
    private static final int HEAD = 2;
    private static final int DEADHEAD = 3;
    private static final int BODY = 4;
    private static final int APPLE2 = 5;
    private static int MODE = READY;

    public static void setMODE(int MODE) {
        SnakeView.MODE = MODE;
    }

    public int getMODE() {
        return MODE;
    }

    private long mScore = 0;
    private long mMoveDelay = 100;
    private boolean mBuff = false;
    private int gorwTag = 1;

    /**
     * Give our snake some buff!
     */
    public void addBuff() {
        if (!mBuff) {
            mBuff = true;
            mMoveDelay /= 5;
            loadTile(APPLE2, r.getDrawable(R.drawable.redstar));

        }
    }

    public void deBuff() {
        if (mBuff) {
            mBuff = false;
            mMoveDelay *= 5;
        }
        loadTile(APPLE2, r.getDrawable(R.drawable.greenstar));
    }

    private long mLastMove;
    private TextView mStatusText;
    private ArrayList<Coordinate> mSnakeTrail = new ArrayList<Coordinate>();
    private ArrayList<Coordinate> mAppleList = new ArrayList<Coordinate>();
    private ArrayList<Coordinate> mAppleList2 = new ArrayList<Coordinate>();
    /**
     * Everyone needs a little randomness in their life
     */
    private static final Random RNG = new Random();
    private RefreshHandler mRedrawHandler = new RefreshHandler();
    Resources r = this.getContext().getResources();

    class RefreshHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            SnakeView.this.update();
            SnakeView.this.invalidate();
        }

        public void sleep(long delayMillis) {
            this.removeMessages(0);
            //     Toast.makeText(SnakeView.this.getContext(),"這是一個TOAST",Toast.LENGTH_SHORT).show();
            sendMessageDelayed(obtainMessage(0), delayMillis);
        }
    }

    public SnakeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SnakeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initSnakeView();
    }

    private void initSnakeView() {
        setFocusable(true);
        resetTiles(6);
        loadTile(HEAD, r.getDrawable(cn.edu.zust.lihuan.R.drawable.head));
        loadTile(APPLE, r.getDrawable(cn.edu.zust.lihuan.R.drawable.apple));
        loadTile(BODY, r.getDrawable(cn.edu.zust.lihuan.R.drawable.body));
        loadTile(DEADHEAD, r.getDrawable(cn.edu.zust.lihuan.R.drawable.deadhead));
        loadTile(APPLE2, r.getDrawable(R.drawable.redstar));
    }

    private void initNewGame() {
        mSnakeTrail.clear();
        mAppleList.clear();
        mAppleList2.clear();
        gorwTag = 1;
        // that's just turned north
        for (int i = 4; i > 0; i--) {
            mSnakeTrail.add(new Coordinate(i, 7));
        }
        mNextDirection = NORTH;
        // How many apples to start with
        for (int i = 0; i < 100; i++) {
            addRandomApple();
        }
        for (int i = 0; i < 5; i++) {
            addRandomApple2();
        }
        //init time of snake
        mMoveDelay = 300;
        mScore = 0;
    }

    private int[] coordArrayListToArray(ArrayList<Coordinate> cvec) {
        int count = cvec.size();
        int[] rawArray = new int[count * 2];
        for (int index = 0; index < count; index++) {
            Coordinate c = cvec.get(index);
            rawArray[2 * index] = c.x;
            rawArray[2 * index + 1] = c.y;
        }
        return rawArray;
    }

    public Bundle saveState() {
        Bundle map = new Bundle();
        map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));
        map.putIntArray("mAppleList2", coordArrayListToArray(mAppleList2));
        map.putInt("mDirection", Integer.valueOf(mDirection));
        map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
        map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
        map.putLong("mScore", Long.valueOf(mScore));
        map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));
        return map;
    }

    private ArrayList<Coordinate> coordArrayToArrayList(int[] rawArray) {
        ArrayList<Coordinate> coordArrayList = new ArrayList<Coordinate>();
        int coordCount = rawArray.length;
        for (int index = 0; index < coordCount; index += 2) {
            Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]);
            coordArrayList.add(c);
        }
        return coordArrayList;
    }

    public void restoreState(Bundle icicle) {
        setMode(PAUSE);
        mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));
        mAppleList2 = coordArrayToArrayList(icicle.getIntArray("mAppleList2"));
        mDirection = icicle.getInt("mDirection");
        mNextDirection = icicle.getInt("mNextDirection");
        mMoveDelay = icicle.getLong("mMoveDelay");
        mScore = icicle.getLong("mScore");
        mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
    }

    public void star() {
        if (mMode == READY | mMode == LOSE) {
            initNewGame();
            setMode(RUNNING);
            this.MODE = RUNNING;
            update();
        } else if (mMode == PAUSE) {
            setMode(RUNNING);
            this.MODE = RUNNING;
            update();
        } else if (mMode == RUNNING) {
            setMode(PAUSE);
            this.MODE = PAUSE;
            update();
        }
    }

    public void up() {
        if (mDirection != SOUTH) {
            mNextDirection = NORTH;
            loadTile(HEAD, r.getDrawable(R.drawable.head));
        }
    }

    public void down() {
        if (mDirection != NORTH) {
            mNextDirection = SOUTH;
            loadTile(HEAD, r.getDrawable(R.drawable.head2));
        }
    }

    public void left() {
        if (mDirection != EAST) {
            mNextDirection = WEST;
            loadTile(HEAD, r.getDrawable(R.drawable.head3));
        }
    }

    public void right() {
        if (mDirection != WEST) {
            mNextDirection = EAST;
            loadTile(HEAD, r.getDrawable(R.drawable.head4));
        }
    }

    public void setTextView(TextView newView) {
        mStatusText = newView;
    }

    public void setMode(int newMode) {
        int oldMode = mMode;
        mMode = newMode;

        if (newMode == RUNNING & oldMode != RUNNING) {
            mStatusText.setVisibility(View.INVISIBLE);
            update();
            return;
        }
        Resources res = getContext().getResources();
        CharSequence str = "";
        if (newMode == PAUSE) {
            str = res.getText(cn.edu.zust.lihuan.R.string.mode_pause);
        }
        if (newMode == READY) {
            str = res.getText(cn.edu.zust.lihuan.R.string.mode_ready);
        }
        if (newMode == LOSE) {
            str = res.getString(cn.edu.zust.lihuan.R.string.mode_lose_prefix) + mScore
                    + res.getString(cn.edu.zust.lihuan.R.string.mode_lose_suffix);
        }

        mStatusText.setText(str);
        mStatusText.setVisibility(View.VISIBLE);
    }

    private void addRandomApple() {
        Coordinate newCoord = null;
        boolean found = false;
        while (!found) {
            // Choose a new location for our apple
            int newX = 1 + RNG.nextInt(mXTileCount - 2);
            int newY = 1 + RNG.nextInt(mYTileCount - 2);
            newCoord = new Coordinate(newX, newY);
            // Make sure it's not already under the snake
            boolean collision = false;
            int snakelength = mSnakeTrail.size();
            for (int index = 0; index < snakelength; index++) {
                if (mSnakeTrail.get(index).equals(newCoord)) {
                    collision = true;
                }
            }
            found = !collision;
        }
        if (newCoord == null) {
            Log.e(TAG, "Somehow ended up with a null newCoord!");
        }
        mAppleList.add(newCoord);
    }

    private void addRandomApple2() {
        Coordinate newCoord = null;
        boolean found = false;
        while (!found) {
            int newX = 1 + RNG.nextInt(mXTileCount - 2);
            int newY = 1 + RNG.nextInt(mYTileCount - 2);
            newCoord = new Coordinate(newX, newY);
            boolean collision = false;
            int snakelength = mSnakeTrail.size();
            for (int index = 0; index < snakelength; index++) {
                if (mSnakeTrail.get(index).equals(newCoord)) {
                    collision = true;
                }
            }
            found = !collision;
        }
        if (newCoord == null) {
            Log.e(TAG, "Somehow ended up with a null newCoord!");
        }
        mAppleList2.add(newCoord);
    }

    public void update() {
        if (mMode == RUNNING) {
            long now = System.currentTimeMillis();
            if (now - mLastMove > mMoveDelay) {
                clearTiles();
                updateWalls();
                updateSnake();
                updateApples();
                updateApples2();
                mLastMove = now;
            }
            mRedrawHandler.sleep(mMoveDelay);
        }
    }

    private void updateWalls() {
        for (int x = 0; x < mXTileCount; x++) {
            setTile(DEADHEAD, x, 0);
            setTile(DEADHEAD, x, mYTileCount - 1);
        }
        for (int y = 1; y < mYTileCount - 1; y++) {
            setTile(DEADHEAD, 0, y);
            setTile(DEADHEAD, mXTileCount - 1, y);
        }
    }

    private void updateApples() {
        for (Coordinate c : mAppleList) {
            setTile(APPLE, c.x, c.y);
        }
    }

    private void updateApples2() {
        for (Coordinate c : mAppleList2) {
            setTile(APPLE2, c.x, c.y);
        }
    }

    private void updateSnake() {
        boolean growSnake = false;
        // grab the snake by the head
        Coordinate head = mSnakeTrail.get(0);
        Coordinate newHead = new Coordinate(1, 1);
        mDirection = mNextDirection;
        switch (mDirection) {
            case EAST: {
                newHead = new Coordinate(head.x + 1, head.y);
                break;
            }
            case WEST: {
                newHead = new Coordinate(head.x - 1, head.y);
                break;
            }
            case NORTH: {
                newHead = new Coordinate(head.x, head.y - 1);
                break;
            }
            case SOUTH: {
                newHead = new Coordinate(head.x, head.y + 1);
                break;
            }
        }
        if ((newHead.x < 1) || (newHead.x > mXTileCount - 2)
                ) {
            setMode(LOSE);
            return;

        } else if (newHead.y == 0) {//穿上面的墻

            newHead.y = mYTileCount - 2;
        } else if (newHead.y == mYTileCount - 1) {//穿下面的墻

            newHead.y = 1;
        }
        int snakelength = mSnakeTrail.size();
        for (int snakeindex = 0; snakeindex < snakelength; snakeindex++) {
            Coordinate c = mSnakeTrail.get(snakeindex);
            if (c.equals(newHead)) {
                setMode(LOSE);
                return;
            }
        }
        int applecount = mAppleList.size();
        int applecount2 = mAppleList2.size();
        for (int appleindex = 0; appleindex < applecount; appleindex++) {
            Coordinate c = mAppleList.get(appleindex);
            if (c.equals(newHead)) {
                mAppleList.remove(c);
                addRandomApple();
                mScore++;
                mMoveDelay *= 0.998;
                growSnake = true;
            }
        }
        for (int appleindex = 0; appleindex < applecount2; appleindex++) {
            Coordinate c = mAppleList2.get(appleindex);
            if (c.equals(newHead)) {
                gorwTag = 2;
                mAppleList2.remove(c);
                addRandomApple2();
                mScore += 5;
                //chenge time of snake
                mMoveDelay *= 0.998;
                growSnake = true;
            }
        }
        switch (gorwTag) {
            case 1:
                mSnakeTrail.add(0, newHead);
                break;

            case 2:
                for (int i = 0; i < 4; i++) {
                    mSnakeTrail.add(0, newHead);
                }
                gorwTag = 1;
                for (int i = 0; i < 4; i++) {
                    updateSnake();
                }
                break;
            default:
                break;
        }
        if (!growSnake) {
            mSnakeTrail.remove(mSnakeTrail.size() - 1);
        }
        // draw snake
        int index = 0;
        for (Coordinate c : mSnakeTrail) {
            if (index == 0) {
                setTile(HEAD, c.x, c.y);
            } else {
                setTile(BODY, c.x, c.y);
            }
            index++;
        }

    }

    private class Coordinate {
        public int x;
        public int y;

        public Coordinate(int newX, int newY) {
            x = newX;
            y = newY;
        }

        public boolean equals(Coordinate other) {
            if (x == other.x && y == other.y) {
                return true;
            }
            return false;
        }

        @Override
        public String toString() {
            return "Coordinate: [" + x + "," + y + "]";
        }
    }

}

snake_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:lh="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1.5">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></RelativeLayout>

        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_centerInParent="true"
            android:gravity="center_horizontal"
            android:text="@string/snake_layout_text_text"
            android:textColor="#ff8888ff"
            android:textSize="36sp"
            android:visibility="visible" />

        <cn.edu.zust.lihuan.SnakeView
            android:id="@+id/snake"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            lh:tileSize="30" />


    </FrameLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <Button
            android:id="@+id/up"
            android:layout_width="90dp"
            android:layout_height="1dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_marginTop="5dp"
            android:background="@drawable/btn_bg_up_selector" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">

            <Button
                android:id="@+id/left"
                android:layout_width="0dp"
                android:layout_height="90dp"
                android:layout_marginLeft="25dp"
                android:layout_weight="1"
                android:background="@drawable/btn_bg_left_selector"


                />

            <Button
                android:id="@+id/home"
                android:layout_width="0dp"
                android:layout_height="90dp"
                android:layout_weight="1"
                android:background="@drawable/btn_bg_home2_selector" />

            <Button
                android:id="@+id/right"
                android:layout_width="0dp"
                android:layout_height="90dp"
                android:layout_marginRight="25dp"
                android:layout_weight="1"
                android:background="@drawable/btn_bg_right_selector" />

        </LinearLayout>

        <Button
            android:id="@+id/dowm"
            android:layout_width="90dp"
            android:layout_height="0dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_marginBottom="1dp"
            android:background="@drawable/btn_bg_down_selector"

            />

    </LinearLayout>

</LinearLayout>

6. 總結

在程序設計的時候喜歡將界面與處理分開,這樣降低耦合性蹦掐,易于維護擴展技羔。UI和游戲邏輯進行了分離僵闯, 它的實現(xiàn)方式就是,用父類TileView來實現(xiàn)比較基礎的界面UI部分藤滥,而TileView類的子類SnakeView類完成了游戲控制邏輯部分鳖粟,這樣 就成功的將兩者進行了分離,對后面的擴展和維護奠定了良好的基礎拙绊。

github源碼地址

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末向图,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子标沪,更是在濱河造成了極大的恐慌张漂,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谨娜,死亡現(xiàn)場離奇詭異,居然都是意外死亡磺陡,警方通過查閱死者的電腦和手機趴梢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來币他,“玉大人坞靶,你說我怎么就攤上這事『ぃ” “怎么了彰阴?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拍冠。 經(jīng)常有香客問我尿这,道長,這世上最難降的妖魔是什么庆杜? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任射众,我火速辦了婚禮,結果婚禮上晃财,老公的妹妹穿的比我還像新娘叨橱。我一直安慰自己,他們只是感情好断盛,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布罗洗。 她就那樣靜靜地躺著,像睡著了一般钢猛。 火紅的嫁衣襯著肌膚如雪伙菜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天厢洞,我揣著相機與錄音仇让,去河邊找鬼典奉。 笑死,一個胖子當著我的面吹牛丧叽,可吹牛的內(nèi)容都是我干的卫玖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼踊淳,長吁一口氣:“原來是場噩夢啊……” “哼假瞬!你這毒婦竟也來了?” 一聲冷哼從身側響起迂尝,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤脱茉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后垄开,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琴许,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年溉躲,在試婚紗的時候發(fā)現(xiàn)自己被綠了榜田。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡锻梳,死狀恐怖箭券,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疑枯,我是刑警寧澤辩块,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站荆永,受9級特大地震影響废亭,放射性物質發(fā)生泄漏。R本人自食惡果不足惜具钥,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一滔以、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氓拼,春花似錦你画、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撬统,卻和暖如春适滓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恋追。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工凭迹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罚屋,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓嗅绸,卻偏偏與公主長得像脾猛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鱼鸠,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,071評論 25 707
  • C語言是面向過程的猛拴,而C++是面向對象的 C和C++的區(qū)別: C是一個結構化語言,它的重點在于算法和數(shù)據(jù)結構蚀狰。C程...
    小辰帶你看世界閱讀 1,066評論 0 3
  • 千人千面愉昆,悲歡離合,萬種是非麻蹋,紛紛擾擾跛溉。經(jīng)歷些年,唯有三道目光讓我印象深刻扮授,莫能忘懷倒谷。 過年回家,七姑八姨齊聚一堂...
    Ravenclawbear閱讀 158評論 0 1
  • 早上五點二十二 坐標英國劍橋 在劍橋還未破曉的清晨用電腦看完了根據(jù)八月長安的小說改編的電視劇《最好的我們》糙箍。滿是感...
    溫風始閱讀 318評論 0 1
  • 漫長的一個冬天 沒有關系 層層的大雪覆蓋 沒有關系 當種子邂逅了春天 就一定要給世界一個驚喜
    簡村小吹閱讀 266評論 14 18