小游戏心得--五子棋(用于新手学习自定义view)

在学完了Android的基础之后,我开始尝试着写一些小项目练练手,同时进一步巩固自己的基础知识,而我选的的第一个项目就是做一个简单的人人对战的五子棋小游戏。

  首先,我们要新建一个自定义控件类Panel,这基本上涵盖着整个项目的大部分操作,比如棋盘的设计等等,下面开始Panel的编写,代码如下:

public class Chess_Panel extends View{
    private int myPanelWidth ;        //棋盘宽度
    private float myLineHeight;    //行宽
    private int maxLine = 10;        //行数
    
    private Paint myPaint;         //画笔
    private Bitmap myWhitePice;    //白棋子
    private Bitmap myBlackPice;    //黑棋子
    private float ratioPieceOfLineHight = 3 * 1.0f / 4;  //棋子为行宽的3/4;
    
    private boolean isGemOver;        //游戏结束
    public static int WHITE_WIN = 0;  //胜利为白方标志
    public static int BLACK_WIN = 1;  //胜利为黑方标志
    private boolean isWhite = true;  //判断是否是白棋先手,或当前为白棋下子
    
    private List<Point> myWhiteArray = new ArrayList<Point>();  //白棋子位置信息
    private List<Point> myBlackArray = new ArrayList<Point>();  //黑棋子位置信息
    
    private onGameListener onGameListener;  //回调接口
    private int mUnder;        //dialog的Y坐标
    
     public Chess_Panel(Context context) {
            this(context, null);
        }
     
    public Chess_Panel(Context context ,AttributeSet attributeSet){            //构造函数
        super(context , attributeSet);
        
        init(); 
    }

    //初始化函数
    private void init() {                    
        myPaint = new Paint();
        myPaint.setColor(0X44ff0000);     //给画笔设置颜色
        myPaint.setAntiAlias(true);      //设置画笔是否使用抗锯齿
        myPaint.setDither(true);            //设置画笔是否防抖动
        myPaint.setStyle(Paint.Style.STROKE);        //设置画笔样式,这里使用描边
        
        myWhitePice = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2); //设置棋子图片
        myBlackPice = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1);
                
    }

所谓自定义控件(或称组件)也就是编写自己的控件类型,而非Android中提供的标准的控件。构造函数中,使用AttributeSet来完成控件类的构造函数。

  Paint类:Android中的画笔类,用于绘制图形,它包含了很多方法对其属性进行设置,如下:

   setAntiAlias: 设置画笔的锯齿效果。 
   setColor: 设置画笔颜色 
   setARGB:  设置画笔的a,r,p,g值。 
   setAlpha:  设置Alpha值 
   setTextSize: 设置字体尺寸。 
   setStyle:  设置画笔风格,空心或者实心。 
   setStrokeWidth: 设置空心的边框宽度。 
   getColor:  得到画笔的颜色 
   getAlpha:  得到画笔的透明度。

  Bitmap指的是一张位图,而BitmapFactory是从文件,数据流,数组等的资源中生成一个Bitmap对象。               BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1)正是从资源中获取一张图片生成一个Bitmap对象的方法。当然,还有其他的方法可以用来生成Bitmap对象,这里就不一一列举了。

  设置好画笔属性之后,我们就开始来设计我们的棋盘布局,以及棋盘的触摸动作等,代码如下:

