五子棋的棋盤Android版

Hadoopp 12年前發布 | 2K 次閱讀 DB-Engines Apache Cayenne 網絡開發

五子棋的棋盤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>

 本文由用戶 Hadoopp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!