iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0

本篇將實作創建8 * 8個棋子(chessman)與8 * 8棋子選擇格(chessmanSelect)以及監聽點擊棋子移動的按鈕監聽器,以及實作完成整個getSuccess()

我們回到getSuccess(),取得棋子資料後,會先創建8 * 8棋子,以及8 * 8棋子選擇格

chessman = createBoard.createChessmanAndChessmanSelect(grid_playerChessman,grid_playerChessmanSelect,chessboardData,chessmanEnable).get(0);
chessmanSelect = createBoard.createChessmanAndChessmanSelect(grid_playerChessman,grid_playerChessmanSelect,chessboardData,chessmanEnable).get(1);

並使用兩個陣列接收:

private ArrayList<Button> chessman = new ArrayList<>();
private ArrayList<TextView> chessmanSelect = new ArrayList<>();

這裡我們呼叫createBoard中的createChessmanAndChessmanSelect方法來創建,所以我們到createBoard中實作方法


createChessmanAndChessmanSelect()

public ArrayList<ArrayList> createChessmanAndChessmanSelect(GridLayout grid_playerChessman,
                                                GridLayout grid_playerChessmanSelect,
                                                HashMap<String,Object> chessboardData,
                                                Boolean chessmanEnable){
        ArrayList callbackArray = new ArrayList();
        // 設定GridLayout的列數和行數
        grid_playerChessman.setColumnCount(8);
        grid_playerChessman.setRowCount(8);
        grid_playerChessmanSelect.setColumnCount(8);
        grid_playerChessmanSelect.setRowCount(8);

        // 動態建立Button並添加到GridLayout中
        for (int i = 0; i < 64; i++) {
            chessman.add(new Button(activity));
            chessmanSelect.add(new TextView(activity));

            // 讀取螢幕大小,並根據大小調整按鈕比例
            DisplayMetrics displayMetrics = new DisplayMetrics();
            activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
            int newWidth = (int) (displayMetrics.widthPixels * 0.1f);
            int newHeight = (int) (newWidth);
            int newMarginsWidth = (int) (displayMetrics.widthPixels * 0);
            int newMarginsHeight = (int) (newMarginsWidth);

            // 設定Button的Layout參數
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            if(grid_playerChessman != null || grid_playerChessmanSelect != null){
                grid_playerChessman.removeView(chessman.get(i));
                grid_playerChessmanSelect.removeView(chessmanSelect.get(i));
            }
            params.width = newWidth;
            params.height = newHeight;
            params.setMargins(newMarginsWidth, newMarginsHeight, newMarginsWidth, newMarginsHeight);
            chessman.get(i).setTypeface(null, Typeface.BOLD);
            chessmanSelect.get(i).setTypeface(null, Typeface.BOLD);
            params.setGravity(Gravity.CENTER);

            // 設定Button的列和行位置
            params.rowSpec = GridLayout.spec(i / 8);
            params.columnSpec = GridLayout.spec(i % 8);

            chessman.get(i).setBackgroundResource(playerChessboardData.getIntChessmanData((String) chessboardData.get(playerChessboardData.getStringBoardData(i))));

            // 將Button添加到GridLayout中
            grid_playerChessmanSelect.addView(chessmanSelect.get(i),params);
            grid_playerChessman.addView(chessman.get(i),params);

            if(chessmanEnable == false){
                chessman.get(i).setEnabled(false);
            }else{
                chessman.get(i).setEnabled(true);
            }
            callbackArray.add(chessman);
            callbackArray.add(chessmanSelect);
        }
        return callbackArray;
    }

這裡我們同時創建8 * 8棋子,以及8 * 8棋子選擇格,並將結果以陣列回傳,所以我們取得資料時會get(0)和get(1)

接著就是監聽棋子,會取得點擊哪個位置格的棋子,得到索引i,並交給selectChessmanListen():

for(int i=0;i<64;i++){
            chessman.get(i).setOnClickListener(selectChessmanListen(i));
        }

selectChessmanListen()

設置2個全域變數startChessman、stopChessman,初值為99,當選擇起手格子後會將position設置給startChessman,當選擇目標格子後會將position設置給stopChessman

基本流程如下:
未命名绘图.drawio

  1. 未選擇起始格時: startChessman為99,stopChessman為99,選格子時會將position設置給startChessman,並透過呼叫chessmanMove中的choice方法取得該格子下棋子的所有可行走格並回傳
  2. 選擇起始格,未選擇目標格時: startChessman不為99,stopChessman為99,如果此時使用者選擇起始格,將先前資料清除;如果不選擇起始格,透過isCanMove方法判斷是否可走,若可走將position設置給stopChessman
  3. 起始格與目標格都已選擇: startChessman不為99,stopChessman不為99,如果此時使用者選擇起始格,將先前資料清除;如果不選擇起始格,透過isCanMove方法判斷是否可走,若可走將position設置給stopChessman;如果選擇目標格(目標格點2下),透過move方法執行棋子移動
