Android中国象棋自绘简单实现

中国象棋(引用自百度百科)

中国象棋是起源于中国的一种棋戏,属于二人对抗性游戏的一种,在中国有着悠久的历史。由于用具简单,趣味性强,成为流行极为广泛的棋艺活动。 中国象棋是中国棋文化也是中华民族的文化瑰宝,它源远流长,趣味浓厚,基本规则简明易懂,千百年来长盛不衰。中国象棋是模拟的古代战争、直线战争、陆地战争、平面战争。在中国古代,象棋被列为士大夫们的修身之艺。现在,则被视为是怡神益智的一种有益身心的活动。象棋集文化、科学、艺术、竞技于一身,不但可以开发智力,启迪思维,锻炼辨证分析能力和培养顽强的意志,而且可以修心养性,陶冶情操,丰富文化生活,深受广大群众的喜爱。古今中外男女老少皆宜,由于用具简单,趣味性强,大街小巷常常可见纹枰对弈的中国象棋爱好者。中国象棋使用方形格状棋盘及红黑二色圆形棋子进行对弈,棋盘上有十条横线、九条竖线共分成90个交叉点;中国象棋的棋子共有32个,每种颜色16个棋子,分为7个兵种,摆放和活动在交叉点上。双方交替行棋,先把对方的将(帅)“将死”的一方获胜(因为擒贼先擒王)。已有几千年历史、充满东方智慧的中国象棋在中国的群众中基础远远超过围棋,一直是普及最广的棋类项目。

前面bb的并不是本次讨论的重点,下面我们就装逼起飞。。。。。。。

首先我们还是来看下最后做出来的效果吧,一个只会堆代码的程序猿会让人很崩溃!!!!!!

或者你又想加点其他效果(这里对棋子加了辐射渐变效果)。。。。此处省略一万字。。。。。。然并卵,想要更好的效果就去找UI小姐姐或度娘吧。。。。。。

装逼完成了,,,,接下来我们来看下这个简单的页面如何用代码绘制出来。

我们做自定义控件是首先整理下逻辑,首先是继承问题我选择了 extends View  这样的话棋盘,棋子都是需要自己动手画的,更好练手。

整体思路:

1.绘制棋盘背景;

2.绘制棋局范围边框;

3.绘制棋盘网格(很简单);

4.绘制中心文字--楚河汉界

5.绘制炮-兵-卒特殊位置辅助线、将帅位置辅助线;

6.绘制棋子(背景+棋子文字);

7.最后就是走棋规则的处理,有效点击区域判断;

8.被将军的提示(这里应该是整个流程中最难的环节);

那么下面就分布实现:

信息解释:

private Paint linePaint;//画线的笔
private Paint qiPaint;//棋子文子画笔
private Paint qibackPaint;//棋子背景画笔
private int h;
private int w;
private int startX,startY;//起始绘制位置
private int defaultPadding=50;
private int hang = 9;//行
private int lie = 8; //列
private int space;
//存放所有位置信息 [X,Y,0,车] 依次对应 【x坐标、y坐标、红黑方、棋子】
private List<List<String>> allDatas=new ArrayList<>();
private List<List<String>> allDatasDefault=new ArrayList<>();
private List<List<List<String>>> back_datas=new ArrayList<>();//下棋落子记录,用于悔棋时调用
private boolean isInit=true;//是否第一次进来————初始化棋盘
private int step;//走棋步数  单数黑  双数红
//画棋盘
private int b_color=0xffF0F0F0;//棋盘背景
private final String back = "悔棋";
private final String reset = "复盘";
private final String per1 = "楚河";
private final String per2 = "汉界";
private final String[] chess1={"车","马","相","士","将"};
private final String[] chess1_d={"车","马","象","仕","帅"};

1.绘制棋盘背景;

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    initSetting();
    //绘制整个背景
    canvas.drawColor(b_color);
}

2.绘制棋局范围边框;

//绘制外边框
linePaint.setStrokeWidth((defaultPadding/2)*2/3);
canvas.drawRect(startX-defaultPadding/2,startY-defaultPadding/2,startX+space*8+defaultPadding/2,startY+space*9+defaultPadding/2,linePaint);

3.绘制棋盘网格(很简单);

//绘制网格
linePaint.setStrokeWidth(strokeWidth);
for (int i = 0; i <=hang ; i++) {
    canvas.drawLine(startX,startY+space*i,startX+space*8,startY+space*i,linePaint);

}
for (int i = 0; i <=lie ; i++) {
    canvas.drawLine(startX+space*i,startY,startX+space*i,startY+space*9,linePaint);
}

4.绘制中心文字--楚河汉界

//绘制楚河汉界区域
linePaint.setColor(b_color);
linePaint.setStyle(Paint.Style.FILL);
int left=startX+strokeWidth/2;
int top=startY+space*4+strokeWidth/2;
int right=startX+space*8-strokeWidth/2;
int bottom=startY+space*5-strokeWidth/2;
canvas.drawRect(left,top,right,bottom,linePaint);

//绘制文字楚河汉界
linePaint.setColor(0xffFFD39B);
linePaint.setTextSize(50);
linePaint.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.BOLD));
Rect rect = new Rect();
linePaint.getTextBounds(per2,0,per2.length(),rect);
int per_width = rect.width();
int per_height = rect.height();
canvas.drawText(per1,startX+space/2,(top+bottom)/2+per_height/2,linePaint);
canvas.drawText(per2,right-space/2-per_width,(top+bottom)/2+per_height/2,linePaint);
//绘制提示当前走棋方
linePaint.setTextSize(35);
String text;
if (currRole.equals("1")){
    linePaint.setColor(0xffff0000);
    text="红方走棋";
}else{
    linePaint.setColor(0xff000000);
    text="黑方走棋";
}
Rect rect1 = new Rect();
linePaint.getTextBounds(text,0,text.length(),rect1);
int per_width1 = rect1.width();
int per_height1 = rect1.height();
canvas.drawText(text,w/2-per_width1/2,(top+bottom)/2+per_height1/2,linePaint);

5.绘制炮-兵-卒特殊位置辅助线、将帅位置辅助线;

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //绘制辅助线---将帅斜线
    linePaint.setColor(lineColor);
    float [] dts = {
        startX+space*3,startY,startX+space*5,startY+space*2,
        startX+space*3,startY+space*2,startX+space*5,startY,
        startX+space*3,startY+space*7,startX+space*5,startY+space*9,
        startX+space*3,startY+space*9,startX+space*5,startY+space*7
    };
   canvas.drawLines(dts,linePaint);
   
    //绘制交点折线--炮-兵-卒
    for (int i = 0; i <=hang ; i++) {//获取Y值---行
    int y = startY+space*i;
        for (int j = 0; j <=lie; j++) {//获取X值---列
            int x = startX+space*j;
            if (i==2&&(j==1||j==7)){
                addlines(canvas,x,y,0);
            }
            if (i==7&&(j==1||j==7)){
                addlines(canvas,x,y,0);
            }
            if (i==3&&j%2==0){
                if (j==0){
                    addlines(canvas,x,y,2);
                }else if (j==8){
                    addlines(canvas,x,y,1);
                }else{
                    addlines(canvas,x,y,0);
                }
            }
            if (i==6&&j%2==0){
                if (j==0){
                    addlines(canvas,x,y,2);
                }else if (j==8){
                    addlines(canvas,x,y,1);
                }else{
                    addlines(canvas,x,y,0);
                }
            }
        }
    }
}

上面用到的addlines()方法如下:

    private int tPadding=10;//角落辅助线的间隔
    private int tlength=20;
    /**
     * 绘制特殊位置辅线---角落辅助线
     * @param canvas
     * @param x  交点x
     * @param y  交点y
     * @param type 1都有  1只有左边   2只有右边
     */
    private void addlines(Canvas canvas,int x,int y,int type) {
        Path path=new Path();
        //左上
        int sx;
        int sy;
        int sx1;
        int sy1;
        int sx2;
        int sy2;
        if (type==0||type==1){
            //左上
            sx= x-tPadding;
            sy = y-tPadding;

            sx1=sx-tlength;
            sy1=sy;

            sx2=sx;
            sy2=sy-tlength;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);

            //左下
            sx=x-tPadding;
            sy=y+tPadding;

            sx1=sx;
            sy1=sy+tlength;

            sx2=sx-tlength;
            sy2=sy;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);
        }
        if (type==0||type==2){
            //右上
            sx=x+tPadding;
            sy=y-tPadding;

            sx1=sx;
            sy1=sy-tlength;

            sx2=sx+tlength;
            sy2=sy;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);

            //右下
            sx= x+tPadding;
            sy = y+tPadding;

            sx1=sx;
            sy1=sy+tlength;

            sx2=sx+tlength;
            sy2=sy;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);

        }

        linePaint.setColor(lineColor);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(3);
        canvas.drawPath(path,linePaint);
    }

