在看完官方教學後,其實大部分都可以續用在五子棋上面,只差在難度較高的勝負邏輯判斷。
( 所以這篇筆記只是單純紀錄勝負判斷的思考過程 )
在正式開始寫之前,經過思考後,切 Component 的方式跟 state 儲存位置應該可以照 React 的五子棋教學:
Game
整個遊戲
Board
棋盤
Square
格子History
側欄( 放步驟記錄 )比較棘手的是牌面陣列 squares
要怎麼規劃:
毫無頭緒,不如先畫出 19x19
的棋面,把座標印在上面。
歷經一番波折印出:
發現這樣好像就滿 OK 的,但每個 square 應該都要有以下資訊:
position
:[x, y]
value
: null || black || white
所以把剛剛產生陣列的函式 createArr
改寫,幫每個 square 加上屬性:
接下來就好處理了,把 UI 的 position
換成 value
,加上 handleClick()
將 square 的 value 改掉
因為目前 state 的資料格式無法查找座標,只能找 squares[index]
,不能用 squares[x][y]
[x, y]
去推導出 index
?[0][0]
=> 0
, [0][1]
=> 1
, [1],[0]
=> 20
toArr()
, toIndex()
while ( credit >=4
|| end >= 2
)
credit++
credit++
credit++
credit++
=> 勝利
end++
=> 跳到步驟 2end++
=> 跳到步驟 2end++
=> 跳到步驟 2end++
=> 跳到步驟 2end++
credit++
end++
=> 結束
end++
=> 結束
總之寫想半天,把往左右 ( 橫向 ) 的方向判定完畢:
findRow()
跑 while 迴圈,直到 credit >= 4
或 end >=2
就跳出:
(1)
credit++
=> 繼續往右找
credit++
=> 繼續往右找end++
=> 跳到步驟 2
(2)
end++
=> 換往左找
credit++
=> 繼續往左找end++
=> 結束簡單來說就是:
credit++
end++
( 圖片上的藍、綠色塊 )直覺應該不會太難,因為我的棋面的陣列只有一維,所以往左右找只要 +1
、-1
比較簡單,改成垂直查找只要再乘上 20
就好:
+1
-1
-20
+20
把 findRow 變成可以用參數改變方向:
其實最大的修改是計算步數的函式 countStep
。
( 程式碼還很亂,因為放了很多方便 debug 的程式碼,但目前算堪用 )
處理最棘手的交叉線,先來看 [index]
要怎麼換算,不知道怎麼算就列出來:
/
-19
、-38
…
+1
+ 往上找: -20
+19
、+38
…
-1
+ 往下找: +20
\
-21
、-42
…
-1
+ 往上找: -20
+21
、+42
…
+1
+ 往下找: +20
寫出來感覺就不難了,規則跟剛剛的「 垂直查找 」類似,只要在剛剛的基礎再做變化就行:
|
=> 右斜線 /
-20
+1
=> 變右上角 -19
+20
-1
=> 變左下角 +19
|
=> 左斜線 \
-20
-1
=> 變左上角 -21
+20
+1
=> 變右下角 +21
我解題的想法是,問題越簡單越好,所以先土法煉鋼的寫完兩條斜線,一樣是改 countStep()
函式
驚人發現: 寫完就發現規則都一樣,其實只要改初始值就好!
getStartPosition()
把各方向的初始值定義好:countStep()
計步函式,整個簡潔許多:再來就把檢查判定改過一輪就行了,本來是這樣的:
改成某方向出現贏家就直接 return
,不用再去比較其他方向。
把最難寫的勝負判斷寫完了!!
過程真是艱辛,雖然用的方法都很土炮,且還有很多優化空間,總之能完成很開心,也深深感受到寫程式要化繁為簡的必要性。
寫一寫發現 state 的 squares 根本不用存位置資訊,所以把原本的物件格式改成 value
字串
控制幾路棋的參數 this.rowNum
滿多地方會用到就不貼了,另外一個就是用 this.rowSize
控制CSS,直接寫在 inline-style 上