五子棋的棋盤Android版
五子棋的棋盤Android版實現,具體上下文可以參考上一篇的五子棋AI實現中的代碼
import java.util.ArrayList; import java.util.List;import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.widget.TextView;
//棋盤 public class Chessboard extends View implements IChessboard{
//游戲狀態常量: //已準備好,可開局 private static final int READY = 1; //已開局 private static final int RUNNING = 2; //已結束 private static final int PLAYER_TWO_LOST = 3; private static final int PLAYER_ONE_LOST = 4; //當前狀態,默認為可開局狀態 private int currentMode = READY; //畫筆對象 private final Paint paint = new Paint(); //代表綠色 private static final int GREEN = 0; private static final int NEW_GREEN = 1; //紅色 private static final int RED = 2; //黃色 private static final int NEW_RED = 3; //點大小 private static int pointSize = 20; //用于提示輸贏的文本控件 private TextView textView = null; //不同顏色的Bigmap數組 private Bitmap[] pointArray = new Bitmap[4]; //屏幕右下角的坐標值,即最大坐標值 private static int maxX; private static int maxY; //第一點偏離左上角從像數,為了棋盤居中 private static int yOffset; private static int xOffset; //兩個玩家 //第一個玩家默認為人類玩家 private IPlayer player1 = new HumanPlayer(); //第二個則根據選擇人機戰還是對戰模式來初始化 private IPlayer player2; //預先初始兩個第二玩家 //電腦玩家 private static IPlayer computer = AiFactory.getInstance(2); //人類玩家 private static final IPlayer human = new HumanPlayer(); // 所有未下的空白點 private final List<Point> allFreePoints = new ArrayList<Point>(); public Chessboard(Context context, AttributeSet attrs) { super(context, attrs); setFocusable(true); //把三個顏色的點準備好,并放入數組 Resources r = this.getContext().getResources(); fillPointArrays(GREEN,r.getDrawable(R.drawable.green_point)); fillPointArrays(NEW_GREEN,r.getDrawable(R.drawable.new_green_point)); fillPointArrays(RED,r.getDrawable(R.drawable.red_point)); fillPointArrays(NEW_RED,r.getDrawable(R.drawable.new_red_point)); //設置畫線時用的顏色 paint.setColor(Color.LTGRAY);
}
//初始橫線和豎線的數目 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { maxX = (int) Math.floor(w / pointSize); maxY = (int) Math.floor(h / pointSize); //設置X、Y座標微調值,目的整個框居中 xOffset = ((w - (pointSize * maxX)) / 2); yOffset = ((h - (pointSize * maxY)) / 2); //創建棋盤上的線條 createLines(); //初始化棋盤上所有空白點 createPoints(); } //產生棋盤上所有的線 private void createLines(){ for (int i = 0; i <= maxX; i++) {//豎線 lines.add(new Line(xOffset+i*pointSize-pointSize/2, yOffset, xOffset+i*pointSize-pointSize/2, yOffset+maxY*pointSize)); } for (int i = 0; i <= maxY; i++) {//橫線 lines.add(new Line(xOffset, yOffset+i*pointSize-pointSize/2, xOffset+maxX*pointSize, yOffset+i*pointSize-pointSize/2)); } } //畫棋盤 private List<Line> lines = new ArrayList<Line>(); private void drawChssboardLines(Canvas canvas){ for (Line line : lines) { canvas.drawLine(line.xStart, line.yStart, line.xStop, line.yStop, paint); } } //線類 class Line{ float xStart,yStart,xStop,yStop; public Line(float xStart, float yStart, float xStop, float yStop) { this.xStart = xStart; this.yStart = yStart; this.xStop = xStop; this.yStop = yStop; } } //畫點 private void drawPoint(Canvas canvas,Point p,int color){ canvas.drawBitmap(pointArray[color],p.x*pointSize+xOffset,p.y*pointSize+yOffset,paint); } //設置運行狀態 public void setMode(int newMode) { currentMode = newMode; if(currentMode==PLAYER_TWO_LOST){ //提示玩家2輸了 textView.setText(R.string.player_two_lost); currentMode = READY; }else if(currentMode==RUNNING){ textView.setText(null); }else if(currentMode==READY){ textView.setText(R.string.mode_ready); }else if(currentMode==PLAYER_ONE_LOST){ //提示玩家1輸了 textView.setText(R.string.player_one_lost); currentMode = READY; } } //設置提示控件 public void setTextView(TextView textView) { this.textView = textView; } //監聽鍵盤事件 @Override public boolean onKeyDown(int keyCode, KeyEvent msg) { if (currentMode == READY && (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT)) { if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){//向右鍵,人機對戰 player2 = computer; }else if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){//向左鍵,人--人對戰 player2 = human; } restart(); setMode(RUNNING); }else if(currentMode==RUNNING && keyCode == KeyEvent.KEYCODE_DPAD_DOWN){//重新開始 restart(); setMode(READY); }else{ return false; } return true; } public void startPlayerVsComputer(int level) { if (currentMode == READY) { if (level < 3) { computer = AiFactory.getInstance(level); player2 = computer; restart(); setMode(RUNNING); } else { setMode(READY); textView.setText(R.string.geniusWinLabel); } } } public void startPlayerVsPlayer() { if (currentMode == READY) { player2 = human; } restart(); setMode(RUNNING); } public void restartGame() { if (currentMode == RUNNING) { restart(); setMode(READY); } } //根據觸摸點坐標找到對應點 private Point newPoint(Float x, Float y){ Point p = new Point(0, 0); for (int i = 0; i < maxX; i++) { if ((i * pointSize + xOffset) <= x && x < ((i + 1) * pointSize + xOffset)) { p.setX(i); } } for (int i = 0; i < maxY; i++) { if ((i * pointSize + yOffset) <= y && y < ((i + 1) * pointSize + yOffset)) { p.setY(i); } } return p; } //重新開始 private void restart() { createPoints(); player1.setChessboard(this); player2.setChessboard(this); setPlayer1Run(); //刷新一下 refressCanvas(); } //是否已開局 private boolean hasStart(){ return currentMode==RUNNING; } //處理觸摸事件 @Override public boolean onTouchEvent(MotionEvent event) { //還沒有開局,或者是按下事件,不處理,只處理開局后的觸摸彈起事件 if(!hasStart() || event.getAction()!=MotionEvent.ACTION_UP){ return true; } //是否正在處理一步棋的過程中 if(onProcessing()){ return true; } playerRun(event); return true; } private synchronized void playerRun(MotionEvent event){ if(isPlayer1Run()){//第一玩家下棋 player1Run(event); }else if(isPlayer2Run()){//第二玩家下棋 player2Run(event); } } private void player1Run(MotionEvent event){ Point point = newPoint(event.getX(), event.getY()); if(allFreePoints.contains(point)){//此棋是否可下 setOnProcessing(); player1.run(player2.getMyPoints(),point); //playerOnePoints.add(point); //刷新一下棋盤 refressCanvas(); //判斷第一個玩家是否已經下了 if(!player1.hasWin()){//我還沒有贏 if(player2==computer){//如果第二玩家是電腦 //10豪秒后才給玩家2下棋 refreshHandler.computerRunAfter(10); }else{ setPlayer2Run(); } }else{ //否則,提示游戲結束 setMode(PLAYER_TWO_LOST); } } } private void player2Run(MotionEvent event){ Point point = newPoint(event.getX(), event.getY()); if(allFreePoints.contains(point)){//此棋是否可下 setOnProcessing(); player2.run(player1.getMyPoints(),point);
// playerTwoPoints.add(point); //刷新一下棋盤 refressCanvas(); //判斷我是否贏了 if(!player2.hasWin()){//我還沒有贏 setPlayer1Run(); }else{ //否則,提示游戲結束 setMode(PLAYER_ONE_LOST); } } }
private RefreshHandler refreshHandler = new RefreshHandler(); class RefreshHandler extends Handler { //這個方法主要在指定的時刻發一個消息 public void computerRunAfter(long delayMillis) { this.removeMessages(0); //發消息觸發handleMessage函數 sendMessageDelayed(obtainMessage(0), delayMillis); } //收到消息 @Override public void handleMessage(Message msg) { //電腦走一步棋子 player2.run(player1.getMyPoints(),null); //刷新一下 refressCanvas(); if(!player2.hasWin()){ //人下 setPlayer1Run(); }else{//第二個玩家贏了 setMode(PLAYER_ONE_LOST); } } }; //是否正在下某一步棋過程中,主是電腦下棋時需要較長的計算時間,這期間一定不可以再響應觸摸事件 private boolean onProcessing() { return whoRun == -1; } //默認第一個玩家先行 private int whoRun = 1; private void setPlayer1Run(){ whoRun = 1; } private void setOnProcessing(){ whoRun = -1; } //是否輪到人類玩家下子 private boolean isPlayer1Run(){ return whoRun==1; } //是否輪到人類玩家下子 private boolean isPlayer2Run(){ return whoRun==2; } private void setPlayer2Run(){ whoRun = 2; } private void refressCanvas(){ //觸發onDraw函數 Chessboard.this.invalidate(); } private void drawPlayer1Point(Canvas canvas){ int size = player1.getMyPoints().size()-1; if(size<0){ return ; } for (int i = 0; i < size; i++) { drawPoint(canvas, player1.getMyPoints().get(i), GREEN); } //最后下的一個點標成黃色 drawPoint(canvas, player1.getMyPoints().get(size), NEW_GREEN); } private void drawPlayer2Point(Canvas canvas){ if(player2==null){ return ; } int size = player2.getMyPoints().size()-1; if(size<0){ return ; } for (int i = 0; i < size; i++) { drawPoint(canvas, player2.getMyPoints().get(i), RED); } //最后下的一個點標成黃色 drawPoint(canvas, player2.getMyPoints().get(size), NEW_RED); } //初始化好三種顏色的點 public void fillPointArrays(int color,Drawable drawable) { Bitmap bitmap = Bitmap.createBitmap(pointSize, pointSize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, pointSize, pointSize); drawable.draw(canvas); pointArray[color] = bitmap; } //doRun方法操作的是看不見的內存數據,此方法內容數據以圖畫的方式表現出來,所以畫之前數據一定要先準備好 @Override protected void onDraw(Canvas canvas) { drawChssboardLines(canvas); //畫鼠標所在的點 drawPlayer1Point(canvas); //畫電腦下的棋子 drawPlayer2Point(canvas); } @Override public List<Point> getFreePoints() { return allFreePoints; } //初始化空白點集合 private void createPoints(){ allFreePoints.clear(); for (int i = 0; i < maxX; i++) { for (int j = 0; j < maxY; j++) { allFreePoints.add(new Point(i, j)); } } } @Override public int getMaxX() { return maxX; } @Override public int getMaxY() { return maxY; }
}</pre>