6.绘制棋子(背景+棋子文字);

 //画棋子
    private int radius=40;
    private boolean isFirst=true;
    @Override
    public void onDrawForeground(Canvas canvas) {
        super.onDrawForeground(canvas);
        Rect rect=new Rect();
        qiPaint.getTextBounds(chess1[0],0,1,rect);
        int per_width2 = rect.width();
        int per_height2 = rect.height();
        qiPaint.setTextSize(40);
        //获取棋盘上所有放置位置
        Log.e("棋盘大小111"," ---"+allDatas.size()+" ---" +allDatas.toString());
        //根据棋盘棋子位置变化更新棋盘
        for (int i = 0; i < allDatas.size(); i++) {
            if (allDatas.get(i).get(2).equals("1")){//表示红棋
                qiPaint.setColor(0xffff0000);
                //该自己走棋才改变棋子背景颜色
                if (i==currPosition &&currRole.equals("1")){
                    qibackPaint.setColor(selectColor);
                }else{
                    qibackPaint.setColor(redColor);
                }
                canvas.drawCircle(Float.valueOf(allDatas.get(i).get(0)),Float.valueOf(allDatas.get(i).get(1)),radius,qibackPaint);
                int x=Integer.valueOf(allDatas.get(i).get(0));
                int y=Integer.valueOf(allDatas.get(i).get(1));
                int lx= x-per_width2/2-strokeWidth;
                int ly= y+per_height2/2-strokeWidth;
                canvas.drawText(allDatas.get(i).get(3),lx,ly,qiPaint);
            }else if (allDatas.get(i).get(2).equals("2")){//表示黑棋--其他无棋位置不做处理
                qiPaint.setColor(0xff000000);
                //该自己走棋才改变棋子背景颜色
                if (i==currPosition&&currRole.equals("2")){
                    qibackPaint.setColor(selectColor);
                }else{
                    qibackPaint.setColor(blockColor);
                }
                canvas.drawCircle(Float.valueOf(allDatas.get(i).get(0)),Float.valueOf(allDatas.get(i).get(1)),radius,qibackPaint);
                int x=Integer.valueOf(allDatas.get(i).get(0));
                int y=Integer.valueOf(allDatas.get(i).get(1));
                int lx= x-per_width2/2-strokeWidth;
                int ly= y+per_height2/2-strokeWidth;
                canvas.drawText(allDatas.get(i).get(3),lx,ly,qiPaint);
            }
        }

        if (isFirst){
            isFirst=false;
            invalidate();
        }
    }

前面的绘制都是在onDraw(Canvas canvas)方法内绘制,这里绘制棋子我是在onDrawForeground(Canvas canvas)方法里面绘制的,不过你在onDraw(Canvas canvas)方法里里绘制也是可以的。记住,这里绘制的不仅是默认棋盘,后续棋局变化刷新后也是直行该代码来刷新棋盘的。根据allDatas内数据的变化。。。。。。。这里是重点,我们来理下里面的逻辑。

我们要理解存放模式,alldatas是存放所有棋盘位置的数据集合对象:

private List<List<String>> allDatas=new ArrayList<>();//每个位置信息包括四个元素 [X,Y,0,车] 依次对应 【x坐标、y坐标、红黑方、棋子】

//获取棋盘上所有放置位置---基础
        if (isInit){//---默认棋盘位置信息只需要执行一次
            isInit=false;
            allDatas.clear();
            for (int i = 0; i <=hang ; i++) {//获取Y值---行
                int y = startY+space*i;
                for (int j = 0; j <=lie; j++) {//获取X值---列

                    int x = startX+space*j;
                    List<String> data=new ArrayList<>();
                    data.add(x+"");
                    data.add(y+"");
                    if (i==0){
                        data.add("1");
                        data.add(chess1[j<=4?j%5:3-j%5]);//{"车","马","相","士","将"}
                    }else if (i==9){
                        data.add("2");
                        data.add(chess1_d[j<=4?j%5:3-j%5]);//{"车","马","象","仕","帅"}
                    }else if (i==2){
                        if (j==1||j==7){
                            data.add("1");
                            data.add("炮");
                            addlines(canvas,x,y,0);
                        }else{
                            data.add("");
                            data.add("");
                        }

                    }else if (i==7){
                        if (j==1||j==7){
                            data.add("2");
                            data.add("炮");
                            addlines(canvas,x,y,0);
                        }else{
                            data.add("");
                            data.add("");
                        }
                    }else if (i==3){
                        if (j%2==0){
                            data.add("1");
                            data.add("兵");
                            if (j==0){
                                addlines(canvas,x,y,2);
                            }else if (j==8){
                                addlines(canvas,x,y,1);
                            }else{
                                addlines(canvas,x,y,0);
                            }
                        }else{
                            data.add("");
                            data.add("");
                        }

                    }else if (i==6 ){
                        if (j%2==0){
                            data.add("2");
                            data.add("卒");
                            if (j==0){
                                addlines(canvas,x,y,2);
                            }else if (j==8){
                                addlines(canvas,x,y,1);
                            }else{
                                addlines(canvas,x,y,0);
                            }
                        }else{
                            data.add("");
                            data.add("");
                        }
                    }else{
                        data.add("");
                        data.add("");
                    }

                    allDatas.add(data);

                }
            }
            List<List<String>> temp=new ArrayList<>();
            for (int j = 0; j < allDatas.size(); j++) {
                List<String> temp1=new ArrayList<>();
                List<String> temp2=new ArrayList<>();
                for (int k = 0; k < allDatas.get(j).size(); k++) {
                    temp1.add(allDatas.get(j).get(k));
                    temp2.add(allDatas.get(j).get(k));
                }
                temp.add(temp1);
                allDatasDefault.add(temp2);
            }
            back_datas.add(temp);
        }

看了上面代码,你一定会很好奇,怎么还有一个temp呢,这个是用来做什么的,这不是画蛇添足吗,allDatasDefault和temp装了一样的数据,但是你会发现back_datas.add(temp);这句代码,  哇!!!!真牛逼!!!正如你所想,这是为悔棋做的准备,悔棋操作装的第一次数据啦。。。。。。。。这里先略过,不是重点,下面继续看!!!!!

7.最后就是走棋规则的处理,有效点击区域判断;

这里很重要的一步就是要确定棋盘上各个交叉点位置数据,因为我们后续的逻辑都是建立在棋子放置位置来进行的。首先需要获取棋盘的初始位置信息。这里只需要进行一次获取就行了,我们在onDraw(Canvas canvas)方法内做这个操作。说明:allDatasDefault是初始棋局保存的数据,聪明的你一定想到了一开始我们展示的gif中的复盘实现的数据基础。

走棋的有效区域即为棋盘内部--准确说应该是棋子所在位置可以响应的范围。比如棋子位置中心,棋子半径区域点击了为有效区域。往下看。。。。。。。。。。。

    private String currRole="1";//当前一轮走棋方  1 红方  2 黑方
    private int currPosition=-1;//当前一轮走棋方选中棋子  默认-1 未选中  其他表示选中位置   移动前位置
    private int currTouch=-1;//当前触摸位置   -----------------------------------------
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //触摸位置
        int cx=0;
        int cy=0;
        int x;
        int y;
        if (event.getAction()==MotionEvent.ACTION_DOWN){
            cx= (int) event.getX();
            cy= (int) event.getY();
            //有效触摸范围
            for (int i = 0; i <allDatas.size() ; i++) {
                x=Integer.valueOf(allDatas.get(i).get(0));
                y=Integer.valueOf(allDatas.get(i).get(1));
                if (cx>x-radius&& cx<x+radius && cy>y-radius &&cy<y+radius){ //有效点击区域
                    Log.e("点击了有效区域","======"+i);
                    currTouch=i;
                    //要区分事件---之前是否选中
                    if (currPosition==-1){//没选中任何棋子
                        Log.e("没棋子-","==");
                        //--当前点击区域是否有棋子
                        if (currRole.equals(allDatas.get(i).get(2))){//表示当前选中了自己的棋子
                            currPosition=i;
                            Log.e("没棋子-点了自己棋子","==");
                        }
                    }else{
                        Log.e("有棋子--","==");
                        //--当前点击区域是否有棋子
                        if (currRole.equals(allDatas.get(i).get(2))){//表示当前选中了自己的棋子
                            currPosition=i;
                            Log.e("有棋子--点了自己棋子","==");
                        }else{

                            Log.e("有棋子--判断走棋","==");
                            //这里有两种可能,一是有别人的棋子,一是无子
                            //这里做走棋规则判断是否可以落子--落子后清除状态  currTouch=-1,
                        }
                    }
                    invalidate();
                }
            }
        }
        return true;
    }