public View.OnClickListener selectChessmanListen(int position){
        // 選擇棋子移動
        return new View.OnClickListener(){
            @Override
            public void onClick(View v){
                // 未選擇起始格
                if(startChessman == 99 && stopChessman == 99){
                    allMoveList = new ArrayList();

                    if(chessmanMove.choice(position,chessboardData,pawnMove1,pawnMove2,castlingMove1)!=null
                            && chessmanMove.choice(position,chessboardData,pawnMove1,pawnMove2,castlingMove1).size()!=0){
                        allMoveList = chessmanMove.choice(position,chessboardData,pawnMove1,pawnMove2,castlingMove1);
                        startChessman = position;
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
                        for(int i=0;i<allMoveList.size();i++){
                            chessmanSelect.get((int)allMoveList.get(i)).setBackgroundResource(R.drawable.greenline);
                        }
                    }
                }
                // 選擇起始格,未選擇目標格
                else if(startChessman != 99 && stopChessman == 99){
                    if(position == startChessman){
                        clearData();
                    }else{
                        isCanMove(position);
                    }
                }
                // 起始格與目標格都已選擇
                else if(startChessman != 99 && stopChessman != 99){
                    if(position == startChessman){
                        clearData();
                    } else if (position == stopChessman) {
                        for(int i=0;i<64;i++){
                            chessman.get(i).setEnabled(false);
                        }
                        move();
                    } else{
                        isCanMove(position);
                    }
                }
            }
        };
    }

clearData()

清除資料相當於初始化

public void clearData(){
        startChessman = 99;
        stopChessman = 99;
        castling = "";
        moveTwoStep = "";
        inPassing = "";
        getCount = 0;
        isPromotion = false;
        for(int i=0;i<64;i++){
            chessmanSelect.get(i).setBackgroundResource(R.drawable.blank);
        }
    }

isCanMove()

這裡負責判斷點擊的目標格是否為可選格,如果是則將position設置給stopChessman,若不是則印出系統訊息

public void isCanMove(int position){
        castling = "";
        inPassing = "";
        if(chessboardData.get(playerChessboardData.getStringBoardData(startChessman)).equals("wP")){
            ArrayList greenArray = new ArrayList();
            greenArray.addAll(canMoveList);
            greenArray.addAll(canMoveTwoStepList);
            greenArray.addAll(canEpMoveList);
            greenArray.addAll(canEatList);
            for(int i=0;i<greenArray.size();i++){
                chessmanSelect.get((int)greenArray.get(i)).setBackgroundResource(R.drawable.greenline);
            }
            if(position+8 == startChessman){
                for(int i=0;i<allMoveList.size();i++){
                    if(position == (int)allMoveList.get(i) && chessboardData.get(playerChessboardData.getStringBoardData(position)).equals("  ")){
                        stopChessman = position;
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
//                        break;
                    }
                }
            } else if (position+16 == startChessman) {
                for(int i=0;i<allMoveList.size();i++){
                    if(position == (int)allMoveList.get(i) && chessboardData.get(playerChessboardData.getStringBoardData(position)).equals("  ")){
                        stopChessman = position;
                        moveTwoStep=playerChessboardData.getStringBoardData(position);
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
//                        break;
                    }
                }
            } else if(position+9==startChessman || position+7==startChessman){
                for(int i=0;i<allMoveList.size();i++){
                    if(position == (int)allMoveList.get(i) && chessboardData.get(playerChessboardData.getStringBoardData(position)).equals("  ")){
                        stopChessman = position;
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
                        inPassing = playerChessboardData.getStringBoardData(position+8);
//                        break;
                    }
                }
                for(int i=0;i<allMoveList.size();i++){
                    if(position == (int)allMoveList.get(i) && String.valueOf(chessboardData.get(playerChessboardData.getStringBoardData(position)).toString().charAt(0)).equals("b")){
                        stopChessman = position;
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
//                        break;
                    }
                }
            } else{
            }
        }else if(chessboardData.get(playerChessboardData.getStringBoardData(startChessman)).equals("wK")){
            for(int i=0;i<allMoveList.size();i++){
                chessmanSelect.get((int)allMoveList.get(i)).setBackgroundResource(R.drawable.greenline);
            }
            for(int i=0;i<allMoveList.size();i++){
                chessmanSelect.get((int)allMoveList.get(i)).setBackgroundResource(R.drawable.greenline);
            }
            if(allMoveList.size() != 0){
                for(int i=0;i<allMoveList.size();i++){
                    if(position == (int)allMoveList.get(i)){
                        if(position == 58){
                            stopChessman = position;
                            chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
                            castling = "leftCastling";
                        }else if(position == 62){
                            stopChessman = position;
                            chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
                            castling = "rightCastling";
                        }
                    }
                }
            }
            for(int i=0;i<allMoveList.size();i++){
                if(position == (int)allMoveList.get(i)){
                    if(chessboardData.get(playerChessboardData.getStringBoardData(position)).equals("  ")
                            || String.valueOf(chessboardData.get(playerChessboardData.getStringBoardData(position)).toString().charAt(0)).equals("b")){
                        stopChessman = position;
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
//                        break;
                    }else{
                        systemMessage("系統訊息:\n不可移動");
                    }
                }
            }
        }else{
            for(int i=0;i<allMoveList.size();i++){
                chessmanSelect.get((int)allMoveList.get(i)).setBackgroundResource(R.drawable.greenline);
                if(position == (int)allMoveList.get(i)){
                    if(chessboardData.get(playerChessboardData.getStringBoardData(position)).equals("  ")
                            || String.valueOf(chessboardData.get(playerChessboardData.getStringBoardData(position)).toString().charAt(0)).equals("b")){
                        stopChessman = position;
                        chessmanSelect.get(position).setBackgroundResource(R.drawable.redline);
//                        break;
                    }else{
                        systemMessage("系統訊息:\n不可移動");
                    }
                }
            }
        }
    }