//触发动作
    public boolean onTouchEvent(MotionEvent event){             
        if (isGemOver) {
            return false;
        }
        
        int action = event.getAction();
        if (action == MotionEvent.ACTION_UP) {   //判断触摸动作,ACTION_UP为单点触摸离开
            int x = (int) event.getX();
            int y = (int) event.getY();
            Point p = getVaLidPiont(x,y);    //获取当前的坐标
            
            if (myWhiteArray.contains(p)|| myBlackArray.contains(p)) {
                return false;
            }
            
            if (isWhite) {
                myWhiteArray.add(p);
            }else {
                myBlackArray.add(p);
            }
            invalidate();         //invalidate()是用来刷新View的,必须在UI线程中使用
            isWhite = !isWhite;
        }
        return true;
    }
    
    
    private Point getVaLidPiont(int x , int y){
        return new Point((int)(x/myLineHeight),(int)(y/myLineHeight));
    }
    
    //计算布局大小
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
        
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
        
        int width = Math.min(widthSize, heightSize);
        
        if (widthMode == MeasureSpec.UNSPECIFIED) {            //MeasureSpec.UNSPECIFIED表示未知大小
            width = heightSize;
        }else if (heightMode == MeasureSpec.UNSPECIFIED) {
            width = widthSize;
        }
        
        setMeasuredDimension(width, width);
        
    }
    
    protected void onSizeChanged(int w, int h ,int oldw , int oldh) {         //当View大小发生改变的时候会被系统自动回调
        super.onSizeChanged(w, h, oldw, oldh);
        myPanelWidth = w;
        myLineHeight = myPanelWidth*1.0f/maxLine;
         mUnder = h - (h - myPanelWidth) / 2;
        
        int pieceWidth = (int) (myLineHeight*ratioPieceOfLineHight);  //棋子大小占行宽的3/4
        myWhitePice = Bitmap.createScaledBitmap(myWhitePice, pieceWidth, pieceWidth, false);    //以src为原图,创建新的图像,指定新图像的高宽以及是否可变。
        myBlackPice = Bitmap.createScaledBitmap(myBlackPice, pieceWidth, pieceWidth, false);    
    }

要学好android触控,就要先了解MotionEvent,同时要对所用的MotionEvent常用的API要比较深入的了解。掌握MotionEvent事件是自定义控件中一个十分重要的部分。

  事件的主要动作类型有如下几种:

    public static final int ACTION_DOWN             = 0;单点触摸动作

    public static final int ACTION_UP               = 1;单点触摸离开动作
    public static final int ACTION_MOVE             = 2;触摸点移动动作
    public static final int ACTION_CANCEL           = 3;触摸动作取消
     public static final int ACTION_OUTSIDE          = 4;触摸动作超出边界
    public static final int ACTION_POINTER_DOWN     = 5;多点触摸动作
    public static final int ACTION_POINTER_UP       = 6;多点离开动作
   以下是一些非touch事件
    public static final int ACTION_HOVER_MOVE       = 7;
    public static final int ACTION_SCROLL           = 8;
    public static final int ACTION_HOVER_ENTER      = 9;
    public static final int ACTION_HOVER_EXIT       = 10;

  onMeasure()函数由包含这个View的具体的ViewGroup调用, onMeasure()当控件的父元素正要放置该控件时调用.onMesure向父元素中传入两个参数——widthMeasureSpec和heightMeasureSpec,这两个参数是由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定,其中包含了Size和Mode信息。

  widthMeasureSpec和heightMeasureSpec的读取如下:

  int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);      
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

  pecMode一共有三种可能:

  MeasureSpec.EXACTLY:父视图希望子视图的大小应该是specSize中指定的。

 

  MeasureSpec.AT_MOST:子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。

 

  MeasureSpec.UNSPECIFIED:我们可以随意指定视图的大小。

  onSizeChanged(int w, int h ,int oldw , int oldh):当View大小发生改变(比如分辨率变化)的时候会被系统自动回调。

 

  Bitmap.createScaledBitmap(src,float, float, false) :以src为原图,创建新的图像,指定新图像的高宽以及是否可变。

接下来就开始设计棋盘线,代码如下:

