安卓開發 數獨
阿新 • • 發佈:2020-12-12
技術標籤:安卓
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);
}
}
}
}