isKorRMove()

回到getSuccess(),我們在此也會做其他判斷,像是城堡或國王是否移動過,以及顯示出棋譜文字

public void isKorRMove(){
        if(!(chessboardData.get("a1").equals("wR"))){
            castlingMove1.put("a1",false);
            dbp.uploadData(roomKey,"CastlingMove1",castlingMove1);
        }
        if(!(chessboardData.get("h1").equals("wR"))){
            castlingMove1.put("h1",false);
            dbp.uploadData(roomKey,"CastlingMove1",castlingMove1);
        }
        if(!(chessboardData.get("e1").equals("wK"))){
            castlingMove1.put("e1",false);
            dbp.uploadData(roomKey,"CastlingMove1",castlingMove1);
        }
    }

showText()

顯示文字

public void showText(){
        tv_message.setText(player2message);
        String showMoveData="";
        String state="";
        for(int i=1;i<chessmanMoveData.size();i++){
            if(i%2==1){
                state="白";
            }else{
                state="黑";
            }
            showMoveData = showMoveData +"\n"+i+"("+state+")"+" : "+chessmanMoveData.get(String.valueOf(i));
        }
        tv_moveData.setText(showMoveData);
    }

所以整個getSuccess方法會是:

public void getSuccess(String getId,
                           String getRoomNumber,
                           Boolean getPlayer1OnlineState,
                           Boolean getPlayer2OnlineState,
                           String getMoveState,
                           HashMap<String,Object> getChessboardData,
                           HashMap<String,Object> getChessmanMoveData,
                           String getTurn,
                           HashMap<String,Object> getPawnMove1,
                           HashMap<String,Object> getPawnMove2,
                           HashMap<String,Object> getCastlingMove1,
                           HashMap<String,Object> getCastlingMove2,
                           String getDate,
                           String getPlayer1message,
                           String getPlayer2message,
                           String getWinPlayer){
        Log.d("TAG", "資料獲取成功");
        roomKey = getId;
        player1OnlineState = getPlayer1OnlineState;
        player2OnlineState = getPlayer2OnlineState;
        moveState = getMoveState;
        chessboardData = getChessboardData;
        chessmanMoveData = getChessmanMoveData;
        turn = Integer.parseInt(getTurn);
        pawnMove1 = getPawnMove1;
        pawnMove2 = getPawnMove2;
        castlingMove1 = getCastlingMove1;
        castlingMove2 = getCastlingMove2;
        date = getDate;
        player1message = getPlayer1message;
        player2message = getPlayer2message;
        winPlayer = getWinPlayer;
        getCount+=1;
//        Log.d("20240318", "getSuccess: "+roomKey);
        // 判斷King或Rook是否移動過
        isKorRMove();
        // 設置訊息文字、棋譜文字
        showText();

        chessman = createBoard.createChessmanAndChessmanSelect(grid_playerChessman,grid_playerChessmanSelect,chessboardData,chessmanEnable).get(0);
        chessmanSelect = createBoard.createChessmanAndChessmanSelect(grid_playerChessman,grid_playerChessmanSelect,chessboardData,chessmanEnable).get(1);

        if(gameMode.equals("ai") && moveState.equals("black") && getCount==1){
            gptMove.setRoomKey(roomKey);
            gptMove.setTurn(String.valueOf(turn));
            gptMove.setCastling(castling);
            gptMove.setChessmanMoveData(chessmanMoveData);
            gptMove.setChessboardData(chessboardData);
            gptMove.setGPT();
        }

        for(int i=0;i<64;i++){
            chessman.get(i).setOnClickListener(selectChessmanListen(i));
        }
    }

下一篇我們介紹PlayerChessmanMoveData中核心的choice方法


上一篇
【DAY 18】activity - Player1ChessGame - listenConversations
下一篇
【DAY 20】activity - Player1ChessGame - getArrChessmanMoveData
系列文
基於Firebase整合生成式AI研究開發雙人國際象棋系統(Based on Firebase and AI to research chess system)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言