基于JS實(shí)現(xiàn)經(jīng)典的井字棋游戲
井字棋作為我們在上學(xué)時(shí)代必玩的一款連珠游戲,你知道如何做到先手必然不會輸嗎?今天我們就用HTML、css、js來實(shí)現(xiàn)一款井字棋游戲。
先看成品
游戲初始化界面:
玩家獲勝
AI電腦獲勝
思路
生成棋盤
- 通過表格生成一個(gè)3*3的表格
- 然后通過css屬性隱藏部分邊框?qū)崿F(xiàn)井字棋盤
重新開始
- 清空文本數(shù)列刪除屬性
玩家落子
- 通過玩家點(diǎn)擊獲取id
- 通過id將點(diǎn)擊的表格塊設(shè)置為
O
電腦落子
- 通過算法來實(shí)現(xiàn)電腦最適合的塊id然后落子
代碼
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>井字棋</title> <link rel="stylesheet" href="css.css" rel="external nofollow" /> </head> <body> <table> <tr> <td class="cell" id="0"></td> <td class="cell" id="1"></td> <td class="cell" id="2"></td> </tr> <tr> <td class="cell" id="3"></td> <td class="cell" id="4"></td> <td class="cell" id="5"></td> </tr> <tr> <td class="cell" id="6"></td> <td class="cell" id="7"></td> <td class="cell" id="8"></td> </tr> </table> <div class="endgame"> <div class="text"></div> </div> <button onclick="startGame()">重新開始</button> <script src="js.js"></script> </body> </html>
CSS
* { margin: 0; padding: 0; } button { position: absolute; position: absolute; left: 50%; margin-left: -65px; top: 50px; } td { border: 2px solid #333; width: 100px; height: 100px; text-align: center; vertical-align: middle; font-family: '微軟雅黑'; font-style: italic; font-size: 70px; cursor: pointer; } table { /*margin: 30px auto;*/ position: absolute; left: 40%; top: 100px; border-collapse: collapse; } table tr:first-child td { border-top: 0; } table tr:last-child td { border-bottom: 0; } table tr td:first-child { border-left: 0; } table tr td:last-child { border-right: 0; } .endgame { display: none; width: 200px; height: 120px; background-color: rgba(205, 132, 65, 0.8); position: absolute; left: 40%; top: 180px; margin-left: 50px; text-align: center; border-radius: 5px; color: white; font-size: 2em; }
js
var origBoard; const huPlayer = 'O'; const aiPlayer = 'X'; const winCombos = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [6, 4, 2] ] /*獲取元素*/ const cells = document.querySelectorAll(".cell"); startGame(); function startGame () { document.querySelector(".endgame").style.display = "none"; //設(shè)置陣列點(diǎn) 創(chuàng)建9個(gè)數(shù)組元素,元素的鍵0到8 origBoard = Array.from(Array(9).keys()); // console.log(origBoard); for (var i = 0; i < cells.length; i++) { //把文本先設(shè)置為空 cells[i].innerHTML = ""; //刪除屬性知道已經(jīng)有人贏了 cells[i].style.removeProperty('background-color'); //點(diǎn)擊方塊 cells[i].addEventListener('click', turnClick, false); } } function turnClick (square) { //記住原來走過的方塊 if (typeof origBoard[square.target.id] == 'number') { //人類玩家點(diǎn)擊 turn(square.target.id, huPlayer); //由人類轉(zhuǎn)向AI玩家 if (!checkTie()) { //電腦玩家將棋子放到最合適的地方 turn(bestStep(), aiPlayer); } } } function turn (squareId, player) { //這些id給玩家 origBoard[squareId] = player; document.getElementById(squareId).innerHTML = player; //讓游戲進(jìn)行檢查 var gameWin = checkWin(origBoard, player); if (gameWin) { gameOver(gameWin); } } //判斷勝利 function checkWin (board, player) { let plays = board.reduce((a, e, i) => (e === player) ? a.concat(i) : a, []) let gameWin = null; //如果是屬于之前winCombos勝利組合 for (let [index, win] of winCombos.entries()) { if (win.every(Element => plays.indexOf(Element) > -1)) { //現(xiàn)在我們知道是哪一個(gè)組合勝利了 gameWin = { index: index, player: player }; break; } } return gameWin; } /*游戲結(jié)束*/ function gameOver (gameWin) { for (let index of winCombos[gameWin.index]) { //人類獲勝則為藍(lán)色 document.getElementById(index).style.backgroundColor = gameWin.player == huPlayer ? "blue" : "red"; } /*事件偵聽器刪除單擊,已經(jīng)結(jié)束了,不能再點(diǎn)擊*/ for (var i = 0; i < cells.length; i++) { cells[i].removeEventListener('click', turnClick, false); } declareWinner(gameWin.player == huPlayer ? "你贏了" : "你輸了"); } function emptySquares () { //過濾每一個(gè)元素,如果元素為number,返回所有方塊 return origBoard.filter(s => typeof s == 'number'); } /*AI最優(yōu)步驟*/ function bestStep () { //智能AI return minmax(origBoard, aiPlayer).index; } //檢查是否是平局 function checkTie () { if (emptySquares().length == 0) { for (var i = 0; i < cells.length; i++) { cells[i].style.backgroundColor = "green"; cells[i].removeEventListener('click', turnClick, false); } //誰獲勝了 // declareWinner("玩家獲勝"); return true; } else { //平局 return false; } } function declareWinner (who) { document.querySelector(".endgame").style.display = 'block'; document.querySelector(".endgame .text").innerHTML = who; } function minmax (newBoard, player) { //找到索引,空方塊功能設(shè)置為a var availSpots = emptySquares(newBoard); if (checkWin(newBoard, player)) { return { score: -10 }; } else if (checkWin(newBoard, aiPlayer)) { return { score: 20 }; } else if (availSpots.length === 0) { return { score: 0 }; } //之后進(jìn)行評估 var moves = []; //收集每個(gè)動作時(shí)的空白點(diǎn) for (var i = 0; i < availSpots.length; i++) { //然后設(shè)置空的索引號 var move = {}; move.index = newBoard[availSpots[i]]; newBoard[availSpots[i]] = player; if (player == aiPlayer) { //存儲對象,包括得分屬性 var result = minmax(newBoard, huPlayer); move.score = result.score; } else { //存儲對象,包括得分屬性 var result = minmax(newBoard, aiPlayer); move.score = result.score; } newBoard[availSpots[i]] = move.index; moves.push(move); } var bestMove; //如果是AI玩家,以非常低的數(shù)字和循環(huán)通過 if (player === aiPlayer) { var bestScore = -1000; for (var i = 0; i < moves.length; i++) { if (moves[i].score > bestScore) { bestScore = moves[i].score; bestMove = i; } } } else { var bestScore = 1000; for (var i = 0; i < moves.length; i++) { if (moves[i].score < bestScore) { bestScore = moves[i].score; bestMove = i; } } } return moves[bestMove]; }
以上就是基于JS實(shí)現(xiàn)經(jīng)典的井字棋游戲的詳細(xì)內(nèi)容,更多關(guān)于JS井字棋的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Javascript實(shí)現(xiàn)html轉(zhuǎn)pdf高清版(提高分辨率)
這篇文章主要介紹了Javascript將html轉(zhuǎn)成pdf高清版(提高分辨率),需要的朋友可以參考下2020-02-02Bootstrap編寫一個(gè)兼容主流瀏覽器的受眾門戶式風(fēng)格頁面
這篇文章主要介紹了Bootstrap編寫一個(gè)兼容IE8、谷歌等主流瀏覽器的受眾門戶式風(fēng)格頁面,感興趣的小伙伴們可以參考一下2016-07-07Axios?get?post請求傳遞參數(shù)的實(shí)現(xiàn)代碼
axios是基于promise用于瀏覽器和node.js的http客戶端,支持瀏覽器和node.js,能攔截請求和響應(yīng),這篇文章主要介紹了axios?get?post請求傳遞參數(shù)的操作代碼,需要的朋友可以參考下2022-11-11javascript+html5實(shí)現(xiàn)繪制圓環(huán)的方法
這篇文章主要介紹了javascript+html5實(shí)現(xiàn)繪制圓環(huán)的方法,實(shí)例分析了javascript實(shí)現(xiàn)html5基于canvas繪制圓環(huán)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07