protected void  onDraw(Canvas canvas) {       //Canvas类相当于一块画布
        super.onDraw(canvas);
        drawBroad(canvas);
        drawPiece(canvas);
        checkGameOver();
    }
    
    private void drawBroad(Canvas canvas){            //画出棋盘线
        int w = myPanelWidth;
        float lineHeight = myLineHeight;
        int startX = (int) (lineHeight/2);            //棋盘线起始X坐标
        int endX = (int)(w-lineHeight/2);            //棋盘终止X坐标
        for(int i = 0; i< maxLine; i++){
            int y = (int)((i+1.5)*lineHeight);        //y坐标
            
            canvas.drawLine(startX, y, endX, y, myPaint);        //画棋盘横向线
            canvas.drawLine(y, startX, y, endX, myPaint);        //画棋盘纵向线
        }
    }
    
    //画棋子
    private void drawPiece(Canvas canvas) {        
        int n1 = myWhiteArray.size();
        int n2 = myBlackArray.size();
        for(int i =0; i< n1 ;i++){
            Point whitePoint = myWhiteArray.get(i);
            canvas.drawBitmap(myWhitePice, (whitePoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight, 
                    (whitePoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
                                    //drawBitmap(Bitmap bitmap, float left, float top, Paint paint);Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置
        }
        
        for(int i =0; i< n2 ;i++){
            Point blackPoint = myBlackArray.get(i);
            canvas.drawBitmap(myBlackPice, (blackPoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight, 
                    (blackPoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
        }
    }

在Android中,Canvas类相当于画布,另外它也是显示位图(Bitmap类)的核心类,它的属性方法如下:

  Canvas(): 创建一个空的画布,可以使用setBitmap()方法来设置绘制具体的画布。
    Canvas(Bitmap bitmap): 以bitmap对象创建一个画布,则将内容都绘制在bitmap上,因此bitmap不得为null。
    Canvas(GL gl): 在绘制3D效果时使用,与OpenGL相关。
    drawColor: 设置Canvas的背景颜色。
    setBitmap:  设置具体画布。
    clipRect: 设置显示区域,即设置裁剪区。                                      isOpaque:检测是否支持透明。                                         rotate:  旋转画布                                                 translate:移动画布                                             scale:缩放画布
    setViewport:  设置画布中显示窗口。
    skew:  设置偏移量。                                             restore: 用来恢复上一次save之前的状态                                    save:用来保存Canvas的当前状态

 注意: save方法、restore方法一般是成对出现的,save方法可多于restore方法,但restore方法不能多于save方法

  drawBitmap(Bitmap bitmap, float left, float top, Paint paint) Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置,panit为我们设计的画笔

 接下来的就是游戏中的一些判断动作了:

//检测游戏是否结束
    private void checkGameOver(){
        boolean whiteWin = checkFiveInLine(myWhiteArray);
        boolean blackWin = checkFiveInLine(myBlackArray);
        
        if (whiteWin || blackWin) {
            isGemOver = true;
               if (onGameListener != null) {
                    onGameListener.onGameOver(whiteWin ? WHITE_WIN : BLACK_WIN);
               }
        }
    }
    //回调一个int数据用于设置Dialog的位置
     public int getUnder() {

            return mUnder;
        }
    
     //检测是否存在五棋子相连的情况
    private boolean checkFiveInLine(List<Point> myArray){
        for(Point p : myArray){
            int x = p.x;
            int y = p.y;
            
            boolean win_flag =                             //判断是否存在五子相连情况
                    checkHorizontal(x , y ,myArray)||checkVertical(x,y,myArray)
                    ||checkLeftDiagonal(x,y,myArray)||checkRightDiagonal(x,y,myArray);
            if (win_flag) {
                return true;
            }
        }
        return false;
    }

    //横向检查是否满足五子相连
    private boolean checkHorizontal(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x+i,y))) {
                count++;
            }else {
                break;
            }
        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x-i,y))) {
                count++;
            }else {
                break;
            }
            

            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //纵向检查是否满足五子相连
    private boolean checkVertical(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x,y+i))) {
                count++;
            }else {
                break;
            }
            
        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x,y-i))) {
                count++;
            }else {
                break;
            }
            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //左斜向检查是否满足五子相连
    private boolean checkLeftDiagonal(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x-i,y+i))) {
                count++;
            }else {
                break;
            }

        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x+i,y-i))) {
                count++;
            }else {
                break;
            }
            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //右斜向检查是否满足五子相连
    private boolean checkRightDiagonal(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){            //切记,i = 1 开始,否则就会只检测到三个子相连就结束了
            if (myArray.contains(new Point(x-i,y-i))) {
                count++;
            }else {
                break;
            }
        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x+i,y+i))) {
                count++;
            }else {
                break;
            }
            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //重新开始游戏
    protected void restartGame(){
        myWhiteArray.clear();
        myBlackArray.clear();
        isGemOver = false;
        isWhite = false;
        invalidate();  //刷新
    }

