1. 程式人生 > 其它 >安卓開發 貪吃蛇

安卓開發 貪吃蛇

技術標籤:安卓

GameView

package com.example.snake6.views;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.
Nullable; import com.example.snake6.control.GamePosition; import com.example.snake6.control.GameStyle; import com.example.snake6.control.GameType; import java.util.ArrayList; import java.util.List; import java.util.Random; public class SnakeGameView extends View { private List<List<GameStyle>
> mGameStyles = new ArrayList<>(); private List<GamePosition> mSnakePosition = new ArrayList<>(); private GamePosition mSnakeHeader; private GamePosition mFoodPosition = new GamePosition(0, 0); private int mStartX, mStartY; private int mGameViewWH = getWH(getContext(),
30); private int mGameViewSize = 20; private int mCount = 0; private int mSnakeLength = 3; private int mSeep = 4; private boolean mIsEnd = false; private int mSnakeDirection = GameType.Right; private Paint mGridPaint = new Paint(); private Paint mStrokePaint = new Paint(); private OnGameListener mListener; public int getCount() { return mCount; } public void setCount(int mCount) { this.mCount = mCount; } private int getWH(Context context, int dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics()); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { mStartX = w / 2 - mGameViewSize * mGameViewWH / 2; mStartY = getWH(getContext(), 0); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = mStartX * 2 + mGameViewSize * mGameViewWH; setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), height); } private void init() { mGameStyles.clear(); mSnakePosition.clear(); mCount = 0; mSnakeLength = 3; mSeep = 4; mIsEnd = false; mSnakeDirection = GameType.Right; List<GameStyle> gameStyle; for (int i = 0; i < mGameViewSize; i++) { gameStyle = new ArrayList<>(); for (int j = 0; j < mGameViewSize; j++) { gameStyle.add(new GameStyle(GameType.Grid)); } mGameStyles.add(gameStyle); } mSnakeHeader = new GamePosition(10, 10); mSnakePosition.add(new GamePosition(mSnakeHeader.getX(), mSnakeHeader.getY())); // 生成食物 createFood(); mIsEnd = false; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.BLACK); mGridPaint.reset(); mGridPaint.setColor(Color.WHITE); mGridPaint.setAntiAlias(true); mStrokePaint.reset(); mStrokePaint.setAntiAlias(true); mStrokePaint.setColor(Color.BLACK); mStrokePaint.setStyle(Paint.Style.STROKE); for (int i = 0; i < mGameViewSize; i++) { for (int j = 0; j < mGameViewSize; j++) { int left = mStartX + i * mGameViewWH; int top = mStartY + j * mGameViewWH; int right = left + mGameViewWH; int bottom = top + mGameViewWH; if (i == mSnakeHeader.getX() && j == mSnakeHeader.getY()) { mGridPaint.setColor(new GameStyle(GameType.Head).setColor()); canvas.drawRect(left, top, right, bottom, mGridPaint); } else { mGridPaint.setColor(mGameStyles.get(i).get(j).setColor()); canvas.drawRect(left, top, right, bottom, mStrokePaint); canvas.drawRect(left, top, right, bottom, mGridPaint); } } } } public void startGame() { init(); GameThread gameThread = new GameThread(); gameThread.start(); } private class GameThread extends Thread { @Override public void run() { while (!mIsEnd) { moveSnake(mSnakeDirection); refreshBody(); checkSnakeEat(); handleTail(); postInvalidate(); step(); } } private void step() { try { sleep(1000 / mSeep); } catch (InterruptedException e) { e.printStackTrace(); } } } private void checkSnakeEat() { GamePosition headerPosition = mSnakePosition.get(mSnakePosition.size() - 1); for (int i = 0; i < mSnakePosition.size() - 2; i++) { GamePosition body = mSnakePosition.get(i); if (headerPosition.getX() == body.getX() && headerPosition.getY() == body.getY()) { mIsEnd = true; if (mListener != null) { mListener.gameOver(); } } } if (headerPosition.getX() == mFoodPosition.getX() && headerPosition.getY() == mFoodPosition.getY()) { mCount++; mSnakeLength++; if (mListener != null) { mListener.getCount(mCount); } createFood(); } } private void createFood() { Random random = new Random(); int foodX = random.nextInt(mGameViewSize - 1); int foodY = random.nextInt(mGameViewSize - 1); for (int i = 0; i < mSnakePosition.size() - 1; i++) { if (foodX == mSnakePosition.get(i).getX() && foodY == mSnakePosition.get(i).getY()) { foodX = random.nextInt(mGameViewSize - 1); foodY = random.nextInt(mGameViewSize - 1); i = 0; } } mFoodPosition.setY(foodY); mFoodPosition.setX(foodX); refreshFood(mFoodPosition); } private void refreshFood(GamePosition foodPosition) { mGameStyles.get(foodPosition.getX()).get(foodPosition.getY()).setType(GameType.Food); } public void setMove(int snakeDirection) { if (snakeDirection == GameType.Left && mSnakeDirection == GameType.Right) return; if (snakeDirection == GameType.Right && mSnakeDirection == GameType.Left) return; if (snakeDirection == GameType.Top && mSnakeDirection == GameType.Bottom) return; if (snakeDirection == GameType.Bottom && mSnakeDirection == GameType.Top) return; mSnakeDirection = snakeDirection; } private void moveSnake(int snakeDirection) { switch (snakeDirection) { case GameType.Left: if (mSnakeHeader.getX() - 1 < 0) { mSnakeHeader.setX(mGameViewSize - 1); } else { mSnakeHeader.setX(mSnakeHeader.getX() - 1); } mSnakePosition.add(new GamePosition(mSnakeHeader.getX(), mSnakeHeader.getY())); break; case GameType.Right: if (mSnakeHeader.getX() + 1 >= mGameViewSize) { mSnakeHeader.setX(0); } else { mSnakeHeader.setX(mSnakeHeader.getX() + 1); } mSnakePosition.add(new GamePosition(mSnakeHeader.getX(), mSnakeHeader.getY())); break; case GameType.Top: if (mSnakeHeader.getY() - 1 < 0) { mSnakeHeader.setY(mGameViewSize - 1); } else { mSnakeHeader.setY(mSnakeHeader.getY() - 1); } mSnakePosition.add(new GamePosition(mSnakeHeader.getX(), mSnakeHeader.getY())); break; case GameType.Bottom: if (mSnakeHeader.getY() + 1 >= mGameViewSize) { mSnakeHeader.setY(0); } else { mSnakeHeader.setY(mSnakeHeader.getY() + 1); } mSnakePosition.add(new GamePosition(mSnakeHeader.getX(), mSnakeHeader.getY())); break; } } // 重新整理身體 private void refreshBody() { for (GamePosition gamePosition : mSnakePosition) { mGameStyles.get(gamePosition.getX()).get(gamePosition.getY()).setType(GameType.Body); } } private void handleTail() { int snakeLength = mSnakeLength; // 將已經走過去的格子重置為普通格子 for (int i = mSnakePosition.size() - 1; i >= 0; i--) { if (snakeLength >= 0) { snakeLength--; } else { GamePosition position = mSnakePosition.get(i); mGameStyles.get(position.getX()).get(position.getY()).setType(GameType.Grid); } } snakeLength = mSnakeLength; for (int i = mSnakePosition.size() - 1; i >= 0; i--) { if (snakeLength >= 0) { snakeLength--; } else { mSnakePosition.remove(i); } } } public interface OnGameListener { void gameOver(); void getCount(int count); } public void setOnGameListener(OnGameListener listener) { this.mListener = listener; } public SnakeGameView(Context context) { this(context, null); } public SnakeGameView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SnakeGameView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } }

GameStyle

package com.example.snake6.control;

import android.graphics.Color;

public class GameStyle {
  private int type;

  public GameStyle(int type) {
    this.type = type;
  }

  public int setColor() {
    switch (type) {
      case GameType.Grid:
        return Color.WHITE;
      case GameType.Head:
        return Color.RED;
      case GameType.Body:
        return Color.GREEN;
      case GameType.Food:
        return Color.parseColor("#FFB6C1");
    }
    return Color.WHITE;
  }

  public void setType(int type) {
    this.type = type;
  }
}

Game Type

package com.example.snake6.control;

public interface GameType {
  int Grid = 1;
  int Head = 2;
  int Body = 3;
  int Food = 4;

  int Left = 1;
  int Right = 2;
  int Top = 3;
  int Bottom = 4;
}