五子棋的棋盘Android版

11年前
五子棋的棋盘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;   }  }