invalidate()是android中用于刷新View显示的一个方法。

  可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象。再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定义View。

  另外,我们还应该暴露我们自定义的控件的接口,以方便调用:

// 用于回调的接口
     public interface onGameListener { 
            void onGameOver(int i);
        }
     
     //自定义接口,用于显示dialog
    public void setOnGameListener(Chess_Panel.onGameListener onGameListener) {
            this.onGameListener = onGameListener;
        }

那么,完整的Chess_Panel代码如下所示:

package com.example.fivechess;


import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class Chess_Panel extends View{
    private int myPanelWidth ;        //棋盘宽度
    private float myLineHeight;    //行宽
    private int maxLine = 10;        //行数
    
    private Paint myPaint;         //画笔
    private Bitmap myWhitePice;    //白棋子
    private Bitmap myBlackPice;    //黑棋子
    private float ratioPieceOfLineHight = 3 * 1.0f / 4;  //棋子为行宽的3/4;
    
    private boolean isGemOver;        //游戏结束
    public static int WHITE_WIN = 0;  //胜利为白方标志
    public static int BLACK_WIN = 1;  //胜利为黑方标志
    private boolean isWhite = true;  //判断是否是白棋先手,或当前为白棋下子
    
    private List<Point> myWhiteArray = new ArrayList<Point>();  //白棋子位置信息
    private List<Point> myBlackArray = new ArrayList<Point>();  //黑棋子位置信息
    
    private onGameListener onGameListener;  //回调接口
    private int mUnder;        //dialog的Y坐标
    
     public Chess_Panel(Context context) {
            this(context, null);
        }
     
    public Chess_Panel(Context context ,AttributeSet attributeSet){            //构造函数
        super(context , attributeSet);
        
        init(); 
    }
    
    // 用于回调的接口
     public interface onGameListener { 
            void onGameOver(int i);
        }
     
     //自定义接口,用于显示dialog
    public void setOnGameListener(Chess_Panel.onGameListener onGameListener) {
            this.onGameListener = onGameListener;
        }
    
    //初始化函数
    private void init() {                    
        myPaint = new Paint();
        myPaint.setColor(0X44ff0000);     //给画笔设置颜色
        myPaint.setAntiAlias(true);      //设置画笔是否使用抗锯齿
        myPaint.setDither(true);            //设置画笔是否防抖动
        myPaint.setStyle(Paint.Style.STROKE);        //设置画笔样式,这里使用描边
        
        myWhitePice = BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2); //设置棋子图片
        myBlackPice = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1);
                
    }
    
    //触发事件
    public boolean onTouchEvent(MotionEvent event){             
        if (isGemOver) {
            return false;
        }
        
        int action = event.getAction();
        if (action == MotionEvent.ACTION_UP) {   //判断触摸动作,ACTION_UP为单点触摸离开
            int x = (int) event.getX();
            int y = (int) event.getY();
            Point p = getVaLidPiont(x,y);
            
            if (myWhiteArray.contains(p)|| myBlackArray.contains(p)) {
                return false;
            }
            
            if (isWhite) {
                myWhiteArray.add(p);
            }else {
                myBlackArray.add(p);
            }
            invalidate();         //invalidate()是用来刷新View的,必须在UI线程中使用
            isWhite = !isWhite;
        }
        return true;
    }
    
    
    private Point getVaLidPiont(int x , int y){
        return new Point((int)(x/myLineHeight),(int)(y/myLineHeight));
    }
    
    //计算布局大小
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
        
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
        
        int width = Math.min(widthSize, heightSize);
        
        if (widthMode == MeasureSpec.UNSPECIFIED) {            //MeasureSpec.UNSPECIFIED表示未知大小
            width = heightSize;
        }else if (heightMode == MeasureSpec.UNSPECIFIED) {
            width = widthSize;
        }
        
        setMeasuredDimension(width, width);
        
    }
    
    protected void onSizeChanged(int w, int h ,int oldw , int oldh) {         //当View大小发生改变的时候会被系统自动回调
        super.onSizeChanged(w, h, oldw, oldh);
        myPanelWidth = w;
        myLineHeight = myPanelWidth*1.0f/maxLine;
         mUnder = h - (h - myPanelWidth) / 2;
        
        int pieceWidth = (int) (myLineHeight*ratioPieceOfLineHight);  //棋子大小占行宽的3/4
        myWhitePice = Bitmap.createScaledBitmap(myWhitePice, pieceWidth, pieceWidth, false);    //以src为原图,创建新的图像,指定新图像的高宽以及是否可变。
        myBlackPice = Bitmap.createScaledBitmap(myBlackPice, pieceWidth, pieceWidth, false);    
    }
    
    protected void  onDraw(Canvas canvas) {       //Canvas类相当于一块画布
        super.onDraw(canvas);
        drawBroad(canvas);
        drawPiece(canvas);
        checkGameOver();
    }
    
    private void drawBroad(Canvas canvas){            //画出棋盘线
        int w = myPanelWidth;
        float lineHeight = myLineHeight;
        int startX = (int) (lineHeight/2);            //棋盘线起始X坐标
        int endX = (int)(w-lineHeight/2);            //棋盘终止X坐标
        for(int i = 0; i< maxLine; i++){
            int y = (int)((i+1.5)*lineHeight);        //y坐标
            
            canvas.drawLine(startX, y, endX, y, myPaint);        //画棋盘横向线
            canvas.drawLine(y, startX, y, endX, myPaint);        //画棋盘纵向线
        }
    }
    
    //画棋子
    private void drawPiece(Canvas canvas) {        
        int n1 = myWhiteArray.size();
        int n2 = myBlackArray.size();
        for(int i =0; i< n1 ;i++){
            Point whitePoint = myWhiteArray.get(i);
            canvas.drawBitmap(myWhitePice, (whitePoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight, 
                    (whitePoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
                                    //drawBitmap(Bitmap bitmap, float left, float top, Paint paint);Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置
        }
        
        for(int i =0; i< n2 ;i++){
            Point blackPoint = myBlackArray.get(i);
            canvas.drawBitmap(myBlackPice, (blackPoint.x+(1-ratioPieceOfLineHight)/2)*myLineHeight, 
                    (blackPoint.y+(1-ratioPieceOfLineHight)/2)*myLineHeight, null);
        }
    }
    
    //检测游戏是否结束
    private void checkGameOver(){
        boolean whiteWin = checkFiveInLine(myWhiteArray);
        boolean blackWin = checkFiveInLine(myBlackArray);
        
        if (whiteWin || blackWin) {
            isGemOver = true;
               if (onGameListener != null) {
                    onGameListener.onGameOver(whiteWin ? WHITE_WIN : BLACK_WIN);
               }
        }
    }
    //回调一个int数据用于设置Dialog的位置
     public int getUnder() {

            return mUnder;
        }
    
     //检测是否存在五棋子相连的情况
    private boolean checkFiveInLine(List<Point> myArray){
        for(Point p : myArray){
            int x = p.x;
            int y = p.y;
            
            boolean win_flag =                             //判断是否存在五子相连情况
                    checkHorizontal(x , y ,myArray)||checkVertical(x,y,myArray)
                    ||checkLeftDiagonal(x,y,myArray)||checkRightDiagonal(x,y,myArray);
            if (win_flag) {
                return true;
            }
        }
        return false;
    }

    //横向检查是否满足五子相连
    private boolean checkHorizontal(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x+i,y))) {
                count++;
            }else {
                break;
            }
        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x-i,y))) {
                count++;
            }else {
                break;
            }
            

            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //纵向检查是否满足五子相连
    private boolean checkVertical(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x,y+i))) {
                count++;
            }else {
                break;
            }
            
        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x,y-i))) {
                count++;
            }else {
                break;
            }
            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //左斜向检查是否满足五子相连
    private boolean checkLeftDiagonal(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x-i,y+i))) {
                count++;
            }else {
                break;
            }

        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x+i,y-i))) {
                count++;
            }else {
                break;
            }
            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //右斜向检查是否满足五子相连
    private boolean checkRightDiagonal(int x ,int y ,List<Point> myArray){        
        int count = 1;
        for(int i = 1;i < 5; i++){            //切记,i = 1 开始,否则就会只检测到三个子相连就结束了
            if (myArray.contains(new Point(x-i,y-i))) {
                count++;
            }else {
                break;
            }
        }
        if (count == 5) {
            return true;
        }
        for(int i = 1;i < 5; i++){
            if (myArray.contains(new Point(x+i,y+i))) {
                count++;
            }else {
                break;
            }
            if (count == 5) {
                return true;
            }
        }
        return false;
    }
    
    //重新开始游戏
    protected void restartGame(){
        myWhiteArray.clear();
        myBlackArray.clear();
        isGemOver = false;
        isWhite = false;
        invalidate();
    }
}  

  终于,完成我们的自定义控件设计之后,我们就进入Activity的编写吧,代码如下:

