1. 程式人生 > 其它 >安卓開發 數獨

安卓開發 數獨

技術標籤:安卓

GameView

package com.example.sudoku4.views;

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

import androidx.annotation.
Nullable; import com.example.sudoku4.gameHelper.GameControl; import com.example.sudoku4.gameHelper.KeyBoardAlert; public class GameView extends View { private int width, height; private Paint mTextPaint, mNormalPaint, mHintPaint, mSuperPaint; private GameControl mGameControl; private boolean
mGameIsOver; private int mTouchY; private int mTouchX; private OnGameListener mListener; private int mode; @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.width = w / 9; this.height = h / 9; } @Override
protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.BLACK); for (int i = 0; i < 9; i++) { canvas.drawLine(0, height * i, getWidth(), height * i, mNormalPaint); canvas.drawLine(0, height * i + 1, getWidth(), height * i + 1, mHintPaint); canvas.drawLine(width * i, 0, width * i, getHeight(), mNormalPaint); canvas.drawLine(width * i + 1, 0, width * i + 1, getHeight(), mNormalPaint); } for (int i = 0; i < 9; i++) { if (i % 3 != 0) continue; canvas.drawLine(0, height * i, getWidth(), height * i, mSuperPaint); canvas.drawLine(0, height * i + 1, getWidth(), height * i + 1, mHintPaint); canvas.drawLine(width * i, 0, width * i, getHeight(), mSuperPaint); canvas.drawLine(width * i + 1, 0, width * i + 1, getHeight(), mNormalPaint); } Paint.FontMetrics fm = mTextPaint.getFontMetrics(); int x = width / 2; int y = (int) (height / 2 - (fm.ascent + fm.descent) / 2); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { canvas.drawText(mGameControl.getXyBackData(i, j), i * width + x, j * height + y, mTextPaint); } } } @Override public boolean onTouchEvent(MotionEvent event) { if (mGameIsOver) return true; if (event.getAction() == MotionEvent.ACTION_DOWN) { mTouchX = (int) event.getX() / width; mTouchY = (int) event.getY() / height; int[] used = mGameControl.getUsed(mTouchX, mTouchY); KeyBoardAlert keyBoardAlert = new KeyBoardAlert(getContext(), GameView.this, used); keyBoardAlert.show(); } return super.onTouchEvent(event); } public void setTileData(int value) { if (mGameControl.setTileData(mTouchX, mTouchY, value)) { if (mGameControl.gameIsOver()) { mGameIsOver = true; if (mListener != null) { mListener.gameOver(); } } invalidate(); } } public void setMode(int mode) { this.mode = mode; mGameControl = new GameControl(mode); invalidate(); } private void init() { mGameIsOver = false; mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextAlign(Paint.Align.CENTER); mTextPaint.setColor(Color.WHITE); mTextPaint.setTextSize(100); mNormalPaint = new Paint(); mNormalPaint.setAntiAlias(true); mNormalPaint.setColor(Color.parseColor("#888888")); mHintPaint = new Paint(); mHintPaint.setAntiAlias(true); mHintPaint.setColor(Color.parseColor("#444444")); mSuperPaint = new Paint(); mSuperPaint.setAntiAlias(true); mSuperPaint.setColor(Color.WHITE); } public interface OnGameListener { void gameOver(); } public void setOnGameListener(OnGameListener listener) { this.mListener = listener; } public void playAgain() { mGameIsOver = false; mGameControl = null; mGameControl = new GameControl(mode); invalidate(); } public GameView(Context context) { this(context, null); } public GameView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public GameView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } }

GameControl

package com.example.sudoku4.gameHelper;

public class GameControl {
  private String template = "360000000004230800000004200"
    + "070460003820000014500013020"
    + "001900000007048300000000045";

  private final String test = "971685324" +
    "425793168" +
    "638214975" +
    "753841296" +
    "892567413" +
    "164932587" +
    "519376842" +
    "347128659" +
    "286459730";

  private int[] mTile;
  private int[][][] mUsed = new int[9][9][];

  public GameControl(int mode) {
    if (mode == 1) {
      initData(test);
    } else {
      initData(template);
    }
    calculateUsedTileAll();
  }