相信各位都能够看懂上面的操作都做了什么,没层代码解释得很清楚。前面做的一系列判断略过,我们在意最后一个else后面怎么操作,也就是点击/触摸事件有效。有效的点击/触摸事件可能分两种情况,一种情况是此处有棋子,另一种情况是此处没有棋子。(注:能走到这个else里面来都是已经选中了自己棋子,这里是落子的操作了,至于能不能在此处落子就要看你)----根据各个棋子的走棋规则来决定,如果满足,执行落子操作,不满足则忽略此次点击/触摸事件。

  • 1 兵、卒的走棋约束:
     /**
     * 1 兵的走棋约束
     * @return 是否有效走棋
     */
    public boolean bing(){
        int x;
        int y;
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            if (currRole.equals("1")){//红方
                if (y<startY+space*5){//在自己这边
                    if (y+space==Integer.valueOf(allDatas.get(currTouch).get(1)) && x==Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是兵直行
                        return true;
                    }else{
                        return false;
                    }
                }else{//已过河
                    if (y+space==Integer.valueOf(allDatas.get(currTouch).get(1)) && x==Integer.valueOf(allDatas.get(currTouch).get(0)) //这里是兵直行
                            ||y==Integer.valueOf(allDatas.get(currTouch).get(1)) && x+space==Integer.valueOf(allDatas.get(currTouch).get(0))//这里是右行
                            ||y==Integer.valueOf(allDatas.get(currTouch).get(1)) && x-space==Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是左行
                        return true;
                    }else{
                        return false;
                    }
                }
            }else{//黑方
                if (y>startY+space*4){//在自己这边
                    if (y-space==Integer.valueOf(allDatas.get(currTouch).get(1)) && x==Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是兵直行
                        return true;
                    }else{
                        return false;
                    }
                }else{//已过河
                    if (y-space==Integer.valueOf(allDatas.get(currTouch).get(1)) && x==Integer.valueOf(allDatas.get(currTouch).get(0)) //这里是兵直行
                            ||y==Integer.valueOf(allDatas.get(currTouch).get(1)) && x+space==Integer.valueOf(allDatas.get(currTouch).get(0))//这里是右行
                            ||y==Integer.valueOf(allDatas.get(currTouch).get(1)) && x-space==Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是左行
                        return true;
                    }else{
                        return false;
                    }
                }
            }

        }
        return false;
    }
  • 2 炮的走棋约束
    /**
     * 2 炮的走棋约束
     * @return 是否有效走棋
     */
    public boolean pao(){
        int x;
        int y;
        int lx;
        int ly;
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx=Integer.valueOf(allDatas.get(currTouch).get(0));
            ly=Integer.valueOf(allDatas.get(currTouch).get(1));

            if ((x!=lx && y!=ly) ||(x==lx&&y==ly)){//这种情况是无效的走棋
                return false;
            }

            if (y==ly){//横向
                int step_x =Math.abs( (lx-x)/space);//横向间隔步数
                if (Math.abs(step_x)==1){//只走一步
                    //判断终点有别人棋子就可以走,否则不能走
                    if (allDatas.get(currTouch).get(3).equals("")){
                        return true;
                    }else{
                        return false;
                    }
                }

                int count=0;//沒棋子时计数
                int count2=0;//有棋子时计数
                //中间没有棋子时
                for (int i = 1; i <step_x; i++) {
                    if (lx>x){//向右走棋
                        if (allDatas.get(currPosition+i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }else{//向左走棋时
                        if (allDatas.get(currPosition-i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }

                }

                if (allDatas.get(currTouch).get(3).equals("")){//中间无棋子,终点无棋子时可可以落子
                    if (count==step_x-1){
                        return true;
                    }else{
                        return false;
                    }
                }else{
                    if (count2==1){//中间有一颗棋子,终点为对方棋子时可以落子
                        //判断终点有别人棋子就可以走,否则不能走
                        if (allDatas.get(currTouch).get(2).equals(currRole)|| allDatas.get(currTouch).get(2).equals("")){
                            return false;
                        }else{
                            return true;
                        }
                    }else{
                        return false;
                    }

                }

            }else{//竖向
                int step_y = Math.abs((ly-y)/space);//竖向间隔步数
                if (Math.abs(step_y)==1){//间隔一步没棋子可以落子
                    if (allDatas.get(currTouch).get(3).equals("")){
                        return true;
                    }else{
                        return false;
                    }
                }

                int count=0;//沒棋子时计数
                int count2=0;//有棋子时计数
                //中间没有棋子时
                for (int i = 1; i <step_y; i++) {
                    if (ly>y){//向下走棋
                        if (allDatas.get(currPosition+9*i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }else{//向上走棋时
                        if (allDatas.get(currPosition-9*i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }

                }

                if (allDatas.get(currTouch).get(3).equals("")){//中间无棋子,终点无棋子时可可以落子
                    if (count==step_y-1){
                        return true;
                    }else{
                        return false;
                    }
                }else{
                    if (count2==1){//中间有一颗棋子,终点为对方棋子时可以落子
                        //判断终点有别人棋子就可以走,否则不能走
                        if (allDatas.get(currTouch).get(2).equals(currRole)|| allDatas.get(currTouch).get(2).equals("")){
                            return false;
                        }else{
                            return true;
                        }
                    }else{
                        return false;
                    }

                }
            }

        }
        return false;
    }
  • 3 车的走棋约束
    /**
     * 3 车的走棋约束
     * @return 是否有效走棋
     */
    public boolean che(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx=Integer.valueOf(allDatas.get(currTouch).get(0));
            ly=Integer.valueOf(allDatas.get(currTouch).get(1));

            if ((x!=lx && y!=ly) ||(x==lx&&y==ly)){//这种情况是无效的走棋
                return false;
            }

            Log.e("ttt22222","==");
            if (y==ly){//横向
                Log.e("ttt33333","==");
                int step_x =Math.abs( (lx-x)/space);
                if (Math.abs(step_x)==1){//只走一步
                    //判断终点有别人棋子就可以走,否则不能走
                    if (allDatas.get(currTouch).get(2).equals(currRole)){
                        Log.e("ttt44444","==");
                        return false;
                    }else{
                        Log.e("ttt5555","==");
                        return true;
                    }
                }

                int count=0;//沒棋子时计数
                for (int i = 1; i <step_x; i++) {
                    if (lx>x){//向右走棋
                        if (allDatas.get(currPosition+i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }else{//向左走棋时
                        if (allDatas.get(currPosition-i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }
                    if (i==step_x-1){//如果中间位置检查完毕
                        Log.e("ttt666666","==");
                        if(count==i){
                            //判断终点有别人棋子就可以走,否则不能走
                            if (!allDatas.get(currTouch).get(2).equals(currRole)){
                                Log.e("ttt88888","==");
                                return true;
                            }else{
                                Log.e("ttt999999","==");
                                return false;
                            }
                        }else{
                            Log.e("tttmmmm","==");
                            return false;//其他为有多子的情况
                        }
                    }
                }

            }else{//竖向
                Log.e("ttt33333","==");
                int step_y =Math.abs( (ly-y)/space);
                if (Math.abs(step_y)==1){//只走一步
                    //判断终点有别人棋子就可以走,否则不能走
                    if (allDatas.get(currTouch).get(2).equals(currRole)){
                        Log.e("ttt44444","==");
                        return false;
                    }else{
                        Log.e("ttt5555","==");
                        return true;
                    }
                }

                int count=0;//沒棋子时计数
                for (int i = 1; i <step_y; i++) {
                    if (ly>y){//向下走棋
                        if (allDatas.get(currPosition+9*i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }else{//向上走棋时
                        if (allDatas.get(currPosition-9*i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }
                    if (i==step_y-1){//如果中间位置检查完毕
                        Log.e("ttt666666","==");
                        if(count==i){
                            //判断终点有别人棋子就可以走,否则不能走
                            if (!allDatas.get(currTouch).get(2).equals(currRole)){
                                Log.e("ttt88888","==");
                                return true;
                            }else{
                                Log.e("ttt999999","==");
                                return false;
                            }
                        }else{
                            Log.e("tttmmmm","==");
                            return false;//其他为有多子的情况
                        }
                    }
                }
            }

        }
        return false;
    }
  • 4 马的走棋约束
    /**
     * 4 马的走棋约束
     * @return 是否有效走棋
     */
    public boolean ma(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx=Integer.valueOf(allDatas.get(currTouch).get(0));
            ly=Integer.valueOf(allDatas.get(currTouch).get(1));

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                return false;
            }else{

                if (Math.abs(ly-y)==2*space &&Math.abs(lx-x)==1*space){//上下方向
                    //上
                    if (ly-y<0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-9).get(3))){
                            return false;
                        }
                    }
                    if (ly-y>0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+9).get(3))){
                            return false;
                        }
                    }
                    return true;
                }else if (Math.abs(lx-x)==2*space&&Math.abs(ly-y)==1*space){//左右方向
                    //左
                    if (lx-x<0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-1).get(3))){
                            return false;
                        }
                    }
                    if (lx-x>0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+1).get(3))){
                            return false;
                        }
                    }
                    return true;
                }else{
                    return false;
                }
            }
        }
        return false;
    }
  • 5 象的走棋约束
     /**
     * 5 象的走棋约束
     * @return 是否有效走棋
     */
    public boolean xiang(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx=Integer.valueOf(allDatas.get(currTouch).get(0));
            ly=Integer.valueOf(allDatas.get(currTouch).get(1));

            //象不能过河限制
            if (allDatas.get(currPosition).get(3).equals("相")&& Integer.valueOf(allDatas.get(currTouch).get(1))>startY+4*space){
                return false;
            }
            if (allDatas.get(currPosition).get(3).equals("象")&& Integer.valueOf(allDatas.get(currTouch).get(1))<startY+5*space){
                return false;
            }

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                return false;
            }else{
                if (Math.abs(ly-y)==2*space &&Math.abs(lx-x)==2*space){//上下方向
                    //向上
                    if (ly-y<0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-9-1).get(3)) && currTouch<currPosition-2*9){//不能左飞
                            return false;
                        }
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-9+1).get(3))&& currTouch>currPosition-2*9){//不能右飞
                            return false;
                        }
                    }
                    //向下
                    if (ly-y>0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+9-1).get(3)) && currTouch<currPosition+2*9){//不能左飞
                            return false;
                        }
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+9+1).get(3))&& currTouch>currPosition+2*9){//不能右飞
                            return false;
                        }
                    }
                    return true;
                }else{
                    return false;
                }
            }
        }
        return false;
    }
  • 6 仕的走棋约束
    /**
     * 6 仕的走棋约束
     * @return 是否有效走棋
     */
    public boolean shi(){
        int x;
        int y;
        int lx;
        int ly;
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx=Integer.valueOf(allDatas.get(currTouch).get(0));
            ly=Integer.valueOf(allDatas.get(currTouch).get(1));

            //仕限制
            if (allDatas.get(currPosition).get(3).equals("士")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))>startY+2*space||
                    (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space || Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){

                Log.e("tttXXXX1","==");
                return false;
            }
            if (allDatas.get(currPosition).get(3).equals("仕")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))<startY+7*space||
                            (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space || Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){
                Log.e("tttXXXX2","==");
                return false;
            }

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                Log.e("tttXXXX3","==");
                return false;
            }else{
                if (Math.abs(ly-y)==1*space &&Math.abs(lx-x)==1*space){
                    Log.e("tttXXXX4","==");
                    return true;
                }else{
                    Log.e("tttXXXX5","==");
                    return false;
                }
            }
        }
        return false;
    }
  • 7 将帅的走棋约束
    /**
     * 7 将帅的走棋约束
     * @return 是否有效走棋
     */
    public boolean shuai(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x=Integer.valueOf(allDatas.get(currPosition).get(0));
            y=Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx=Integer.valueOf(allDatas.get(currTouch).get(0));
            ly=Integer.valueOf(allDatas.get(currTouch).get(1));

            //仕限制
            if (allDatas.get(currPosition).get(3).equals("将")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))>startY+2*space||
                            (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space ||Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){
                return false;
            }
            if (allDatas.get(currPosition).get(3).equals("帅")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))<startY+7*space||
                            (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space||Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){
                return false;
            }

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                return false;
            }else{
                if ((Math.abs(ly-y)==1*space &&Math.abs(lx-x)==0) ||(Math.abs(ly-y)==0 &&Math.abs(lx-x)==1*space)){
                    return true;
                }
            }


        }
        return false;
    }