public class MainActivity extends Activity {
    
    private Chess_Panel panel;
    private AlertDialog.Builder builder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        panel = (Chess_Panel)findViewById(R.id.main_panel);
        builder= new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("游戏结束");
        builder.setNegativeButton("退出", new OnClickListener() {
            
            @Override
            public void onClick(DialogInterface dialogInterface, int which) {
                MainActivity.this.finish();
            }
        });
        builder.setPositiveButton("再来一局", new OnClickListener() {
            
            @Override
            public void onClick(DialogInterface interface1, int which) {
                
                panel.restartGame();
            }
        });
        panel.setOnGameListener(new Chess_Panel.onGameListener() {
            
            @Override
            public void onGameOver(int i) {
                String str = "";
                if (i== Chess_Panel.WHITE_WIN) {
                    str = "白方胜利!";
                }else if (i== Chess_Panel.BLACK_WIN) {
                    str = "黑方胜利!";
                }
                builder.setMessage(str);
                builder.setCancelable(false);    //不可用返回键取消
                AlertDialog dialog = builder.create();
                Window dialogWindow = dialog.getWindow();
                WindowManager.LayoutParams params = new WindowManager.LayoutParams();
                params.x = 0;
                params.y = panel.getUnder();
                dialogWindow.setAttributes(params);    //设置Dialog显示的位置
                dialog.setCanceledOnTouchOutside(false);  //不可点击取消
                dialog.show();
            }
        } );
        
    }
}

 这两句的作用是让游戏满屏显示,即不显示通知状态栏:  
   Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  另外注意,不要忘记在activity_main.xml中添加我们自定义的控件,代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg"
    tools:context="com.example.fivechess.MainActivity" >

    <com.example.fivechess.Chess_Panel
        android:id="@+id/main_panel"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true" />

</RelativeLayout>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值