  private int getTile(int x, int y) {
    return mTile[y * 9 + x];
  }

  private void setTile(int x, int y, int value) {
    mTile[y * 9 + x] = value;
  }

  public int[] getUsed(int x, int y) {
    return mUsed[x][y];
  }

  private void initData(String data) {
    mTile = new int[data.length()];
    for (int i = 0; i < mTile.length; i++) {
      mTile[i] = data.charAt(i) - '0';
    }
  }

  public String getXyBackData(int x, int y) {
    int temp = getTile(x, y);

    if (temp == 0) {
      return "";
    } else {
      return temp + "";
    }
  }

  public int[] calculateUsedTile(int x, int y) {
    int[] count = new int[9];

    for (int i = 0; i < 9; i++) {
      if (i == x) continue;
      int temp = getTile(i, y);
      if (temp != 0) {
        count[temp - 1] = temp;
      }
    }

    for (int i = 0; i < 9; i++) {
      if (i == y) continue;
      int temp = getTile(x, i);
      if (temp != 0) {
        count[temp - 1] = temp;
      }
    }

    int startX = x / 3 * 3;
    int startY = y / 3 * 3;

    for (int i = startX; i < startX + 3; i++) {
      for (int j = startY; j < startY + 3; j++) {
        if (i == x && j == y) continue;
        int temp = getTile(i, j);
        if (temp != 0) {
          count[temp - 1] = temp;
        }
      }
    }

    int unUsed = 0;
    for (int i : count) {
      unUsed++;
    }

    int[] noZeroNewCount = new int[unUsed];
    unUsed = 0;

    for (int i : count) {
      if (i != 0) {
        noZeroNewCount[unUsed++] = i;
      }
    }
    return noZeroNewCount;
  }

  private void calculateUsedTileAll() {
    for (int i = 0; i < 9; i++) {
      for (int j = 0; j < 9; j++) {
        mUsed[i][j] = calculateUsedTile(i, j);
      }
    }
  }

  public boolean setTileData(int x, int y, int value) {
    int[] temp = getUsed(x, y);

    if (value != 0) {
      for (int i : temp) {
        if (i == value) return false;
      }
    }

    setTile(x, y, value);
    calculateUsedTileAll();
    return true;
  }

  public boolean gameIsOver() {
    int count = 0;

    for (int i = 0; i < 9; i++) {
      for (int j = 0; j < 9; j++) {
        int temp = getTile(i, j);
        if (temp != 0) count++;
      }
    }

    if (count == 81) {
      return true;
    }

    return false;
  }
}

Key bord

package com.example.sudoku4.gameHelper;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;

import com.example.sudoku4.R;
import com.example.sudoku4.views.GameView;

public class KeyBoardAlert extends Dialog {
  private final int[] mUsed;
  private GameView mGameView;
  private Context mContext;
  private Button[] mButtons = new Button[9];


  public KeyBoardAlert(@NonNull Context context, GameView gameView, int[] used) {
    super(context);
    this.mContext = context;
    this.mGameView = gameView;
    this.mUsed = used;
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_key_board);
    initView();
    initEvent();
  }

  private void initEvent() {
    for (int i = 0; i < mButtons.length; i++) {
      final String value = mButtons[i].getText().toString();
      mButtons[i].setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          updateGameView(value);
        }
      });
    }
  }

  private void updateGameView(String value) {
    mGameView.setTileData(Integer.parseInt(value));
    dismiss();
  }

  private void initView() {
    mButtons[0] = findViewById(R.id.key_1);
    mButtons[1] = findViewById(R.id.key_2);
    mButtons[2] = findViewById(R.id.key_3);
    mButtons[3] = findViewById(R.id.key_4);
    mButtons[4] = findViewById(R.id.key_5);
    mButtons[5] = findViewById(R.id.key_6);
    mButtons[6] = findViewById(R.id.key_7);
    mButtons[7] = findViewById(R.id.key_8);
    mButtons[8] = findViewById(R.id.key_9);

    for (int i = 0; i < mUsed.length; i++) {
      if (mUsed[i] != 0) {
        mButtons[mUsed[i] - 1].setVisibility(View.GONE);
      }
    }
  }
}