上面的走棋约束有备注,聪明的大家只要理解了其中一个相信会举一反百吧,这里不再做过多无用解释。棒棒哒!!!!!!!

8.被将军的提示(这里应该是整个流程中最难的环节);

这个环节暂时还未实现,请多关注更新。。。。。。。^-^    ^-^   ^-^   ^-^   ^-^

列举了上面这么多的内容,说实话没,写到此处,手已经酸了,赶紧找个按摩店,,,,,走起!!!!!

不过貌似还有东邪还没有说完,555555,摸一摸包也确实没钱啦,可怜的代码仔还是老老实实地继续撸代码吧。。。。。

前面说到了复盘的操作,就是重置到初始状态呗。还难不到我。往下看。。。。。。。。。

    public void fupan(){
        currRole="1";
        currPosition=-1;
        currTouch=-1;
        allDatas.clear();
        for (int k = 0; k < allDatasDefault.size(); k++) {
            List<String> temp=new ArrayList<>();
            for (int i = 0; i <allDatasDefault.get(k).size() ; i++) {
                temp.add(allDatasDefault.get(k).get(i));
            }
            allDatas.add(temp);
        }
        invalidate();
    }

然后不是还有悔棋吗,继续撸。。。。。

   public void huiqi(){
        Log.e("huiqi",back_datas.size()+""+back_datas.toString());
        if (back_datas.size()>1){
            allDatas.clear();
            back_datas.remove(back_datas.size()-1);
            //遍历获取当前悔棋后棋子位置信息
            for (int k = 0; k < back_datas.get(back_datas.size()-1).size(); k++) {
                List<String> temp=new ArrayList<>();
                for (int i = 0; i <back_datas.get(back_datas.size()-1).get(k).size() ; i++) {
                    temp.add(back_datas.get(back_datas.size()-1).get(k).get(i));
                }
                allDatas.add(temp);
            }
            Log.e("huiqi=====",allDatas.toString());
            if (currRole.equals("1")){//重置当前走棋状态
                currRole="2";
                currPosition=-1;
                currTouch=-1;
            }else{
                currRole="1";
                currPosition=-1;
                currTouch=-1;
            }
            invalidate();
        }else{
            Toast.makeText(getContext(),"当前无法继续悔棋了",Toast.LENGTH_SHORT).show();
        }
    }

实现起来还是很简单的。

我们看下走棋约束、复盘、悔棋的调用时机是在onTouchEvent(MotionEvent event)中,源码:

    private String currRole="1";//当前一轮走棋方  1 红方  2 黑方
    private int currPosition=-1;//当前一轮走棋方选中棋子  默认-1 未选中  其他表示选中位置   移动前位置
    private int currTouch=-1;//当前触摸位置   -----------------------------------------
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //触摸位置
        int cx=0;
        int cy=0;
        int x;
        int y;
        if (event.getAction()==MotionEvent.ACTION_DOWN){
            cx= (int) event.getX();
            cy= (int) event.getY();
            //有效触摸范围
            for (int i = 0; i <allDatas.size() ; i++) {
                x=Integer.valueOf(allDatas.get(i).get(0));
                y=Integer.valueOf(allDatas.get(i).get(1));
                if (cx>x-radius&& cx<x+radius && cy>y-radius &&cy<y+radius){ //有效点击区域
                    Log.e("点击了有效区域","======"+i);
                    currTouch=i;
                    //要区分事件---之前是否选中
                    if (currPosition==-1){//没选中任何棋子
                        Log.e("没棋子-","==");
                        //--当前点击区域是否有棋子
                        if (currRole.equals(allDatas.get(i).get(2))){//表示当前选中了自己的棋子
                            currPosition=i;
                            Log.e("没棋子-点了自己棋子","==");
                        }
                    }else{
                        Log.e("有棋子--","==");
                        //--当前点击区域是否有棋子
                        if (currRole.equals(allDatas.get(i).get(2))){//表示当前选中了自己的棋子
                            currPosition=i;
                            Log.e("有棋子--点了自己棋子","==");
                        }else{

                            Log.e("有棋子--判断走棋","==");
                            //这里有两种可能,一是有别人的棋子,一是无子
                            //这里做走棋规则判断是否可以落子--落子后清除状态  currTouch=-1,

                            boolean result=false;
                            if (allDatas.get(currPosition).get(3).equals("兵")||allDatas.get(currPosition).get(3).equals("卒")){
                                result=bing();
                            }
                            //走炮的规则
                            if (allDatas.get(currPosition).get(3).equals("炮")){
                                result=pao();
                            }
                            if (allDatas.get(currPosition).get(3).equals("车")){
                                result=che();
                            }
                            if (allDatas.get(currPosition).get(3).equals("马")){
                                result=ma();
                            }
                            if (allDatas.get(currPosition).get(3).equals("象")||allDatas.get(currPosition).get(3).equals("相")){
                                result=xiang();
                            }
                            if (allDatas.get(currPosition).get(3).equals("仕")||allDatas.get(currPosition).get(3).equals("士")){
                                result=shi();
                            }
                            if (allDatas.get(currPosition).get(3).equals("将")||allDatas.get(currPosition).get(3).equals("帅")){
                                result=shuai();
                            }

                            if (result){
                                //if (meet()){
                                    step++;
                                    VibrateUtil.getInstance((Activity) getContext()).playRing();
                                    //更新棋子状态
                                    allDatas.get(i).set(2,allDatas.get(currPosition).get(2));
                                    allDatas.get(i).set(3,allDatas.get(currPosition).get(3));

                                    allDatas.get(currPosition).set(2,"");
                                    allDatas.get(currPosition).set(3,"");

                                    if (currRole.equals("1")){
                                        currRole="2";
                                    }else{
                                        currRole="1";
                                    }
                                    //这里做棋局结束的判断
                                    int countj =0;
                                    int counts =0;
                                    for (int j = 0; j <allDatas.size() ; j++) {
                                        if (allDatas.get(j).get(3).equals("将")){
                                            countj++;
                                        }
                                        if (allDatas.get(j).get(3).equals("帅")){
                                            counts++;
                                        }
                                    }
                                    if (countj==0){
                                        Toast.makeText(getContext(),"黑方胜利",Toast.LENGTH_LONG).show();
                                    }
                                    if (counts==0){
                                        Toast.makeText(getContext(),"红方胜利",Toast.LENGTH_LONG).show();
                                    }

                                    //走子成功后存入新棋盘
                                    if (back_datas.size()>5){
                                        back_datas.remove(0);
                                    }
                                    List<List<String>> temp=new ArrayList<>();
                                    for (int j = 0; j < allDatas.size(); j++) {
                                        List<String> temp1=new ArrayList<>();
                                        for (int k = 0; k < allDatas.get(j).size(); k++) {
                                            temp1.add(allDatas.get(j).get(k));
                                        }
                                        temp.add(temp1);
                                    }
                                    back_datas.add(temp);
                                    Log.e("huiqi----",back_datas.size()+"");
                                /*}else{
                                    Toast.makeText(getContext(),"将帅不能见面",Toast.LENGTH_SHORT).show();
                                }*/

                            }

                        }
                    }
                    invalidate();

                }


            }
            //点击了自绘的悔棋按钮
            if (cx>startX&& cx<startX+2*space && cy>tPadding &&cy<tPadding+space){
                huiqi();
            }

            //点击了自绘的悔棋按钮
            if (cx>startX+2*space&& cx<startX+2*space+2*space && cy>tPadding &&cy<tPadding+space){
                fupan();
            }
        }


        return true;
    }

 

