---
# System prepended metadata

title: 10/14 Arcade也能學演算法Ouo!? 演算法遊戲(5)
tags: [2022 iThome 鐵人賽]

---

---
tags: 2022 iThome 鐵人賽 
title: 10/14 Arcade也能學演算法Ouo!? 演算法遊戲(5)
AUTHOR: 鍾佳龍
---
# Arcade再進化
## Arcade也能學演算法Ouo!? 演算法遊戲!(5)
### **第五篇：棋類遊戲-黑白棋實作篇**

> ### 大綱
> * 遊戲內容
> * 基本設定
> * 下棋
> * 顯示結果
> * 結束了?

## 遊戲內容
[![](https://i.imgur.com/eA3H66l.gif)](https://arcade.makecode.com/S44558-75061-91805-02033)
點擊動圖可以進入遊戲

首先
有紅色框框可以選位置
然後下棋
最後結束的時候會告訴你是誰贏了

## 製作開始!!
開始第一件事情就是建立角色拉
可以從上面的成果預覽看到
我們的物件就三個

1. 棋盤
1. 棋子
1. 紅色游標
```typescript
let backgroung_board = sprites.create(img`
    ...
`, SpriteKind.Player)
backgroung_board.changeScale(2, ScaleAnchor.Middle)

let board = sprites.create(img`
    ...
`, SpriteKind.Player)
board.changeScale(2, ScaleAnchor.Middle)

let choese = sprites.create(img`
    ...
`, SpriteKind.Player)
choese.setPosition(75, 55)
```

然後是我們一路走熟到爆的控制選擇
這次有點小不一樣
因為我們有橫軸跟縱軸
聰明的你應該知道怎麼做了吧

```typescript
// control
let now_x = 3
let now_y = 3
controller.right.onEvent(ControllerButtonEvent.Pressed, function () {
    now_x = (now_x + 1) % 8
    choese.setPosition(39+now_x*12, 19+now_y*12)
})
controller.left.onEvent(ControllerButtonEvent.Pressed, function () {
    if (now_x == 0) {
        now_x = 8;
    }
    now_x -= 1;
    choese.setPosition(39 + now_x * 12, 19 + now_y * 12)
})
controller.down.onEvent(ControllerButtonEvent.Pressed, function () {
    now_y = (now_y + 1) % 8
    choese.setPosition(39 + now_x * 12, 19 + now_y * 12)
})
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
    if (now_y == 0) {
        now_y = 8;
    }
    now_y -= 1;
    choese.setPosition(39 + now_x * 12, 19 + now_y * 12)
})
```
這次的話不只是左右移動了
還要上下
所以我們設定兩個軸
一個是X一個Y

接者就要進入上次文章的範圍了喔

## 下棋
我設定A鍵下棋

```typescript
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    let put = false;
    let X = now_x
    let Y = now_y
    ...
})
```
先存個變數方便調用
然後第一件就是要偵測是否能下
也就是我們上篇的`check_put_legitimate`函式
那這邊基本上沒有改變喔
就是上一篇的程式碼搬過來了
不知道是什麼的可以回到上一篇
有變的就是在return的部分
下面會講到

```typescript
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    let put = false;
    let X = now_x
    let Y = now_y

    // check put
    
    let check = check_put_legitimate(X, Y, turn);
    if (check) {
        put = true;
        play(X, Y, turn, mode, coun);
    }
    ...
```
檢查位置是否合法後就可以執行下棋的部分了
不過有看上一篇的應該有發現我的play函式怎麼多了兩個參數阿
這是因為在typescript的關係喔
> 對arcade縮然說他是用javascript但事實上他是用typescript
> 那因為typescript是強型態喔
> 所以return的變數型態如果照上篇的寫法
> 他的回傳值型代會變成`(boolen, number[])`然後就不能當作`number`用了

所以我另外把mode 跟count變成全域變數
阿但!
不知道為啥我名稱不能設`count`所以就退而求其次取`coun`了
剩下完全沒改
所以我就不貼程式碼瞜 大家自行到範例程式看

## 顯示結果

```typescript
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    let put = false;
    let X = now_x
    let Y = now_y

    // check put
    
    let check = check_put_legitimate(X, Y, turn);
    if (check) {
        put = true;
        play(X, Y, turn, mode, coun);
    }
    if (put) {
        print();
        ...
})
```
那這次不是因在console喔
所以這邊的`print`是完全不一樣

不過這次的方法各位也很熟悉了

```typescript
function print() {
    let bord_img = image.create(33, 33)
    for (let Y = 0; Y < 8; Y++) {
        for (let X = 0; X < 8; X++) {
            if(Data[Y][X] != " "){
                let color = Data[Y][X] == "O" ? 1 : 15
                bord_img.setPixel(2+4*X,  + 2+4*Y, color)
                bord_img.setPixel(1 + 4 * X, + 2 + 4 * Y, color)
                bord_img.setPixel(3 + 4 * X, + 2 + 4 * Y, color)
                bord_img.setPixel(2 + 4 * X, + 1 + 4 * Y, color)
                bord_img.setPixel(2 + 4 * X, + 3 + 4 * Y, color)

            }
        }
    }
    board.setImage(bord_img)
}
```
就簡單的更改角色皮膚

## 結束拉
最後是判斷是否結束
這邊的話也是上次飯粒程式改的喔

```typescript
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
    let put = false;
    let X = now_x
    let Y = now_y

    // check put
    
    let check = check_put_legitimate(X, Y, turn);
    if (check) {
        put = true;
        play(X, Y, turn, mode, coun);
    }
    if (put) {
        print();
        turn = turn == "O" ? "X" : "O";
        if (check_end(turn)) {
            turn = turn == "O" ? "X" : "O";
            if (check_end(turn)) {
                game.splash(`${turn == "O"? "white": "black"} is win!!`)
                game.over(false)
            }
        }
        scene.setBackgroundColor(turn == "O" ? 1 : 15)
    }
})
```
就是如果下一輪的人不能下
那就pass
阿但是在下一輪也不能下
那遊戲就結束了
最後數數看誰棋多

```typescript
function check_end(turn:string) {
    let end = true;
    for (let i = 0; i < 8; i++) {
        for (let j = 0; j < 8; j++) {
            if (Data[i][j] == " ") {
                if (check_put_legitimate(j, i, turn)) {
                    end = false;
                }
            }
        }
    }
    return end;
}

function check_win() {
    let count = [0, 0];
    for (let i = 0; i < 8; i++) {
        for (let j = 0; j < 8; j++) {
            if (Data[i][j] == "O") {
                count[0]++;
            } else if (Data[i][j] == "X") {
                count[1]++;
            }
        }
    }
    return count[0] > count[1] ? "white" : "black";
}
```
這就是全部內容拉
---
> ## 下期預告
> **嗯?完結啦!!**