先看看效果图
贪吃蛇设计思路 贪吃蛇分为3个对象:
舞台我们可以看作为一个二维数组  蛇和食物 都是数组中的元素 
蛇是一串数组中的连续的元素  分为蛇的头元素和蛇身长度
食物可以看作是数组中的一个元素 
蛇的移动 蛇可以向上,向下,向左,向右移动
蛇移动 头元素+1 尾元素-1
碰撞检测 当蛇的头部元素碰撞到食物 则吃掉食物 蛇长度+1。 如果碰撞到蛇身 游戏结束,到舞台边界 直接穿过去
随机生成食物 使用Random 生成食物坐标 x,和y 生成后判断是不是在蛇身坐标上,如果是重新生成。
代码实现 首先我们使用自定义View 来实现
1 2 3 4 5 6 7 8 public class SnakePanelView extends View {   @Override   protected void onDraw(Canvas canvas) {     super.onDraw(canvas);     //绘制界面...   } } 
 
然后我们定义格子元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class GridSquare {   private int mType;//元素类型   public GridSquare(int type) {     mType = type;   }   public int getColor() {     switch (mType) {       case GameType.GRID://空格子         return Color.WHITE;       case GameType.FOOD://食物         return Color.BLUE;       case GameType.SNAKE://蛇         return Color.parseColor("#FF4081");     }     return Color.WHITE;   }   public void setType(int type) {     mType = type;   } } 
 
这个就是格子对象
然后我们定义出的二维数组舞台定义如下:
1 private List<List<GridSquare>> mGridSquare = new ArrayList<>(); 
 
定义出了舞台数组 我们需要定义食物的位置和蛇的位置。所以我们需要定义一个对象 这个对象需要两个成员变量 x 和 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 public class GridPosition {   private int x;   private int y;   public GridPosition(int x, int y) {     this.x = x;     this.y = 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;   } } 
 
然后我们需要定义蛇头位置、蛇身List 和食物的位置
1 2 3 private List<GridPosition> mSnakePositions = new ArrayList<>(); private GridPosition mSnakeHeader;//蛇头部位置 private GridPosition mFoodPosition;//食物的位置 
 
然后我们需要定义蛇的一系列属性:速度、蛇身长度和运动方向。
1 2 3 private int mSnakeLength = 3;//蛇身长度 private long mSpeed = 8;//运行速度 值越大 速度越快 private int mSnakeDirection = GameType.RIGHT;//运行方向  
 
让蛇运动起来我们需要一个游戏主循环 我们可以简单定义一个循环
1 2 3 4 5 6 7 8 9 private class GameMainThread extends Thread {     @Override     public void run() {       while (true) {         //todo...       }     } } 
 
我们在循环里处理蛇移动、碰撞检测和食物生产等操作。
处理蛇的移动方法:
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 private void moveSnake(int snakeDirection) {     switch (snakeDirection) {       case GameType.LEFT:         if (mSnakeHeader.getX() - 1 < 0) {//边界判断:如果到了最左边 让他穿过屏幕到最右边 mGridSize 为舞台大小           mSnakeHeader.setX(mGridSize - 1);         } else {           mSnakeHeader.setX(mSnakeHeader.getX() - 1);         }         mSnakePositions.add(new GridPosition(mSnakeHeader.getX(), mSnakeHeader.getY()));         break;       case GameType.TOP:         if (mSnakeHeader.getY() - 1 < 0) {           mSnakeHeader.setY(mGridSize - 1);         } else {           mSnakeHeader.setY(mSnakeHeader.getY() - 1);         }         mSnakePositions.add(new GridPosition(mSnakeHeader.getX(), mSnakeHeader.getY()));         break;       case GameType.RIGHT:         if (mSnakeHeader.getX() + 1 >= mGridSize) {           mSnakeHeader.setX(0);         } else {           mSnakeHeader.setX(mSnakeHeader.getX() + 1);         }         mSnakePositions.add(new GridPosition(mSnakeHeader.getX(), mSnakeHeader.getY()));         break;       case GameType.BOTTOM:         if (mSnakeHeader.getY() + 1 >= mGridSize) {           mSnakeHeader.setY(0);         } else {           mSnakeHeader.setY(mSnakeHeader.getY() + 1);         }         mSnakePositions.add(new GridPosition(mSnakeHeader.getX(), mSnakeHeader.getY()));         break;     } } 
 
处理碰撞:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 //检测碰撞 private void checkCollision() {     //检测是否咬到自己     GridPosition headerPosition = mSnakePositions.get(mSnakePositions.size() - 1);     for (int i = 0; i < mSnakePositions.size() - 2; i++) {       GridPosition position = mSnakePositions.get(i);       if (headerPosition.getX() == position.getX() && headerPosition.getY() == position.getY()) {         //咬到自己 停止游戏         mIsEndGame = true;         showMessageDialog();         return;       }     }     //判断是否吃到食物     if (headerPosition.getX() == mFoodPosition.getX()         && headerPosition.getY() == mFoodPosition.getY()) {       mSnakeLength++;       generateFood();     } } 
 
随机生成食物:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private void generateFood() {     Random random = new Random();     int foodX = random.nextInt(mGridSize - 1);     int foodY = random.nextInt(mGridSize - 1);     for (int i = 0; i < mSnakePositions.size() - 1; i++) {       if (foodX == mSnakePositions.get(i).getX() && foodY == mSnakePositions.get(i).getY()) {         //不能生成在蛇身上         foodX = random.nextInt(mGridSize - 1);         foodY = random.nextInt(mGridSize - 1);         //重新循环         i = 0;       }     }     mFoodPosition.setX(foodX);     mFoodPosition.setY(foodY);     refreshFood(mFoodPosition); } 
 
基本的游戏逻辑已经完成。
工程已经放在GITHUb