您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery | 小程序 |

JavaScript通过极大极小值算法实现AI井字棋游戏

51自学网 2022-02-21 13:35:27
  javascript

话不多说直接上运行截图:

黑棋是玩家的位置,红色方是电脑。电脑会根据当前棋盘的情况选择一个对自己有利却对玩家不利的情况。

算法可以实现电脑胜利,或者电脑和玩家平局。

代码如下:

<!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 bestPosition = {		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, 0, 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, 85 + j * 140, 40, 0, 2 * Math.PI); //画圆context.closePath();

分别是落笔和抬笔的操作。这样可以避免canvas上画圆时路径相连的问题。
下载地址:
Vue获取表单数据的方法
利用momentJs做一个倒计时组件(实例代码)

万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。