Back to project page MiReversi.
The source code is released under:
MIT License
If you think the Android project MiReversi listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (c) 2011 Makoto Ishida/*from w w w.ja va 2s. c om*/ * Please see the file MIT-LICENSE.txt for copying permission. */ package com.example.mireversi; import java.util.ArrayList; import java.util.List; import com.example.mireversi.model.Board; import com.example.mireversi.model.Cell; import com.example.mireversi.model.IPlayerCallback; import com.example.mireversi.model.Player; import com.example.mireversi.model.Cell.E_STATUS; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.RadialGradient; import android.graphics.RectF; import android.graphics.Paint.Style; import android.graphics.Shader; import android.os.Handler; import android.text.TextUtils; import android.view.MotionEvent; import android.view.View; import android.widget.Toast; public class ReversiView extends View implements IPlayerCallback, Runnable{ private static final int VIEW_ID = 1000; private Board mBoard; private Paint mPaintScreenBg = new Paint(); private Paint mPaintScreenBg2 = new Paint(); private Paint mPaintBoardBg = new Paint(); private Paint mPaintBoardBorder = new Paint(); private Paint mPaintCellFgB = new Paint(); private Paint mPaintCellFgW = new Paint(); private Paint mPaintCellAvB = new Paint(); private Paint mPaintCellAvW = new Paint(); private Paint mPaintTextFg = new Paint(); private Paint mPaintTurnRect = new Paint(); private Paint mPaintWinnerRect = new Paint(); private Paint mPaintCellCur = new Paint(); private Bitmap mBitmapWhite; private Bitmap mBitmapBlack; private Bitmap mBitmapBoard; private int mWidth; private int mHeight; private static final float CELL_SIZE_FACTOR = 0.40f; private static final float CELL_SIZE_FACTOR_PRG = 0.30f; private boolean mPaused; private Handler mHandler = new Handler(); private List<Cell> mTurnningCells = null; private List<Cell> mChangedCells = null; private int mTurnningProgress = 0; private static final int TURNNING_FREQ = 15; //frames to complete a turn. private static final int TURNING_TIME = 600; //msec private Bitmap[] mBitmapBtoW = new Bitmap[TURNNING_FREQ]; private Bitmap[] mBitmapWtoB = new Bitmap[TURNNING_FREQ]; public ReversiView(Context context) { super(context); setId(VIEW_ID); setFocusable(true); mPaintScreenBg.setColor(getResources().getColor(R.color.screen_bg)); mPaintScreenBg2.setColor(getResources().getColor(R.color.screen_bg2)); mPaintBoardBg.setColor(getResources().getColor(R.color.board_bg)); mPaintBoardBorder.setColor(getResources().getColor(R.color.board_border)); mPaintCellFgB.setColor(getResources().getColor(R.color.cell_fg_black)); mPaintCellFgW.setColor(getResources().getColor(R.color.cell_fg_white)); mPaintCellAvB.setColor(getResources().getColor(R.color.cell_fg_black)); mPaintCellAvW.setColor(getResources().getColor(R.color.cell_fg_white)); mPaintCellCur.setColor(getResources().getColor(R.color.cell_fg_current)); mPaintTextFg.setColor(getResources().getColor(R.color.text_fg)); mPaintTurnRect.setColor(getResources().getColor(R.color.turn_rect)); mPaintWinnerRect.setColor(getResources().getColor(R.color.winner_rect)); //??????????????????????????????????????????????? mPaintCellFgB.setAntiAlias(true); mPaintCellFgW.setAntiAlias(true); mPaintCellAvB.setAntiAlias(true); mPaintCellAvW.setAntiAlias(true); mPaintCellCur.setAntiAlias(true); mPaintCellAvB.setAlpha(32); mPaintCellAvW.setAlpha(64); mPaintCellCur.setAlpha(128); mPaintTextFg.setAntiAlias(true); mPaintTextFg.setStyle(Style.FILL); //????URL: // http://y-anz-m.blogspot.com/2010/02/android-multi-screen.html // http://y-anz-m.blogspot.com/2010/05/androiddimension.html Resources res = getResources(); int fontSize = res.getDimensionPixelSize(R.dimen.font_size_status); mPaintTextFg.setTextSize(fontSize); mPaintTurnRect.setAntiAlias(true); mPaintTurnRect.setAlpha(128); mPaintTurnRect.setStyle(Style.STROKE); mPaintTurnRect.setStrokeWidth(5f); mPaintWinnerRect.setAntiAlias(true); mPaintWinnerRect.setAlpha(192); mPaintWinnerRect.setStyle(Style.STROKE); mPaintWinnerRect.setStrokeWidth(5f); init(false); } public void init(boolean auto_start){ mBoard = new Board(); mPaused = false; mBoard.setPlayer1(Player.getPlayer1(getContext(), mBoard, E_STATUS.Black)); mBoard.setPlayer2(Player.getPlayer2(getContext(), mBoard, E_STATUS.White)); invalidate(); //Utils.d("init"); if (auto_start){ callPlayer(); } GameActivity activity = (GameActivity)this.getContext(); activity.hideWinner("Started!"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); this.mWidth = getWidth(); this.mHeight = getHeight(); mBoard.setSize(this.mWidth, this.mHeight); if (mBitmapBlack == null){ loadBitmap(); } drawBoard(canvas); } private void loadBitmap(){ float cw = mBoard.getCellWidth(); float ch = mBoard.getCellHeight(); int INSET = (int)(cw * CELL_SIZE_FACTOR * 0.3); Resources res = this.getContext().getResources(); try { //???????? Bitmap board = BitmapFactory.decodeResource(res, R.drawable.bg2_green2); mBitmapBoard = Bitmap.createScaledBitmap(board, (int)mBoard.getRectF().width(), (int)mBoard.getRectF().height(), true); } catch (Exception ex) { Utils.d(ex.getMessage()); } try { //?????? Bitmap black = BitmapFactory.decodeResource(res, R.drawable.b1); mBitmapBlack = Bitmap.createScaledBitmap(black, (int)(cw-INSET*2), (int)(ch-INSET*2), true); //?????? Bitmap white = BitmapFactory.decodeResource(res, R.drawable.w1); mBitmapWhite = Bitmap.createScaledBitmap(white, (int)cw-INSET*2, (int)ch-INSET*2, true); //??????????????????????????????????????????? for (int i = 1;i <= TURNNING_FREQ; i++){ if (i <= TURNNING_FREQ/2){ mBitmapBtoW[i-1] = Bitmap.createScaledBitmap(mBitmapBlack, (int)(cw-INSET*2) * (TURNNING_FREQ - i*2) / TURNNING_FREQ, (int)(ch-INSET*2), true); mBitmapWtoB[i-1] = Bitmap.createScaledBitmap(mBitmapWhite, (int)(cw-INSET*2) * (TURNNING_FREQ - i*2) / TURNNING_FREQ, (int)(ch-INSET*2), true); } else { mBitmapBtoW[i-1] = Bitmap.createScaledBitmap(mBitmapWhite, (int)(cw-INSET*2) * (i*2 - TURNNING_FREQ) / TURNNING_FREQ, (int)(ch-INSET*2), true); mBitmapWtoB[i-1] = Bitmap.createScaledBitmap(mBitmapBlack, (int)(cw-INSET*2) * (i*2 - TURNNING_FREQ) / TURNNING_FREQ, (int)(ch-INSET*2), true); } } } catch (Exception ex){ Utils.d(ex.getMessage()); } } @Override public boolean onTouchEvent(MotionEvent event) { //??????????????????????????? if (mTurnningCells != null || mTurnningProgress > 0) return true; float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_UP: int r = (int)(y / mBoard.getCellHeight()); int c = (int)(x / mBoard.getCellWidth()); if (r < Board.ROWS && c < Board.COLS && r >=0 && c >= 0){ Player p = mBoard.getCurrentPlayer(); if (p != null && p.isHuman()){ move(new Point(c, r)); } } break; default: } return true; } private void move(final Point point){ //???????????????????????????????????????????????????? if (mTurnningCells != null){ mHandler.postDelayed(new Runnable(){ @Override public void run(){ move(point); } }, TURNING_TIME / 2); return; } mChangedCells = null; mTurnningCells = null; mTurnningProgress = 0; Cell currentCell = mBoard.getCell(point); if (currentCell.getReversibleCells().size() == 0){ String s = String.format("Invalid move. (r,c=%d,%d)", point.y, point.x); //Toast.makeText(this.getContext(), s, Toast.LENGTH_SHORT).show(); Utils.d(s); return; } mChangedCells = mBoard.changeCell(point, mBoard.getTurn()); mTurnningCells = new ArrayList<Cell>(mChangedCells); mTurnningCells.remove(currentCell); int nextAvailableCellCount = mBoard.changeTurn(mChangedCells); if (nextAvailableCellCount == 0){ if (mBoard.countBlankCells() == 0){ //????????????????????????????? finish(); } else { showSkippMessage(); //???? nextAvailableCellCount = mBoard.changeTurn(mChangedCells); if (nextAvailableCellCount == 0){ //??????????????????????????????????????? finish(); } } } invalidate(currentCell.getRect()); //?????????????????????? startTurnning(); //???????????????????? callPlayer(); } @Override public void onEndThinking(final Point pos) { if (pos == null) return; if (pos.y < 0 || pos.x < 0) return; if (mPaused) return; move(pos); } @Override public void onProgress() { invalidate(0, (int)mBoard.getRectF().bottom, mWidth, mHeight); } @Override public void onPointStarted(Point pos) { Cell cell = mBoard.getCell(pos); invalidate(cell.getRect()); //???????????????????????? } @Override public void onPointEnded(Point pos) { Cell cell = mBoard.getCell(pos); invalidate(cell.getRect()); //???????????????????????? } private void finish(){ //???????????????????????????????????????????????????? if (mTurnningCells != null){ mHandler.postDelayed(new Runnable(){ @Override public void run(){ finish(); } }, TURNING_TIME / 2); return; } mBoard.setFinished(); invalidate(); } public void showCountsToast(){ Cell.E_STATUS winner = mBoard.getWinnerStatus(); String msg = "Black: " + mBoard.countCells(Cell.E_STATUS.Black) + "\n" + "White: " + mBoard.countCells(Cell.E_STATUS.White) + "\n\n"; if (mBoard.isFinished()){ if (winner != Cell.E_STATUS.None){ msg += "Winner is: " + Cell.statusToDisplay(winner) + "!!"; } else { msg += "Draw game! "; } } else { if (winner != Cell.E_STATUS.None){ msg += Cell.statusToDisplay(winner) + " is winning...\n\n"; } msg += mBoard.getTurnDisplay() + "'s turn."; } Toast.makeText(this.getContext(), msg, Toast.LENGTH_LONG).show(); Utils.d(msg); } private void showSkippMessage(){ String msg = Cell.statusToDisplay(mBoard.getTurn()) + " has been skipped."; Toast.makeText(this.getContext(), msg, Toast.LENGTH_SHORT).show(); Utils.d(msg); } private void drawBoard(Canvas canvas){ if (mBoard.getRectF().width() <= 0f ) return; float bleft = mBoard.getRectF().left; float btop = mBoard.getRectF().top; float bw = mBoard.getRectF().width(); float bh = mBoard.getRectF().height(); float cw = mBoard.getCellWidth(); float ch = mBoard.getCellHeight(); //???????? canvas.drawBitmap(mBitmapBoard, bleft, btop, null); //?? for (int i = 0; i < Board.COLS; i++) { canvas.drawLine(cw * (i+1) + bleft, btop, cw * (i+1) + bleft, bh + btop, mPaintBoardBorder); } //?? for (int i = 0; i < Board.ROWS; i++) { canvas.drawLine(bleft, ch * (i+1) + btop, bw + bleft, ch * (i+1) + btop, mPaintBoardBorder); } //???????Cell????? drawCells(canvas, cw); //?????????????????????????????? drawStatus(canvas); } //???????Cell???????????????????????????????????????? private void drawCells(Canvas canvas, float cw){ boolean show_hints = Pref.getShowHints(getContext()); Cell[][] cells = mBoard.getCells(); for (int i = 0; i < Board.ROWS; i++) { for (int j = 0; j < Board.COLS; j++) { Cell cell =cells[i][j]; Cell.E_STATUS st = cell.getStatus(); if (st == E_STATUS.None){ if (show_hints) drawHints(cell, canvas, cw); } else { drawStone(cell, canvas, cw, st); } } } } private void drawStone(Cell cell, Canvas canvas, float cw, Cell.E_STATUS st){ final float INSET = (cell.getWidth() * CELL_SIZE_FACTOR * 0.3f); Bitmap bm; if (mTurnningProgress >0 && mTurnningCells != null && mTurnningCells.contains(cell)){ bm = (st == E_STATUS.Black) ? mBitmapWtoB[mTurnningProgress-1] : mBitmapBtoW[mTurnningProgress-1]; int offset_w; if (mTurnningProgress <= TURNNING_FREQ/2){ offset_w = (int)(cw-INSET*2) * (mTurnningProgress*2) / TURNNING_FREQ / 2; } else { offset_w = (int)(cw-INSET*2) * (TURNNING_FREQ - mTurnningProgress)*2 / TURNNING_FREQ / 2; } canvas.drawBitmap(bm, cell.getLeft()+INSET + offset_w, cell.getTop()+INSET, null); } else { bm = (st == E_STATUS.Black) ? mBitmapBlack : mBitmapWhite; canvas.drawBitmap(bm, cell.getLeft()+INSET, cell.getTop()+INSET, null); } } private void drawHints(Cell cell, Canvas canvas, float cw){ if (cell.getReversibleCells().size() == 0) return; //?????????????????????????????????????????? float aw = cw * 0.1f; Paint pt = mBoard.getTurn() == Cell.E_STATUS.Black ? mPaintCellAvB : mPaintCellAvW; canvas.drawCircle(cell.getCx(), cell.getCy(), aw, pt); } private void drawStatus(Canvas canvas){ Resources res = getResources(); float turn_rect_inset = res.getDimension(R.dimen.turn_rect_inset); float turn_rect_round = res.getDimension(R.dimen.turn_rect_round); float turn_circle_x = res.getDimension(R.dimen.turn_circle_x); float turn_circle_y = res.getDimension(R.dimen.turn_circle_y); float turn_text_x = res.getDimension(R.dimen.turn_text_x); float turn_text_y = res.getDimension(R.dimen.turn_text_y); float top = mBoard.getRectF().bottom + mBoard.getRectF().top; float center = mBoard.getRectF().width() / 2f; //????????????????? // Shader shader = new LinearGradient(mWidth/2, top + (mHeight - top) * 0.5f, mWidth/2, mHeight, mPaintScreenBg.getColor(), mPaintScreenBg2.getColor(), Shader.TileMode.CLAMP); Shader shader = new RadialGradient(mWidth/2f, top * 0.9f, mWidth * 0.7f, mPaintScreenBg2.getColor(), mPaintScreenBg.getColor(), Shader.TileMode.CLAMP); Paint paint = new Paint( mPaintScreenBg); paint.setShader(shader); canvas.drawRect(0, top, mWidth, mHeight, paint); if (!mBoard.isFinished()){ RectF rect; if (mBoard.getTurn() == E_STATUS.Black){ rect = new RectF(turn_rect_inset, top + turn_rect_inset, center - turn_rect_inset, mHeight - turn_rect_inset); } else { rect = new RectF(center + turn_rect_inset, top + turn_rect_inset, mWidth - turn_rect_inset, mHeight - turn_rect_inset); } mPaintTurnRect.setStyle(Style.FILL); mPaintTurnRect.setAlpha(128); canvas.drawRoundRect(rect, turn_rect_round, turn_rect_round, mPaintTurnRect); //?? mPaintTurnRect.setStyle(Style.STROKE); mPaintTurnRect.setAlpha(255); canvas.drawRoundRect(rect, turn_rect_round, turn_rect_round, mPaintTurnRect); //? } float circle_w = mBoard.getCellWidth() * CELL_SIZE_FACTOR; //????? canvas.drawCircle(turn_circle_x, top + turn_circle_y, circle_w, mPaintCellFgB); //?????????? canvas.drawCircle(center + turn_circle_x, top + turn_circle_y, circle_w, mPaintCellFgB); canvas.drawCircle(center + turn_circle_x, top + turn_circle_y, circle_w * 0.94f, mPaintCellFgW); //????????????????? int fontSize = res.getDimensionPixelSize(R.dimen.font_size_status); mPaintTextFg.setTextSize(fontSize); String s = String.valueOf(mBoard.countCells(E_STATUS.Black)); canvas.drawText(s, turn_text_x, top + turn_text_y, mPaintTextFg); //??????? s = String.valueOf(mBoard.countCells(E_STATUS.White)); canvas.drawText(s, center + turn_text_x, top + turn_text_y, mPaintTextFg); //??????? //??????????????????? int fontSizeName = res.getDimensionPixelSize(R.dimen.font_size_name); mPaintTextFg.setTextSize(fontSizeName); canvas.drawText(mBoard.getPlayer1().getName(), turn_circle_x, top + turn_text_y*1.8f, mPaintTextFg); //????????? canvas.drawText(mBoard.getPlayer2().getName(), center + turn_circle_x, top + turn_text_y*1.8f, mPaintTextFg); //????????? //?????????????????????????????????? Player p = mBoard.getCurrentPlayer(); if (p != null && !p.isHuman() /*&& mTurnningCells == null*/){ //?????????????????????? Cell cell = p.getCurrentCell(); if (cell != null){ canvas.drawCircle(cell.getCx(), cell.getCy(), mBoard.getCellWidth() * CELL_SIZE_FACTOR_PRG, mPaintCellCur); invalidate(cell.getRect()); } } if (mBoard.isFinished()){ mPaintTextFg.setTextSize(fontSize); drawWinner(canvas); } } private void drawWinner(Canvas canvas){ String s; Player winner = mBoard.getWinner(); if (winner != null){ s = winner.getName() + " wins! "; } else { s = "Draw game! "; } // //????????????? // Paint paintBg = new Paint(); // paintBg.setColor(Color.BLACK); // paintBg.setAlpha(128); // canvas.drawRect(mBoard.getRectF(), paintBg); GameActivity activity = (GameActivity)this.getContext(); activity.showWinner(s); } public String getState(){ String s = mBoard.getStateString(); Utils.d("getState: state=" + s); return s; } public void pause(){ mPaused = true; Player p = mBoard.getCurrentPlayer(); if (p != null && !p.isHuman()){ //???????????????????????????????????????? p.stopThinking(); } } public void resume(String state){ Utils.d("onResume: state=" + state); mPaused = false; if (!TextUtils.isEmpty(state)){ mBoard.loadFromStateString(state); mBoard.setPlayer1(Player.getPlayer1(getContext(), mBoard, E_STATUS.Black)); mBoard.setPlayer2(Player.getPlayer2(getContext(), mBoard, E_STATUS.Black)); } callPlayer(); } private void callPlayer(){ if (mPaused) return; //???????????????????????????????????????????????????? if (mTurnningCells != null){ mHandler.postDelayed(new Runnable(){ @Override public void run(){ callPlayer(); } }, TURNING_TIME / 2); return; } Player p = mBoard.getCurrentPlayer(); if (p != null && !p.isHuman()){ p.startThinking(this); } } //????????????????????????????????? private void startTurnning(){ new Thread(this).start(); } //???????????????????????????????? @Override public void run() { if (mTurnningCells != null && mTurnningCells.size() >0){ for (mTurnningProgress = 1; mTurnningProgress <= TURNNING_FREQ; mTurnningProgress++){ //????????UI?????????????????????????? mHandler.post(new Runnable(){ @Override public void run(){ if (mTurnningCells != null){ for (Cell cell : mTurnningCells) { invalidate(cell.getRect()); //???????????????????????? } } } }); try { Thread.sleep(TURNING_TIME / TURNNING_FREQ); } catch (Exception e) { Utils.d(e.getMessage()); } } } mTurnningCells = null; mTurnningProgress = 0; //????????????????????? mHandler.post(new Runnable(){ @Override public void run(){ if (mChangedCells != null){ for (Cell cell : mChangedCells) { invalidate(cell.getRect()); //???????????????????????? } } //????????????????????????? invalidate(0, (int)mBoard.getRectF().bottom, mWidth, mHeight); } }); } }