摘要:說起井字游戲,真是滿滿的童年味道,還記得最瘋狂的時候是小時候跟同桌拿著一張草稿紙就能玩一節課,回到家跟弟弟也能繼續玩,對于沒有太多娛樂節目的童年來說,真是一款玩不厭的小游戲。
99% of information we read, we forget anyway. The best way to remember is to "DO".
體驗地址:http://www.hoohack.me/assets/tictactoe/
游戲完整的代碼在我的 github 上,有興趣也可以圍觀一下:TicTacToe,也希望大家可以點個 star。
緣起最近在FreeCodeCamp上面學習前端知識,不知不覺已經學到了319課,現在遇到的一個小project是做一款井字游戲。說起井字游戲,真是滿滿的童年味道,還記得最瘋狂的時候是小時候跟同桌拿著一張草稿紙就能玩一節課,回到家跟弟弟也能繼續玩,對于沒有太多娛樂節目的童年來說,真是一款玩不厭的小游戲。這款游戲代碼比較簡單,主要是掌握算法的原理,但是也有一些需要注意的地方,于是想把自己遇到的問題記錄下來。
游戲界面進入正題。項目的效果圖如下:
FreeCodeCamp上要求不能查看源碼來實現,于是便想著先把頁面做出來。看到井字格子,就想著用9個li,然后設置li的邊框作為井字線。于是用了一個div包住一個ul,里面有9個li。
游戲有一個開始界面可供選擇玩家的角色,然后選擇先手是哪一方,接著開始游戲。選擇界面做了一個遮罩層,里面提供給用戶選擇,選擇之后便把遮罩層隱藏并開始游戲。
井字游戲算法算法參考了這篇文章。但里面的圖片看不到了,筆者根據自己的理解再解釋一遍,并配上一些圖片。
這次做的是人機對戰,因此就需要寫出比較智能的算法。首先,設計者要懂得玩游戲,有自己的策略,接下來就是將自己的策略付諸實現。
從下圖可以看到,整個棋盤可以連接處8條線,即一共有8種取勝可能:
1. 開局第一步,這一步有兩種情況A、如果先手是電腦,那么就將棋子下在中心位置,如圖:
B、如果先手是玩家,那么有下面三種情況要考慮
如果玩家在中心位置,那么電腦必須落在四個角位,因為如果不落在角位,那么就會出現必輸的情形。假設現在用1-9表示9個棋位。如下圖所示,如果玩家第一步在中心位置,第二步電腦落在第2位的棱位(圖中的2),第三步玩家只需要在第7或第9位下棋(圖中的3),第四步電腦必須在1或3位,第五步玩家跟進在7或9,則第六步電腦必須在1或3,那么第七步玩家只需要在4或者6下棋就可以贏了。
如果玩家在棱位/角位,那么電腦需要在中心位置下棋,在保證不輸的情況下反擊。
2. 第二步棋(先角原則)根據上面的分析,如果先手是玩家且玩家落棋在中心位置,為了避免必輸的情形,電腦需要落棋在角上。而如果先手是電腦,那么如果玩家落在棱位,電腦落在角位讓必輸的情形屬于玩家。
3. 攻擊檢測棋盤,如果有兩枚己方的棋子連在一起且連線中仍有空位,那么就落棋在該位。
4. 防守檢測棋盤,如果有對方的兩枚棋子連在一起且連線中仍有空位,那么就落棋在該位。
5. 垃圾時間當不需要攻擊也不需要防守的時候,那就隨便找個位置下棋,盡可能找到連線中還有兩個空位的位置。
特殊情況有一種特殊情況是不能執行先角原則的,如下圖所示,第一步,玩家先下棋在1,第二步,電腦根據開局第一步的規則下棋在中心位置5,第三步,玩家在1的對角位置9下棋,根據先角原則,第四步電腦將落在3或者7的棋位,第五步玩家在7或者3的位置封堵電腦,那么此時電腦就輸了。唯有此種情況不能執行先角原則,所以在非攻擊且非防守的時候要先排除掉此情況。
具體實現:
說了那么多,可能比較枯燥,下面介紹一下具體的代碼實現。
程序使用一個二維數組panel保存棋盤的狀態,1是電腦的值,-1是玩家的值。winArr保存所有可能贏的8個棋位組合;維護computerWin和userWin,初始值等于winArr,當電腦或玩家每次下棋時,都分別更新這兩個數組,刪除掉不能贏的棋位組合。在更新panel的時候會分別更新computerWin和userWin。
核心的方法是play,play的執行步驟偽代碼如下:
如果可以攻擊 遍歷computerWin數組,找到可以攻擊的棋位,下棋,顯示是否贏了。 不能攻擊,如果需要防守 遍歷userWin,根據玩家可贏的組合,找出需要防守的棋位,下棋,更新panel; 不需要防守,如果是電腦先手的第一步 在中心位置下棋,更新panel; 不是先手第一步 如果中心位置沒有被占去,在中心位置下棋,更新panel;返回 如果是特殊情況,在棱位下棋,更新panel; 返回 如果角位仍有位置,選擇一個角位下棋,更新panel; 返回 最后一種情況,找到剩余的空位,優先選擇位于computerWin的空位,下棋,更新panel; 返回
play算法的實現如下:
if(canAttack()) { console.log("attack"); var attackPos = findAttackPos(); updatePanel(attackPos, computerVal); } else if(needDefend()) { console.log("defend"); var defendPos = findDefendPos(); updatePanel(defendPos, computerVal); } else if(firstStep()) { console.log("first"); updatePanel(firstPos, computerVal); running = true; } else { console.log("other"); if(panel[1][1] == 0) { updatePanel(firstPos, computerVal); return; } if(special()) { console.log("special"); var pos = findSpecialPos(); updatePanel(pos, computerVal); return; } var random = Math.floor(Math.random() * 2); if(panel[0][0] == 0 && panel[2][2] == 0) { var pos = (random == 0) ? 0 : 8; updatePanel(pos, computerVal); } else if(panel[0][2] == 0 && panel[2][0] == 0) { var pos = (random == 0) ? 2: 6; updatePanel(pos, computerVal); } else { var otherPos = findEmptyPos(); updatePanel(otherPos, computerVal); } }總結
在編碼的過程中遇到的一個難題就是JavaScript的數組對象,我在第一次調用play方法開頭輸出panel的時候,得到的是play執行后panel的值,后來請教一位大神,發現是因為panel是一個對象,因為對象遍歷引用的都是同一塊內存地址,所以一旦有改變,就全部改了。如果直接使用下標輸出每一個值的話是可以得到初始的值的,也可以用JSON方法將數組字符串,然后打印出來查看結果。
另外,也學會了如何在JavaScript里面封裝一個類,將私有方法寫在類的外面,需要暴露的方法寫在類里面。當然,還有很多需要學習的地方。繼續學習。
有時候一些東西看起來很簡單,或者聽到了很多次,心里面覺得實現起來應該很簡單的,沒什么了不起,覺得不以為然,但只有真正去實踐出來的時候才能體會到其中的樂趣和思想,才能真正的掌握。所以,盡情的去DO。
本文較短,如果還有什么疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。
如果本文對你有幫助,望大力點推薦。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79310.html
摘要:如果上述兩種情況均不存在,當發現,位置是空時,電腦先下這一步。其他情況均隨意落子。 朋友們,我們還記得以前上課經常和同桌玩起井字棋,那么我們就當我們回憶童年,現在也...
摘要:玩家選擇開始游戲后,出現雷盤,并且隨機布置雷。雷盤的數組大小為,方便計算掃雷時周圍雷的數量,并防止數組越界。放置布置的雷的信息放置排查出雷的信息初始化雷盤初始化展示界面打印展示界面效果如下布置雷隨機在數組中讓十個變成作為雷。 目錄 前言 一、游戲思路 二、游戲框架 1.菜單界面 1.菜單:...
摘要:三子棋目錄一問題介紹三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋 目錄 一、問題介紹 ? ? ? ? 三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋的游戲規則十分的簡單: ...
摘要:文章目錄前言正文一,游戲實現基本流程二游戲實現步驟創建工程及分配功能給頭文件上內容當當當,主函數出場游戲函數里面打印游戲菜單棋盤初始化打印棋盤玩家下棋電腦下棋判斷結果三游戲結果演示恭喜友友獲勝啦電腦獲勝,很遺憾,再接再厲 ...
閱讀 2984·2021-10-19 11:46
閱讀 979·2021-08-03 14:03
閱讀 2934·2021-06-11 18:08
閱讀 2905·2019-08-29 13:52
閱讀 2744·2019-08-29 12:49
閱讀 480·2019-08-26 13:56
閱讀 924·2019-08-26 13:41
閱讀 849·2019-08-26 13:35