五子棋的棋盤Android版

子棋的棋盤Android版實現,具體上下文可以參考上一篇的五子棋AI實現中的代碼
[java] 
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; 
    } 

You May Also Like