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:[email protected]
 * 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之中國象棋資源下載

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章