Vue — 實作井字遊戲

Chloe Lo
chloelo925
Published in
4 min readMar 13, 2020

原來我也寫得出來ooxx

Photo by NeONBRAND on Unsplash

coding 的過程,思考流程對我來說是最基礎也最重要的步驟,先列出所有應該要實作出的步驟。

Todo Steps --

  1. 劃出九宮格
  2. 設定兩個玩家:O 與 X,一方點擊完必須要換手,
    點過的格子不能重複點擊
  3. 勝負結果出現後,剩下的空白格不能點擊
  4. 重置鍵可以隨時重新開始遊戲
  5. 審視程式碼,如果有更好的寫法就再調整

STEP 1

在 HTML 中,用 v-for 去跑迴圈,劃出九個格子,樣式屬 css 部分,就不加詳述。

STEP 2

Data 裡,設定 grids 陣列為九宮格,預設值皆為 0,player 為玩家,預設為 1 ( 畫面呈現就是代表 O 玩家 ),當點擊其中一個格子,玩家要轉換,值變成 -1 ( 代表 X 玩家)。

上方敘述得知可以設計兩個 function, setGrid 與 setSymbol

  • setGrid( ){ }:寫入點擊方格時,被點擊的方格狀態要改變
  • setSymbol( ){ }:寫入畫面,由數值 0, 1, -1,轉換為 空白, O, X

補充:在 Vue 裡,不能直接指定陣列的值,如以下寫法:

this.grids[index] = 1; 

要用 this.$set(array, index, value) function 的方式寫入:

this.$set(this.grids, index, this.player);

STEP 3

這個步驟是這個遊戲裡最難的部分,要寫出判定輸贏的 function, , 首先我們要先新增一個二維陣列,裡面總共有八個組合,只有符合其中一個組合遊戲就結束,八個組合分別是橫排三條線,直排三條線,對角兩條線。
組合裡的數字為九宮格相對應的 index。

const winLineSets = [
[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6]
]

接著要設計 getWinner( ){ } function,

  • 基礎寫法:for 迴圈
  • 進階寫法:reduce

先求有再求好,功能先寫出來再去鑽研更好的方法,

for 迴圈

winLine 是所有贏的組合,再用 ES6 語法解構,a, b, c 分別代表贏的組合的index, 帶入 grids, 只要完成總分是 3 分,就是 O 玩家贏,反之,如果總分是 -3,就是 X 玩家贏,只要是其他分數就沒有贏家,回傳 0 。

getWinner () {
for (let i = 0; i < 8; i++) {
let winLine = winLineSets[i];
let [a, b, c] = winLine;
let sum = this.grids[a] + this.grids[b] + this.grids[c];
if (sum === 3) return 1;
if (sum === -3) return -1;
}
return 0;
},

reduce

將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。(from MDN)
accumalator 參數是累計器,在 reduce 裡可以當成一個變數,將初始值與帶入的值累計暫存,初使值為非必填,沒有初始值就會直接以 arr 第一個進入的值開始,callback 參數中前兩個為必填,後兩個參數選填,類似 forEach 會把陣列每個元素帶入。

arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)

此範例中的寫法:

STEP 4

reset 功能比較好能理解,建立一個按鈕,點擊後 grids 陣列通通歸 0,玩家回復初始值 1,贏家也回復初始值 0。

reset () {
this.grids = [0, 0, 0, 0, 0, 0, 0, 0, 0];
this.player = 1;
}

STEP 5

winner 的值其實可以直接從 grids 的變化得知,所以我們可以把 getWinner 這個 function 從 methods 裡面取出,改放到 computed 裡,命名直接叫 winner (),data 裡也不需要另外宣告 winner 這個資料。

畫面呈現:

參考資料:
reduce 釋義

--

--