在这里我们回顾下之前的坑,为什么要使用两个对象保存而不是直接赋值添加到集合。这是因为对象的指向问题,当你执行

allDatas.clear();
back_datas.remove(back_datas.size()-1);
allDatas.addAll(back_datas.get(back_datas.size()-1));

前面不遍历数据使用另外变量存储数据的话,后续引用的指向是同一个对象,就会使数据同时该变而一起被清空,执行allDatas.clear();后再添加拿到的数据就为空白数据。另外就是上面对象的复制是同过遍历实现,你如果觉得麻烦的话,可以将对象写到内存中(需要序列化请先序列化(Serializable), ), 然后再读出,也很简单。

 

至此,自绘的中国象棋就实现了。

下面贴上该空间全部源码

package com.goldvsspace.chinesechess;

import android.app.Activity;
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;

/**
 * email:1040152329@qq.com
 * Created by gold on 2019/10/30
 * Describe:
 **/
public class ChineseChessView extends View {
    private Paint linePaint;//画线的笔
    private Paint qiPaint;//棋子文子画笔
    private Paint qibackPaint;//棋子背景画笔
    private int lineColor=0xffEEDC82;
    private int redColor=0xffFFA54F;
    private int blockColor=0xff008B00;
    private int selectColor=0xff3A5FCD;
    public ChineseChessView(Context context) {
        this(context,null);

    }

    private int strokeWidth=5;
    private void initView() {
        linePaint=new Paint();
        qibackPaint=new Paint();
        qiPaint=new Paint();
        initSetting();
    }

