--- tags: 2022 iThome 鐵人賽 title: 10/2 Arcade也能學演算法Ouo!? 演算法遊戲(3) AUTHOR: 鍾佳龍 --- # Arcade再進化 ## Arcade也能學演算法Ouo!? 演算法遊戲!(3) ### **第三篇:棋類遊戲-立體四子棋** > ### 大綱 > * 遊戲內容 > * 創建角色 > * 控制箭頭 > * 放置棋子 > * 顯示結果 > * 尋找連線 > ## 成果預覽 這是一個雙人對戰遊戲 可以利用左右鍵控制箭頭下棋 每次下棋只能選擇欄 選後會落下至作最上方 只要四個連線即為贏得遊戲 [![](https://i.imgur.com/zFA5U0p.gif)](https://arcade.makecode.com/S26763-39501-31310-23616) 點擊上圖可以進入遊戲頁面 > ## 創建角色 這次會有三個角色 * 棋盤本人 * 棋子狀態 * 箭頭 棋盤 ```typescript! let checkerboard = sprites.create(img` ........................ ........................ .8..8..8..8..8..8..8..8. .8.88.88.88.88.88.88.88. .8..8..8..8..8..8..8..8. .8.88.88.88.88.88.88.88. .8..8..8..8..8..8..8..8. .8.88.88.88.88.88.88.88. .8..8..8..8..8..8..8..8. .8.88.88.88.88.88.88.88. .8..8..8..8..8..8..8..8. .8.88.88.88.88.88.88.88. .8..8..8..8..8..8..8..8. .8.88.88.88.88.88.88.88. 888888888888888888888888 8......................8 `, SpriteKind.Player) checkerboard.setScale(5, ScaleAnchor.Middle) ``` 然後是棋子 因為棋子的部份我們要用圖片的方式顯示 為了可以跟棋盤重疊 所以我們設定都要跟棋盤一樣 ```typescript let bord = sprites.create(img` 16*24 `, SpriteKind.Player) bord.setScale(5, ScaleAnchor.Middle) ``` 箭頭的部分很簡單就直接宣告就行 ```typescript let arrow = sprites.create(img` . . . . . . . . . . 2 . . . . . . 2 . . . . . . 2 . . . . . . 2 . . . . 2 2 2 2 2 . . . 2 2 2 . . . . . 2 . . . . . . . . . . `, SpriteKind.Player) ``` 然後我將箭頭放置在棋盤的第一欄上方 ```typescript arrow.setPosition(37, 20) ``` > ## 控制箭頭 我們總共有七欄 要讓箭頭左右移動 ㄟ! 這聽起來很像上次同化遊戲的選顏色 沒錯! 所以我們就拿上次的程式碼來改就好 ```typescript let now_number = 0 controller.right.onEvent(ControllerButtonEvent.Pressed, function () { now_number = (now_number + 1) % 7 }) controller.left.onEvent(ControllerButtonEvent.Pressed, function () { if (now_number == 0) { now_number = 7; } now_number -= 1; }) ``` 然後是要讓箭頭移動 我們可以想成 他從我初次設定的地方(37, 20) 數字多少就移動多少像素(15) 然後再放進去就好 ```typescript let now_number = 0 controller.right.onEvent(ControllerButtonEvent.Pressed, function () { now_number = (now_number + 1) % 7 arrow.setPosition(37 + (now_number * 15), 20) }) controller.left.onEvent(ControllerButtonEvent.Pressed, function () { if (now_number == 0) { now_number = 7; } now_number -= 1; arrow.setPosition(37 + (now_number * 15), 20) }) ``` > ## 放置棋子 我們要做一個儲存棋盤的地方 方便我們之後要用 ```typescript let Data = [ [" ", " ", " ", " ", " ", " ", " "], [" ", " ", " ", " ", " ", " ", " "], [" ", " ", " ", " ", " ", " ", " "], [" ", " ", " ", " ", " ", " ", " "], [" ", " ", " ", " ", " ", " ", " "], [" ", " ", " ", " ", " ", " ", " "] ] ``` 有棋盤了 接下來就是下棋了 因為我們的規則是放到指定行會往下掉 掉到頂端 所以我們思考的方式就是我們要從下面搜尋 找到最下面的" " ```typescript function play(location:number) { for (let i = 5; i > -1; i--) { if (Data[i][location] == " ") { ... } } } ``` 然後我要把最下面的那格換成其他記號 我這邊以O X ```typescript! let tuen = "O" let row:number function put(location:number) { for (let i = 5; i > -1; i--) { if (Data[i][location] == " ") { Data[i][location] = turn row = i break } } } ``` 這邊先順便拿個row 之後會用到 到此為止 下棋的部分就算告一落了 > ## 顯示結果 下完棋後要顯示出來 這邊我用的方法是讓背景自己改變 改變角色圖片上一次也用過 ```typescript function show_board() { let bord_img = image.create(24, 16) // 製造一個空畫板 for (let R = 0; R < 6; R++) { for (let C = 0; C < 7; C++) {// 依序讀取資料 if (Data[R][C] != " ") {//如果那格有資料 let color if (Data[R][C] == "O") { color = 2 } else { color = 5 } //將棋子畫上去 bord_img.setPixel(C * 3 + 3, R * 2+2, color) bord_img.setPixel(C * 3 + 2, R * 2+2, color) bord_img.setPixel(C * 3 + 2, R * 2+3, color) } } } bord.setImage(bord_img) // 改變圖片 } ``` > ## 我怎麼知道他連線了 最後就是判斷連線了 我們的想法就是以我這次下棋的地方為中心 然後往外找是否連線 以橫向來看 ```typescript function check_end(location: number, row: number) { // 檢查橫向 // 左向 let count = 0 for (let i = 0; i < 4 && (location + i < 7); i++) { if (Data[row][location + i] != turn) { break } count += 1 } console.log(count) // 右向 for (let i = 0; i < 4 && (location - i > -1); i++) { if (Data[row][location - i] != turn) { break } count += 1 } if (count > 4) { return true } ... ``` 橫向就是左向加右向 剩下的直 斜 向因為篇幅 所以我沒放進來 請自行到我的遊戲頁面看程式碼 --- 基礎架構以完畢 最後就是依序呼叫 ```typescript controller.A.onEvent(ControllerButtonEvent.Pressed, function () { put(now_number) show_board() let is_end = check_end(now_number, row)) if (is_end){ game.showLongText(`${turn}win`, DialogLayout.Bottom) game.over(false) } if(turn == "O"){ turn = "X" }else{ turn = "O" } }) ``` --- > ## 下期預告 > **各種棋篇-黑白棋**