1. 程式人生 > 程式設計 >JavaScript通過極大極小值演算法實現AI井字棋遊戲

JavaScript通過極大極小值演算法實現AI井字棋遊戲

話不多說直接上執行截圖:

JavaScript通過極大極小值演算法實現AI井字棋遊戲

黑棋是玩家的位置,紅色方是電腦。電腦會根據當前棋盤的情況選擇一個對自己有利卻對玩家不利的情況。

演算法可以實現電腦勝利,或者電腦和玩家平局。

程式碼如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>井字棋AI</title>
<style>
	.title {
		text-align: center;
	}
	
	.chess {
		display: block;
		/*變成塊級元素,使用margin居中*/
		margin: 50px auto;
		box-shadow: 5px 5px 5px #B9B9B9,-2px -2px 2px #EFEFEF;
		cursor: pointer;
	}
	
	div {
		text-align: center;
	}
	
	.restart {
		padding: 10px 20px;
		background-color: #EE82EE;
		border-radius: 5px;
		color: white;
		cursor: pointer;
	}
</style>
</head>
 
<body>
	<h3 class="title">--井字棋--</h3>
	<canvas class="chess" width="450px" height="450px"></canvas>
	<div>
		<a class="restart" onclick="rst()">重新開始</a>
	</div>
</body>
 
<script>
	var chess = document.getElementsByClassName("chess")[0];
	var title = document.getElementsByClassName("title")[0];
	var context = chess.getContext("2d");
	context.strokeStyle = "#B9B9B9"
 
	window.onload = function() {
		drawChessBoard();
		Init()
	}
 
	function drawChessBoard() {
		for(var i = 0; i < 4; i++) {
			//設定橫線起始點座標
			context.moveTo(15,15 + i * 140)
			//設定橫線結束點座標
			context.lineTo(435,15 + i * 140)
			//連線2點
			context.stroke();
			//設定豎線
			context.moveTo(15 + i * 140,15)
			//設定橫線結束點座標
			context.lineTo(15 + i * 140,435)
			//連線2點
			context.stroke();
		}
	}
 
	//定義二維陣列標記棋子
	var chessboard = []
	for(var i = 0; i < 4; i++) {
		chessboard[i] = [];
		for(var j = 0; j < 4; j++) {
			chessboard[i][j] = 0;
		}
	}
 
	const NUMBER = 3
	const STEP = 9
	const MAN = 1
	const COMPUTER = -1
	const SEARCHDEPTH = 9
	const INT_MAX = 999999
	const INT_MIN = -1000000
 
	var player = 0
	var isGameOver = false
	var currentDepth = 0
	var bestP
osition = { x: 0,y: 0 } function Init() { for(let i = 0; i < NUMBER; i++) { for(let j = 0; j < NUMBER; j++) { chessboard[i][j] = 0 } } player = MAN isGameOver = false currentDepth = 0 } function isEnd() { let i = 0 let j = 0 var count = 0 for(i = 0; i < NUMBER; i++) { //行 count = 0; for(j = 0; j < NUMBER; j++) count += chessboard[i][j]; if(count == 3 || count == -3) return count / 3; } for(j = 0; j < NUMBER; j++) { //列 count = 0; for(i = 0; i < NUMBER; i++) count += chessboard[i][j]; if(count == 3 || count == -3) return count / 3; } count = 0; count = chessboard[0][0] + chessboard[1][1] + chessboard[2][2]; if(count == 3 || count == -3) return count / 3; count = chessboard[0][2] + chessboard[1][1] + chessboard[2][0]; if(count == 3 || count == -3) return count / 3; return 0; } function MaxMinSearch(depth) { var value = 0; if(player == MAN) value = INT_MIN; if(player == COMPUTER) value = INT_MAX; if(isEnd() != 0) { return Evaluate(); } if(depth == SEARCHDEPTH) { value = Evaluate(); return value; } for(let i = 0; i < NUMBER; i++) { for(let j = 0; j < NUMBER; j++) { if(chessboard[i][j] == 0) { if(player == MAN) { chessboard[i][j] = MAN; player = COMPUTER; var nextvalue = MaxMinSearch(depth + 1); player = MAN; if(value < nextvalue) { value = nextvalue; if(depth == currentDepth) { bestPosition.x = i; bestPosition.y = j; } } } else if(player == COMPUTER) { chessboard[i][j] = COMPUTER; player = MAN; var nextvalue = MaxMinSearch(depth + 1); player = COMPUTER; if(value > nextvalue) { value = nextvalue; if(depth == currentDepth) { bestPosition.x = i; bestPosition.y = j; } } }
chessboard[i][j] = 0; } } } return value; } function Logic(){ if (isGameOver) { if (isEnd() == MAN) { alert("遊戲結束 玩家勝利") } else if (isEnd() == COMPUTER) { alert("遊戲結束 電腦勝利") } else { alert("遊戲結束 平局") } } } function Evaluate() { var value = isEnd(); if(value == MAN) return INT_MAX; if(value == COMPUTER) return INT_MIN; } chess.onclick = function(event) { if(player != MAN) { return; } //獲取座標 var x = event.offsetX; var y = event.offsetY; x = Math.trunc((x - 15) / 140) y = Math.trunc((y - 15) / 140) ManPlay(x,y) if(isEnd() == 0 && currentDepth < 8) { ComputerPlay() if(isEnd() != 0) { isGameOver = true } } else { isGameOver = true } Logic() } function ManPlay(x,y) { chessboard[x][y] = MAN DrawBroad(x,y,MAN) currentDepth++ player = COMPUTER } function ComputerPlay() { MaxMinSearch(currentDepth) chessboard[bestPosition.x][bestPosition.y] = COMPUTER DrawBroad(bestPosition.x,bestPosition.y,COMPUTER) currentDepth++ player = MAN } //落子時繪畫棋盤 function DrawBroad(i,j,player) { context.beginPath(); context.arc(85 + i * 140,85 + j * 140,40,2 * Math.PI); //畫圓 context.closePath(); var color; if(player == MAN) { color = "#000"; } else { color = "red" } context.fillStyle = color; context.fill(); } function rst() { window.location.reload(); } </script> </html>

其中,程式碼的242行和244行中的

context.beginPath();
context.arc(85 + i * 140,2 * Math.PI); //畫圓
context.closePath();

分別是落筆和抬筆的操作。這樣可以避免canvas上畫圓時路徑相連的問題。

JqaLAn此這篇關於通過極大極小值演算法實現AI井字棋遊戲的文章就介紹到這了,更多相關Script井字棋遊戲內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!