馮地龍
五子棋大家都玩過,雙方分別使用黑白兩色的棋子,下在棋盤直線與橫線的交叉點(diǎn)上,先形成五子連珠者獲勝。五子棋起源于中國(guó),還是全國(guó)智力運(yùn)動(dòng)會(huì)競(jìng)技項(xiàng)目之一。由于規(guī)則簡(jiǎn)單,老少皆宜,而且趣味橫生,引人入勝(圖1)。
今天跟大家分享怎么用Scratch制作五子棋游戲。想要把五子棋的規(guī)則完全用Scratch編程實(shí)現(xiàn)還是不容易的。在編寫程序之前,我們先梳理一下思路,程序需要實(shí)現(xiàn)以下目標(biāo):
①繪制棋盤
②限制光標(biāo)移動(dòng)
③實(shí)現(xiàn)落子功能
④判斷棋盤狀態(tài)
⑤判斷五子連珠
⑥實(shí)現(xiàn)人機(jī)對(duì)下
2021年第3期我們?cè)?jīng)介紹過用Scratch制作五子棋,當(dāng)時(shí)實(shí)現(xiàn)了繪制棋盤和黑白交替落子功能,也就是完成了前3項(xiàng)功能,后面幾項(xiàng)沒能實(shí)現(xiàn)?,F(xiàn)在我們的編程能力已經(jīng)提高了,本文將能實(shí)現(xiàn)前5項(xiàng)功能,完成五子相連的勝負(fù)判斷。由于前3項(xiàng)功能已經(jīng)介紹過,本文只提示一下要點(diǎn),重點(diǎn)還是在于判斷棋盤狀態(tài)和判斷五子連珠。至于實(shí)現(xiàn)人機(jī)對(duì)下涉及算法策略,我們以后再來實(shí)現(xiàn)。
1.用一個(gè)角色隱藏繪制棋盤。
2.為了方便計(jì)算,起點(diǎn)坐標(biāo)值取整數(shù)(XY軸方向分別為-150、150)。重復(fù)繪制16條橫線和豎線,每條長(zhǎng)度300。
3.繪制XY方向的間距為20(也就是步長(zhǎng))。
4.用畫筆功能完成繪制15×15的棋盤。
參考代碼如圖2:
1.創(chuàng)建新的角色“光標(biāo)”,用來提示當(dāng)前操作者,含有兩個(gè)造型(黑色光標(biāo)造型編碼為1;白色光標(biāo)造型編碼為2),光標(biāo)角色稍大于五子棋(因五子棋在光標(biāo)內(nèi)落子)。
2.利用邏輯與配合棋盤大小的坐標(biāo)值把光標(biāo)控制在棋盤內(nèi)跟隨鼠標(biāo)指針移動(dòng)。
3.根據(jù)光標(biāo)跟隨鼠標(biāo)的坐標(biāo)值可以計(jì)算出在棋盤的行數(shù)和列數(shù),儲(chǔ)存在新建變量的“行數(shù)Y”和變量“列數(shù)X”中。“行數(shù)Y”是因?yàn)閅值不同則行數(shù)不同,同理兩個(gè)棋子的X值不同Y值一樣則兩個(gè)棋子在同一行,有相同的“行數(shù)Y”。
4.通過計(jì)算,把變量“行數(shù)Y”和“列數(shù)X”計(jì)算出來的舞臺(tái)坐標(biāo)值分別賦值到鼠標(biāo)XY軸坐標(biāo)上,同時(shí)設(shè)為當(dāng)前坐標(biāo),這樣我們就可以把角色固定在棋盤XY兩軸相交點(diǎn)上。
5.棋盤大小是15×15,行數(shù)和列數(shù)相交點(diǎn)也就是225個(gè)。
6.通過變量“行數(shù)Y”和變量“列數(shù)X”中的計(jì)算得出光標(biāo)在棋盤內(nèi)X、Y(行列相交的點(diǎn))新的坐標(biāo)值,賦值在新建變量ID上。(ID相當(dāng)于在棋盤行列相交點(diǎn)的每一個(gè)坐標(biāo)。每一個(gè)相交點(diǎn)都有一個(gè)對(duì)應(yīng)的ID值。)
參考代碼如圖3:
1.創(chuàng)建角色五子棋,棋的造型為兩個(gè),黑色棋1和白色棋2(對(duì)應(yīng)光標(biāo)造型的顏色)。
2.在光標(biāo)角色里通過按下鼠標(biāo)成立與不成立的邏輯,按下就廣播新建消息落子,切換下一個(gè)造型,如果沒有按下鼠標(biāo)就一直等待。落子代碼在圖3中。
3.當(dāng)角色五子棋接收到落子的消息,換成光標(biāo)的造型編碼,移動(dòng)到角色光標(biāo)的位置蓋上圖章(實(shí)現(xiàn)落子功能)。如圖4。
1.新建“棋盤狀態(tài)”列表,這是15×15=225項(xiàng)的列表。將0加入狀態(tài)(空狀態(tài))(圖5)。
2.通過在光標(biāo)角色里按下鼠標(biāo)成立與不成立的邏輯,嵌套條件判斷如果列表的ID項(xiàng)等于0(也就是空狀態(tài),沒有棋子),廣播消息落子,并把造型的編號(hào)賦值在列表棋盤狀態(tài)的ID項(xiàng)(造型編號(hào)兩個(gè),也就賦值1的狀態(tài),1就是黑棋),下一個(gè)造型。
3.如果列表的ID項(xiàng)不等于0(狀態(tài)兩種,0是空狀態(tài),1代表黑子和2代表白子),有棋子狀態(tài)的情況不能廣播落子消息,無動(dòng)作。等待光標(biāo)移動(dòng)到棋盤是0的ID項(xiàng)才能實(shí)現(xiàn)按下鼠標(biāo)條件成立并廣播落子的消息。具體代碼請(qǐng)參考圖3。落子之后列表對(duì)應(yīng)效果如圖6。
1.判斷五子連珠首先要知道五子棋的連珠規(guī)則,以最近一個(gè)棋子落下為原點(diǎn),橫豎斜等八個(gè)方向有5顆同色棋子連成一條線代表此方勝利。
2.創(chuàng)建繪制新的角色“判斷”。鼠標(biāo)在棋盤內(nèi)移動(dòng),注意行列的變量,你會(huì)發(fā)現(xiàn)方向變化的規(guī)律,總結(jié)出往八個(gè)方向每走一格數(shù)據(jù)的變化:
正方向,向上走X增加0、Y增加1;斜上走X增加1、 Y增加1;右走X增加1、Y增加0;斜下走X增加1、Y減少1(如圖7)。
反方向走的規(guī)律變化類似,只是根據(jù)方向變成負(fù)數(shù),變量“列數(shù)X”和“行數(shù)Y”增加負(fù)1。
3.新建變量“判斷列數(shù)X”和“判斷行數(shù)Y”,并把變量“列數(shù)X”和“行數(shù)Y”賦值給這兩個(gè)變量上,用于判斷五子連珠。
4.自定義函數(shù)積木“判斷連珠XYK”,參數(shù)XY表示縱橫坐標(biāo),K為系數(shù)用作正反方向。
原理:變量“列數(shù)X”和“行數(shù)Y”分別賦值到對(duì)應(yīng)“判斷列數(shù)X”和“判斷行數(shù)Y”;然后開始判斷,將“判斷列數(shù)X”和“判斷行數(shù)Y”增加“判斷連珠”函數(shù)里的X和Y的值乘以系數(shù)K(正數(shù)1和負(fù)數(shù)1),這樣可以將8個(gè)方向都試一遍。
先判斷落子在棋盤內(nèi),在行數(shù)與列數(shù)是-1到15之間。
如果棋盤狀態(tài)的ID項(xiàng)等于當(dāng)前的造型編號(hào)(1或2)時(shí),將變量計(jì)數(shù)增加1,重復(fù)4次,如果等于棋盤狀態(tài)的1或者2時(shí),表示旁邊有同色的棋子,就按這個(gè)方向繼續(xù)去檢測(cè),如果可以重復(fù)4次就表示五子連珠了,否則就停止這個(gè)腳本(如圖8)。
5. 在角色光標(biāo)里,按下鼠標(biāo)成立,廣播新建消息判斷方向消息,當(dāng)判斷角色接收到判斷方向消息后把自定義函數(shù)積木判斷連珠方向值傳送一遍。
6. 自定義函數(shù)積木方向,把判斷連珠函數(shù)里面的系數(shù)K正反值輸入進(jìn)去,將變量檢測(cè)設(shè)為1,如果變量計(jì)數(shù)的值檢測(cè)到大于4,且光標(biāo)的造型編碼等于1,黑棋贏,等于2白棋贏(如圖9)。
到這里,我們的五子棋游戲也就成功了。其實(shí)五子棋的難點(diǎn)在于思路,判斷邏輯要明確清楚,涉及的數(shù)學(xué)知識(shí)比較廣泛,比如參數(shù)K就是向量知識(shí)。根據(jù)鼠標(biāo)的指針坐標(biāo)計(jì)算變量行數(shù)Y,變量列數(shù)X以及變量ID。你需要充分理解自定義積木里面參數(shù)之間的關(guān)系,判斷勝負(fù)的條件等。
這里我們只用五子連珠來判斷勝負(fù),真實(shí)比賽中為了平衡先手的優(yōu)勢(shì)還會(huì)對(duì)黑棋規(guī)定“禁手”。如三三禁手(兩個(gè)以上的活三)、四四禁手、長(zhǎng)連禁手。黑方禁手形成時(shí),白方應(yīng)立即指出。若白方在之后繼續(xù)落子,則禁手失效。黑方出現(xiàn)禁手,無論是自愿下或被迫下,均判負(fù)。黑方五連與禁手同時(shí)形成,判黑方勝。
最后給大家留一個(gè)問題,在目前的五子棋游戲中是屬于雙人對(duì)戰(zhàn),如果把一方改為自動(dòng)(機(jī)器AI)落子實(shí)現(xiàn)人機(jī)大戰(zhàn)呢?好了,這個(gè)問題就交給下一篇文章了。我們一起動(dòng)腦思考一下吧。