    private void initSetting() {
        linePaint.setAntiAlias(true);
        linePaint.setColor(lineColor);
        linePaint.setStyle(Paint.Style.STROKE);

        qiPaint.setAntiAlias(true);
        qiPaint.setColor(lineColor);
        qiPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));

        qibackPaint.setColor(0xffEEDC82);
        qibackPaint.setStyle(Paint.Style.FILL);
        //qibackPaint.setMaskFilter(new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL));
        qibackPaint.setAntiAlias(true);
    }

    public ChineseChessView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ChineseChessView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private int h;
    private int w;
    private int startX,startY;//起始绘制位置
    private int defaultPadding=50;
    private int hang = 9;//行
    private int lie = 8; //列
    private int space;
    //存放所有位置信息 [X,Y,0,车] 依次对应 【x坐标、y坐标、红黑方、棋子】
    private List<List<String>> allDatas=new ArrayList<>();
    private List<List<String>> allDatasDefault=new ArrayList<>();
    private List<List<List<String>>> back_datas=new ArrayList<>();//下棋落子记录,用于悔棋时调用
    private boolean isInit=true;//是否第一次进来————初始化棋盘
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.h=h;
        this.w=w;
        int realWidth=w-defaultPadding*2;
        int realHeight=realWidth*9/8;
        space=realWidth/8;
        startX=defaultPadding;
        startY=(h-realHeight)/2;
    }

    //画棋盘
    private int b_color=0xffF0F0F0;//棋盘背景
    private final String back = "悔棋";
    private final String reset = "复盘";
    private final String per1 = "楚河";
    private final String per2 = "汉界";
    private final String[] chess1={"车","马","相","士","将"};
    private final String[] chess1_d={"车","马","象","仕","帅"};
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        initSetting();
        //绘制整个背景
        canvas.drawColor(b_color);
        //canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background),new Rect(0,0,w,h),new Rect(0,0,w,h),linePaint);

        //绘制外边框
        linePaint.setStrokeWidth((defaultPadding/2)*2/3);
        canvas.drawRect(startX-defaultPadding/2,startY-defaultPadding/2,startX+space*8+defaultPadding/2,startY+space*9+defaultPadding/2,linePaint);

        //绘制网格
        linePaint.setStrokeWidth(strokeWidth);
        for (int i = 0; i <=hang ; i++) {
            canvas.drawLine(startX,startY+space*i,startX+space*8,startY+space*i,linePaint);

        }
        for (int i = 0; i <=lie ; i++) {
            canvas.drawLine(startX+space*i,startY,startX+space*i,startY+space*9,linePaint);
        }
        //绘制楚河汉界区域
        linePaint.setColor(b_color);
        linePaint.setStyle(Paint.Style.FILL);
        int left=startX+strokeWidth/2;
        int top=startY+space*4+strokeWidth/2;
        int right=startX+space*8-strokeWidth/2;
        int bottom=startY+space*5-strokeWidth/2;
        canvas.drawRect(left,top,right,bottom,linePaint);

        //绘制文字楚河汉界
        linePaint.setColor(0xffFFD39B);
        linePaint.setTextSize(50);
        linePaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
        Rect rect = new Rect();
        linePaint.getTextBounds(per2,0,per2.length(),rect);
        int per_width = rect.width();
        int per_height = rect.height();
        canvas.drawText(per1,startX+space/2,(top+bottom)/2+per_height/2,linePaint);
        canvas.drawText(per2,right-space/2-per_width,(top+bottom)/2+per_height/2,linePaint);

        //绘制提示当前走棋方
        linePaint.setTextSize(35);
        String text;
        if (currRole.equals("1")){
            linePaint.setColor(0xffff0000);
            text="红方走棋";
        }else{
            linePaint.setColor(0xff000000);
            text="黑方走棋";
        }
        Rect rect1 = new Rect();
        linePaint.getTextBounds(text,0,text.length(),rect1);
        int per_width1 = rect1.width();
        int per_height1 = rect1.height();
        canvas.drawText(text,w/2-per_width1/2,(top+bottom)/2+per_height1/2,linePaint);


        //绘制辅助线---将帅斜线
        linePaint.setColor(lineColor);
        float [] dts = {
                startX+space*3,startY,startX+space*5,startY+space*2,
                startX+space*3,startY+space*2,startX+space*5,startY,
                startX+space*3,startY+space*7,startX+space*5,startY+space*9,
                startX+space*3,startY+space*9,startX+space*5,startY+space*7
        };
        canvas.drawLines(dts,linePaint);

        //获取棋盘上所有放置位置---基础
        if (isInit){
            isInit=false;
            allDatas.clear();
            for (int i = 0; i <=hang ; i++) {//获取Y值---行
                int y = startY+space*i;
                for (int j = 0; j <=lie; j++) {//获取X值---列

                    int x = startX+space*j;
                    List<String> data=new ArrayList<>();
                    data.add(x+"");
                    data.add(y+"");
                    if (i==0){
                        data.add("1");
                        data.add(chess1[j<=4?j%5:3-j%5]);//{"车","马","相","士","将"}
                    }else if (i==9){
                        data.add("2");
                        data.add(chess1_d[j<=4?j%5:3-j%5]);//{"车","马","象","仕","帅"}
                    }else if (i==2){
                        if (j==1||j==7){
                            data.add("1");
                            data.add("炮");
                            addlines(canvas,x,y,0);
                        }else{
                            data.add("");
                            data.add("");
                        }

                    }else if (i==7){
                        if (j==1||j==7){
                            data.add("2");
                            data.add("炮");
                            addlines(canvas,x,y,0);
                        }else{
                            data.add("");
                            data.add("");
                        }
                    }else if (i==3){
                        if (j%2==0){
                            data.add("1");
                            data.add("兵");
                            if (j==0){
                                addlines(canvas,x,y,2);
                            }else if (j==8){
                                addlines(canvas,x,y,1);
                            }else{
                                addlines(canvas,x,y,0);
                            }
                        }else{
                            data.add("");
                            data.add("");
                        }

                    }else if (i==6 ){
                        if (j%2==0){
                            data.add("2");
                            data.add("卒");
                            if (j==0){
                                addlines(canvas,x,y,2);
                            }else if (j==8){
                                addlines(canvas,x,y,1);
                            }else{
                                addlines(canvas,x,y,0);
                            }
                        }else{
                            data.add("");
                            data.add("");
                        }
                    }else{
                        data.add("");
                        data.add("");
                    }

                    allDatas.add(data);

                }
            }
            List<List<String>> temp=new ArrayList<>();
            for (int j = 0; j < allDatas.size(); j++) {
                List<String> temp1=new ArrayList<>();
                List<String> temp2=new ArrayList<>();
                for (int k = 0; k < allDatas.get(j).size(); k++) {
                    temp1.add(allDatas.get(j).get(k));
                    temp2.add(allDatas.get(j).get(k));
                }
                temp.add(temp1);
                allDatasDefault.add(temp2);
            }
            back_datas.add(temp);
        }
        //绘制交点折线
        for (int i = 0; i <=hang ; i++) {//获取Y值---行
            int y = startY+space*i;
            for (int j = 0; j <=lie; j++) {//获取X值---列
                int x = startX+space*j;
                if (i==2&&(j==1||j==7)){
                    addlines(canvas,x,y,0);
                }
                if (i==7&&(j==1||j==7)){
                    addlines(canvas,x,y,0);
                }
                if (i==3&&j%2==0){
                    if (j==0){
                        addlines(canvas,x,y,2);
                    }else if (j==8){
                        addlines(canvas,x,y,1);
                    }else{
                        addlines(canvas,x,y,0);
                    }
                }
                if (i==6&&j%2==0){
                    if (j==0){
                        addlines(canvas,x,y,2);
                    }else if (j==8){
                        addlines(canvas,x,y,1);
                    }else{
                        addlines(canvas,x,y,0);
                    }
                }
            }
        }

        //绘制悔棋按钮
        linePaint.setStyle(Paint.Style.FILL);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            linePaint.setColor(lineColor);
            Rect rect3=new Rect();
            linePaint.getTextBounds(back,0,back.length(),rect3);
            int h_width = rect3.width();
            int h_height = rect3.height();
            canvas.drawRoundRect(startX,tPadding,startX+2*space,tPadding+space,30,30,linePaint);
            linePaint.setColor(blockColor);
            canvas.drawText(back,startX+space-h_width/2,tPadding+space/2+h_height/2,linePaint);
        }
        //绘制复盘按钮
        linePaint.setStyle(Paint.Style.FILL);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            linePaint.setColor(lineColor);
            Rect rect3=new Rect();
            linePaint.getTextBounds(reset,0,reset.length(),rect3);
            int h_width = rect3.width();
            int h_height = rect3.height();
            canvas.drawRoundRect(startX+2*space,tPadding,startX+2*space+2*space,tPadding+space,30,30,linePaint);
            linePaint.setColor(blockColor);
            canvas.drawText(reset,startX+2*space+2*space/2-h_width/2,tPadding+space/2+h_height/2,linePaint);
        }

    }

    private int tPadding=10;//角落辅助线的间隔
    private int tlength=20;
    /**
     * 绘制特殊位置辅线---角落辅助线
     * @param canvas
     * @param x  交点x
     * @param y  交点y
     * @param type 1都有  1只有左边   2只有右边
     */
    private void addlines(Canvas canvas, int x, int y, int type) {
        Path path=new Path();
        //左上
        int sx;
        int sy;
        int sx1;
        int sy1;
        int sx2;
        int sy2;
        if (type==0||type==1){
            //左上
            sx= x-tPadding;
            sy = y-tPadding;

            sx1=sx-tlength;
            sy1=sy;

            sx2=sx;
            sy2=sy-tlength;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);

            //左下
            sx=x-tPadding;
            sy=y+tPadding;

            sx1=sx;
            sy1=sy+tlength;

            sx2=sx-tlength;
            sy2=sy;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);
        }
        if (type==0||type==2){
            //右上
            sx=x+tPadding;
            sy=y-tPadding;

            sx1=sx;
            sy1=sy-tlength;

            sx2=sx+tlength;
            sy2=sy;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);

            //右下
            sx= x+tPadding;
            sy = y+tPadding;

            sx1=sx;
            sy1=sy+tlength;

            sx2=sx+tlength;
            sy2=sy;
            path.moveTo(sx1,sy1);
            path.lineTo(sx,sy);
            path.lineTo(sx2,sy2);

        }

        linePaint.setColor(lineColor);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(3);
        canvas.drawPath(path,linePaint);
    }

    //画棋子
    private int radius=40;
    private boolean isFirst=true;
    @Override
    public void onDrawForeground(Canvas canvas) {
        super.onDrawForeground(canvas);
        Rect rect=new Rect();
        qiPaint.getTextBounds(chess1[0],0,1,rect);
        int per_width2 = rect.width();
        int per_height2 = rect.height();
        qiPaint.setTextSize(40);
        //获取棋盘上所有放置位置
        Log.e("棋盘大小111"," ---"+allDatas.size()+" ---" +allDatas.toString());
        //根据棋盘棋子位置变化更新棋盘
        for (int i = 0; i < allDatas.size(); i++) {
            if (allDatas.get(i).get(2).equals("1")){//表示红棋
                qiPaint.setColor(0xffff0000);
                //该自己走棋才改变棋子背景颜色
                if (i==currPosition &&currRole.equals("1")){
                    qibackPaint.setColor(selectColor);
                }else{
                    qibackPaint.setColor(redColor);
                }
                canvas.drawCircle(Float.valueOf(allDatas.get(i).get(0)), Float.valueOf(allDatas.get(i).get(1)),radius,qibackPaint);
                int x= Integer.valueOf(allDatas.get(i).get(0));
                int y= Integer.valueOf(allDatas.get(i).get(1));
                int lx= x-per_width2/2-strokeWidth;
                int ly= y+per_height2/2-strokeWidth;
                canvas.drawText(allDatas.get(i).get(3),lx,ly,qiPaint);
            }else if (allDatas.get(i).get(2).equals("2")){//表示黑棋--其他无棋位置不做处理
                qiPaint.setColor(0xff000000);
                //该自己走棋才改变棋子背景颜色
                if (i==currPosition&&currRole.equals("2")){
                    qibackPaint.setColor(selectColor);
                }else{
                    qibackPaint.setColor(blockColor);
                }
                canvas.drawCircle(Float.valueOf(allDatas.get(i).get(0)), Float.valueOf(allDatas.get(i).get(1)),radius,qibackPaint);
                int x= Integer.valueOf(allDatas.get(i).get(0));
                int y= Integer.valueOf(allDatas.get(i).get(1));
                int lx= x-per_width2/2-strokeWidth;
                int ly= y+per_height2/2-strokeWidth;
                canvas.drawText(allDatas.get(i).get(3),lx,ly,qiPaint);
            }
        }

        if (isFirst){
            isFirst=false;
            invalidate();
        }
    }

    private String currRole="1";//当前一轮走棋方  1 红方  2 黑方
    private int currPosition=-1;//当前一轮走棋方选中棋子  默认-1 未选中  其他表示选中位置   移动前位置
    private int currTouch=-1;//当前触摸位置   -----------------------------------------
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //触摸位置
        int cx=0;
        int cy=0;
        int x;
        int y;
        if (event.getAction()== MotionEvent.ACTION_DOWN){
            cx= (int) event.getX();
            cy= (int) event.getY();
            //有效触摸范围
            for (int i = 0; i <allDatas.size() ; i++) {
                x= Integer.valueOf(allDatas.get(i).get(0));
                y= Integer.valueOf(allDatas.get(i).get(1));
                if (cx>x-radius&& cx<x+radius && cy>y-radius &&cy<y+radius){ //有效点击区域
                    Log.e("点击了有效区域","======"+i);
                    currTouch=i;
                    //要区分事件---之前是否选中
                    if (currPosition==-1){//没选中任何棋子
                        Log.e("没棋子-","==");
                        //--当前点击区域是否有棋子
                        if (currRole.equals(allDatas.get(i).get(2))){//表示当前选中了自己的棋子
                            currPosition=i;
                            Log.e("没棋子-点了自己棋子","==");
                        }
                    }else{
                        Log.e("有棋子--","==");
                        //--当前点击区域是否有棋子
                        if (currRole.equals(allDatas.get(i).get(2))){//表示当前选中了自己的棋子
                            currPosition=i;
                            Log.e("有棋子--点了自己棋子","==");
                        }else{

                            Log.e("有棋子--判断走棋","==");
                            //这里有两种可能,一是有别人的棋子,一是无子
                            //这里做走棋规则判断是否可以落子--落子后清除状态  currTouch=-1,

                            boolean result=false;
                            if (allDatas.get(currPosition).get(3).equals("兵")||allDatas.get(currPosition).get(3).equals("卒")){
                                result=bing();
                            }
                            //走炮的规则
                            if (allDatas.get(currPosition).get(3).equals("炮")){
                                result=pao();
                            }
                            if (allDatas.get(currPosition).get(3).equals("车")){
                                result=che();
                            }
                            if (allDatas.get(currPosition).get(3).equals("马")){
                                result=ma();
                            }
                            if (allDatas.get(currPosition).get(3).equals("象")||allDatas.get(currPosition).get(3).equals("相")){
                                result=xiang();
                            }
                            if (allDatas.get(currPosition).get(3).equals("仕")||allDatas.get(currPosition).get(3).equals("士")){
                                result=shi();
                            }
                            if (allDatas.get(currPosition).get(3).equals("将")||allDatas.get(currPosition).get(3).equals("帅")){
                                result=shuai();
                            }

                            if (result){
                                //if (meet()){
                                    VibrateUtil.getInstance((Activity) getContext()).playRing();
                                    //更新棋子状态
                                    allDatas.get(i).set(2,allDatas.get(currPosition).get(2));
                                    allDatas.get(i).set(3,allDatas.get(currPosition).get(3));

                                    allDatas.get(currPosition).set(2,"");
                                    allDatas.get(currPosition).set(3,"");

                                    if (currRole.equals("1")){
                                        currRole="2";
                                    }else{
                                        currRole="1";
                                    }
                                    //这里做棋局结束的判断
                                    int countj =0;
                                    int counts =0;
                                    for (int j = 0; j <allDatas.size() ; j++) {
                                        if (allDatas.get(j).get(3).equals("将")){
                                            countj++;
                                        }
                                        if (allDatas.get(j).get(3).equals("帅")){
                                            counts++;
                                        }
                                    }
                                    if (countj==0){
                                        Toast.makeText(getContext(),"黑方胜利", Toast.LENGTH_LONG).show();
                                    }
                                    if (counts==0){
                                        Toast.makeText(getContext(),"红方胜利", Toast.LENGTH_LONG).show();
                                    }

                                    //走子成功后存入新棋盘
                                    List<List<String>> temp=new ArrayList<>();
                                    for (int j = 0; j < allDatas.size(); j++) {
                                        List<String> temp1=new ArrayList<>();
                                        for (int k = 0; k < allDatas.get(j).size(); k++) {
                                            temp1.add(allDatas.get(j).get(k));
                                        }
                                        temp.add(temp1);
                                    }
                                    back_datas.add(temp);
                                    Log.e("huiqi----",back_datas.size()+"");
                                /*}else{
                                    Toast.makeText(getContext(),"将帅不能见面",Toast.LENGTH_SHORT).show();
                                }*/

                            }

                        }
                    }
                    invalidate();

                }


            }
            //点击了自绘的悔棋按钮
            if (cx>startX&& cx<startX+2*space && cy>tPadding &&cy<tPadding+space){
                huiqi();
            }

            //点击了自绘的悔棋按钮
            if (cx>startX+2*space&& cx<startX+2*space+2*space && cy>tPadding &&cy<tPadding+space){
                fupan();
            }
        }


        return true;
    }

    //========================================************************下面约定走棋规则*********************=============================================

    /**
     * 1 兵的走棋约束
     * @return 是否有效走棋
     */
    public boolean bing(){
        int x;
        int y;
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            if (currRole.equals("1")){//红方
                if (y<startY+space*5){//在自己这边
                    if (y+space== Integer.valueOf(allDatas.get(currTouch).get(1)) && x== Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是兵直行
                        return true;
                    }else{
                        return false;
                    }
                }else{//已过河
                    if (y+space== Integer.valueOf(allDatas.get(currTouch).get(1)) && x== Integer.valueOf(allDatas.get(currTouch).get(0)) //这里是兵直行
                            ||y== Integer.valueOf(allDatas.get(currTouch).get(1)) && x+space== Integer.valueOf(allDatas.get(currTouch).get(0))//这里是右行
                            ||y== Integer.valueOf(allDatas.get(currTouch).get(1)) && x-space== Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是左行
                        return true;
                    }else{
                        return false;
                    }
                }
            }else{//黑方
                if (y>startY+space*4){//在自己这边
                    if (y-space== Integer.valueOf(allDatas.get(currTouch).get(1)) && x== Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是兵直行
                        return true;
                    }else{
                        return false;
                    }
                }else{//已过河
                    if (y-space== Integer.valueOf(allDatas.get(currTouch).get(1)) && x== Integer.valueOf(allDatas.get(currTouch).get(0)) //这里是兵直行
                            ||y== Integer.valueOf(allDatas.get(currTouch).get(1)) && x+space== Integer.valueOf(allDatas.get(currTouch).get(0))//这里是右行
                            ||y== Integer.valueOf(allDatas.get(currTouch).get(1)) && x-space== Integer.valueOf(allDatas.get(currTouch).get(0))){//这里是左行
                        return true;
                    }else{
                        return false;
                    }
                }
            }

        }
        return false;
    }

    /**
     * 2 炮的走棋约束
     * @return 是否有效走棋
     */
    public boolean pao(){
        int x;
        int y;
        int lx;
        int ly;
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx= Integer.valueOf(allDatas.get(currTouch).get(0));
            ly= Integer.valueOf(allDatas.get(currTouch).get(1));

            if ((x!=lx && y!=ly) ||(x==lx&&y==ly)){//这种情况是无效的走棋
                return false;
            }

            if (y==ly){//横向
                int step_x = Math.abs( (lx-x)/space);//横向间隔步数
                if (Math.abs(step_x)==1){//只走一步
                    //判断终点有别人棋子就可以走,否则不能走
                    if (allDatas.get(currTouch).get(3).equals("")){
                        return true;
                    }else{
                        return false;
                    }
                }

                int count=0;//沒棋子时计数
                int count2=0;//有棋子时计数
                //中间没有棋子时
                for (int i = 1; i <step_x; i++) {
                    if (lx>x){//向右走棋
                        if (allDatas.get(currPosition+i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }else{//向左走棋时
                        if (allDatas.get(currPosition-i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }

                }

                if (allDatas.get(currTouch).get(3).equals("")){//中间无棋子,终点无棋子时可可以落子
                    if (count==step_x-1){
                        return true;
                    }else{
                        return false;
                    }
                }else{
                    if (count2==1){//中间有一颗棋子,终点为对方棋子时可以落子
                        //判断终点有别人棋子就可以走,否则不能走
                        if (allDatas.get(currTouch).get(2).equals(currRole)|| allDatas.get(currTouch).get(2).equals("")){
                            return false;
                        }else{
                            return true;
                        }
                    }else{
                        return false;
                    }

                }

            }else{//竖向
                int step_y = Math.abs((ly-y)/space);//竖向间隔步数
                if (Math.abs(step_y)==1){//间隔一步没棋子可以落子
                    if (allDatas.get(currTouch).get(3).equals("")){
                        return true;
                    }else{
                        return false;
                    }
                }

                int count=0;//沒棋子时计数
                int count2=0;//有棋子时计数
                //中间没有棋子时
                for (int i = 1; i <step_y; i++) {
                    if (ly>y){//向下走棋
                        if (allDatas.get(currPosition+9*i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }else{//向上走棋时
                        if (allDatas.get(currPosition-9*i).get(3).equals("")){
                            count++;
                        }else{
                            count2++;
                        }
                    }

                }

                if (allDatas.get(currTouch).get(3).equals("")){//中间无棋子,终点无棋子时可可以落子
                    if (count==step_y-1){
                        return true;
                    }else{
                        return false;
                    }
                }else{
                    if (count2==1){//中间有一颗棋子,终点为对方棋子时可以落子
                        //判断终点有别人棋子就可以走,否则不能走
                        if (allDatas.get(currTouch).get(2).equals(currRole)|| allDatas.get(currTouch).get(2).equals("")){
                            return false;
                        }else{
                            return true;
                        }
                    }else{
                        return false;
                    }

                }
            }

        }
        return false;
    }

    /**
     * 3 车的走棋约束
     * @return 是否有效走棋
     */
    public boolean che(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx= Integer.valueOf(allDatas.get(currTouch).get(0));
            ly= Integer.valueOf(allDatas.get(currTouch).get(1));

            if ((x!=lx && y!=ly) ||(x==lx&&y==ly)){//这种情况是无效的走棋
                return false;
            }

            Log.e("ttt22222","==");
            if (y==ly){//横向
                Log.e("ttt33333","==");
                int step_x = Math.abs( (lx-x)/space);
                if (Math.abs(step_x)==1){//只走一步
                    //判断终点有别人棋子就可以走,否则不能走
                    if (allDatas.get(currTouch).get(2).equals(currRole)){
                        Log.e("ttt44444","==");
                        return false;
                    }else{
                        Log.e("ttt5555","==");
                        return true;
                    }
                }

                int count=0;//沒棋子时计数
                for (int i = 1; i <step_x; i++) {
                    if (lx>x){//向右走棋
                        if (allDatas.get(currPosition+i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }else{//向左走棋时
                        if (allDatas.get(currPosition-i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }
                    if (i==step_x-1){//如果中间位置检查完毕
                        Log.e("ttt666666","==");
                        if(count==i){
                            //判断终点有别人棋子就可以走,否则不能走
                            if (!allDatas.get(currTouch).get(2).equals(currRole)){
                                Log.e("ttt88888","==");
                                return true;
                            }else{
                                Log.e("ttt999999","==");
                                return false;
                            }
                        }else{
                            Log.e("tttmmmm","==");
                            return false;//其他为有多子的情况
                        }
                    }
                }

            }else{//竖向
                Log.e("ttt33333","==");
                int step_y = Math.abs( (ly-y)/space);
                if (Math.abs(step_y)==1){//只走一步
                    //判断终点有别人棋子就可以走,否则不能走
                    if (allDatas.get(currTouch).get(2).equals(currRole)){
                        Log.e("ttt44444","==");
                        return false;
                    }else{
                        Log.e("ttt5555","==");
                        return true;
                    }
                }

                int count=0;//沒棋子时计数
                for (int i = 1; i <step_y; i++) {
                    if (ly>y){//向下走棋
                        if (allDatas.get(currPosition+9*i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }else{//向上走棋时
                        if (allDatas.get(currPosition-9*i).get(3).equals("")){
                            count++;
                        }else{
                            return false;
                        }
                    }
                    if (i==step_y-1){//如果中间位置检查完毕
                        Log.e("ttt666666","==");
                        if(count==i){
                            //判断终点有别人棋子就可以走,否则不能走
                            if (!allDatas.get(currTouch).get(2).equals(currRole)){
                                Log.e("ttt88888","==");
                                return true;
                            }else{
                                Log.e("ttt999999","==");
                                return false;
                            }
                        }else{
                            Log.e("tttmmmm","==");
                            return false;//其他为有多子的情况
                        }
                    }
                }
            }

        }
        return false;
    }

    /**
     * 4 马的走棋约束
     * @return 是否有效走棋
     */
    public boolean ma(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx= Integer.valueOf(allDatas.get(currTouch).get(0));
            ly= Integer.valueOf(allDatas.get(currTouch).get(1));

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                return false;
            }else{

                if (Math.abs(ly-y)==2*space && Math.abs(lx-x)==1*space){//上下方向
                    //上
                    if (ly-y<0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-9).get(3))){
                            return false;
                        }
                    }
                    if (ly-y>0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+9).get(3))){
                            return false;
                        }
                    }
                    return true;
                }else if (Math.abs(lx-x)==2*space&& Math.abs(ly-y)==1*space){//左右方向
                    //左
                    if (lx-x<0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-1).get(3))){
                            return false;
                        }
                    }
                    if (lx-x>0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+1).get(3))){
                            return false;
                        }
                    }
                    return true;
                }else{
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * 5 象的走棋约束
     * @return 是否有效走棋
     */
    public boolean xiang(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx= Integer.valueOf(allDatas.get(currTouch).get(0));
            ly= Integer.valueOf(allDatas.get(currTouch).get(1));

            //象不能过河限制
            if (allDatas.get(currPosition).get(3).equals("相")&& Integer.valueOf(allDatas.get(currTouch).get(1))>startY+4*space){
                return false;
            }
            if (allDatas.get(currPosition).get(3).equals("象")&& Integer.valueOf(allDatas.get(currTouch).get(1))<startY+5*space){
                return false;
            }

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                return false;
            }else{
                if (Math.abs(ly-y)==2*space && Math.abs(lx-x)==2*space){//上下方向
                    //向上
                    if (ly-y<0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-9-1).get(3)) && currTouch<currPosition-2*9){//不能左飞
                            return false;
                        }
                        if (!TextUtils.isEmpty(allDatas.get(currPosition-9+1).get(3))&& currTouch>currPosition-2*9){//不能右飞
                            return false;
                        }
                    }
                    //向下
                    if (ly-y>0){
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+9-1).get(3)) && currTouch<currPosition+2*9){//不能左飞
                            return false;
                        }
                        if (!TextUtils.isEmpty(allDatas.get(currPosition+9+1).get(3))&& currTouch>currPosition+2*9){//不能右飞
                            return false;
                        }
                    }
                    return true;
                }else{
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * 6 仕的走棋约束
     * @return 是否有效走棋
     */
    public boolean shi(){
        int x;
        int y;
        int lx;
        int ly;
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx= Integer.valueOf(allDatas.get(currTouch).get(0));
            ly= Integer.valueOf(allDatas.get(currTouch).get(1));

            //仕限制
            if (allDatas.get(currPosition).get(3).equals("士")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))>startY+2*space||
                    (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space || Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){

                Log.e("tttXXXX1","==");
                return false;
            }
            if (allDatas.get(currPosition).get(3).equals("仕")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))<startY+7*space||
                            (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space || Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){
                Log.e("tttXXXX2","==");
                return false;
            }

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                Log.e("tttXXXX3","==");
                return false;
            }else{
                if (Math.abs(ly-y)==1*space && Math.abs(lx-x)==1*space){
                    Log.e("tttXXXX4","==");
                    return true;
                }else{
                    Log.e("tttXXXX5","==");
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * 7 将帅的走棋约束
     * @return 是否有效走棋
     */
    public boolean shuai(){
        int x;
        int y;
        int lx;
        int ly;
        Log.e("ttt11111","==");
        if (currPosition!=-1){
            //选中棋子位置
            x= Integer.valueOf(allDatas.get(currPosition).get(0));
            y= Integer.valueOf(allDatas.get(currPosition).get(1));
            //要走的位置
            lx= Integer.valueOf(allDatas.get(currTouch).get(0));
            ly= Integer.valueOf(allDatas.get(currTouch).get(1));

            //仕限制
            if (allDatas.get(currPosition).get(3).equals("将")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))>startY+2*space||
                            (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space || Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){
                return false;
            }
            if (allDatas.get(currPosition).get(3).equals("帅")&&
                    (Integer.valueOf(allDatas.get(currTouch).get(1))<startY+7*space||
                            (Integer.valueOf(allDatas.get(currTouch).get(0))<startX+3*space|| Integer.valueOf(allDatas.get(currTouch).get(0))>startX+5*space))){
                return false;
            }

            if (allDatas.get(currTouch).get(2).equals(currRole)){//如果是自己的棋就不能走
                return false;
            }else{
                if ((Math.abs(ly-y)==1*space && Math.abs(lx-x)==0) ||(Math.abs(ly-y)==0 && Math.abs(lx-x)==1*space)){
                    return true;
                }
            }


        }
        return false;
    }

    /**
     * 8 将帅不能见面的走棋约束  true会   false不会
     * @return 是否有效走棋
     */
    public boolean meet() {
        if (currPosition != -1) {
            int j_position = 0;//将的位置
            int s_position = 0;//帅的位置
            for (int i = 0; i < allDatas.size(); i++) {
                if (allDatas.get(i).get(3).equals("将")) {
                    j_position = i;
                } else if (allDatas.get(i).get(3).equals("帅")) {
                    s_position = i;
                }
            }

            int count = 0;//将帅直线中间有多少个棋子
            Log.e("ffff-------------", "==" + allDatas.toString());
            if (j_position % 9 == s_position % 9) {//将帅在同一直线上时---中间只有一个棋子不能移动
                for (int i = (j_position/9)+1; i < s_position / 9; i++) {
                    if (!TextUtils.isEmpty(allDatas.get(i * 9 + j_position).get(3))) {
                        Log.e("ffff-------------", allDatas.get(i * 9 + j_position).get(3)+"==" + count);
                        count++;
                    }
                }
                Log.e("ffff---------11----", "==" + count);
                if (count == 1) {
                    Log.e("ffff-------22------", (currPosition % 9 == j_position % 9) +""+ (currTouch != j_position % 9) +(currPosition>j_position)+(currPosition<s_position)+"==" + count);
                    if (currPosition % 9 == j_position % 9 && currTouch%9 != j_position % 9 &&currPosition>j_position&&currPosition<s_position) {//只有一棋走开
                        Log.e("ffff-------333------", "==" + count);
                        return false;
                    }
                }
            }else{

                Log.e("ffff------44-------", "==" + count);
                if (Math.abs(j_position%9-s_position%9)==1){//将帅所在直线相邻--中间无棋子不能移动见面
                   Log.e("ffff-----66--------", "==" + count);
                   if (allDatas.get(currPosition).get(3).equals("将")){
                       Log.e("ffff------77-------", "==" + count);
                       if (currTouch%9==s_position%9 && (currTouch==j_position+1||currTouch==j_position-1)){
                           for (int i = currTouch/9+1; i < s_position / 9; i++) {
                                if (!TextUtils.isEmpty(allDatas.get(s_position-i * 9 ).get(3))) {
                                    Log.e("ffff-------------", allDatas.get(s_position-i * 9).get(3)+"==" + count);
                                    count++;
                                }
                            }
                           if (count==0){
                               Log.e("ffff-----88--------", "==" + count);
                               return false;
                           }

                       }
                   }

                    if (allDatas.get(currPosition).get(3).equals("帅")){
                        Log.e("ffff------99-------", "==" + count);
                        if (currTouch%9==j_position%9&&(currTouch==s_position+1||currTouch==s_position-1)){//帅是在左右移动一步时
                            for (int i = j_position/9+1; i < currTouch / 9; i++) {
                                if (!TextUtils.isEmpty(allDatas.get(i * 9 + j_position).get(3))) {
                                    Log.e("ffff-------------", allDatas.get(i * 9 + j_position).get(3)+"==" + count);
                                    count++;
                                }
                            }
                            if (count==0){
                                Log.e("ffff-----mm--------", "==" + count);
                                return false;
                            }

                            return false;
                        }
                    }

                }
            }
        }
        return true;
    }

    public void huiqi(){
        Log.e("huiqi",back_datas.size()+""+back_datas.toString());
        if (back_datas.size()>1){
            allDatas.clear();
            back_datas.remove(back_datas.size()-1);
            for (int k = 0; k < back_datas.get(back_datas.size()-1).size(); k++) {
                List<String> temp=new ArrayList<>();
                for (int i = 0; i <back_datas.get(back_datas.size()-1).get(k).size() ; i++) {
                    temp.add(back_datas.get(back_datas.size()-1).get(k).get(i));
                }
                allDatas.add(temp);
            }
            Log.e("huiqi=====",allDatas.toString());
            if (currRole.equals("1")){
                currRole="2";
                currPosition=-1;
                currTouch=-1;
            }else{
                currRole="1";
                currPosition=-1;
                currTouch=-1;
            }
            invalidate();
        }else{
            Toast.makeText(getContext(),"当前无法继续悔棋了", Toast.LENGTH_SHORT).show();
        }
    }

    public void fupan(){
        currRole="1";
        currPosition=-1;
        currTouch=-1;
        allDatas.clear();
        for (int k = 0; k < allDatasDefault.size(); k++) {
            List<String> temp=new ArrayList<>();
            for (int i = 0; i <allDatasDefault.get(k).size() ; i++) {
                temp.add(allDatasDefault.get(k).get(i));
            }
            allDatas.add(temp);
        }
        invalidate();
    }
}

 

欢迎参考与评论留言:

自定义View之中国象棋资源下载

 

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值