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 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上画圆时路径相连的问题。 

到此这篇关于JavaScript通过极大极小值算法实现AI井字棋游戏的文章就介绍到这了,更多相关JavaScript井字棋游戏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript Canvas实现井字棋游戏

    本文实例为大家分享了JavaScript Canvas实现井字棋游戏的具体代码,供大家参考,具体内容如下 index.html <!DOCTYPE html> <html> <head> <title>Tic Tac Toe</title> <style> * { padding: 0; margin: 0; } body, html, #game { height: 100%; background: #FCFCFC; } #gam

  • vue实现井字棋游戏

    本文实例为大家分享了vue实现井字棋游戏的具体代码,供大家参考,具体内容如下 之前看react的教程时看到的小游戏,试着用vue做一个.右边的winner提示胜者,还没有胜者时提示下一个棋子的种类.restart按钮点击可重新开始.go to step可跳转到第n步. html: <div id="app"> <ul id="board" class="white normal"> <li class="s

  • python入门游戏之井字棋实例代码

    目录 井字棋简介 实例代码 总结 井字棋简介 井字棋又称三子棋,英文名为Tic Tac Toe.具体玩法为在一个3x3的棋盘上,一个玩家用X做棋子,另一个玩家用O做棋子,谁先在棋盘上的一行.一列或对角线上画满三个棋子,即可获胜,如果棋盘下满无人胜出,即为平局. 实例代码 #要用的函数,可以在主程序用到时再看 def panduan1(a,b):#判断是否获胜,返回1则证明此颜色的棋获胜 x=0 if x==0: for i in range(3):#检索二维数组的第i行 q=0;p=0 for

  • python实现带界面的井字棋小游戏

    目录 1.首先安装tkinter 2.初始化窗口 3.定义按钮 4.检查获胜的条件 今天我们用python+tkinter安装带界面的井字棋,效果如图所示. Tkinter 是 Python 的标准 GUI 库.Python 使用 Tkinter 可以快速的创建 GUI 应用程序.由于 Tkinter 是内置到 python 的安装包中.只要安装好 Python 之后就能 import Tkinter 库.而且 IDLE 也是用 Tkinter 编写而成.对于简单的图形界面 Tkinter 还是

  • C语言实现简单的井字棋游戏

    本文实例为大家分享了C语言实现简单井字棋游戏的具体代码,供大家参考,具体内容如下 1.什么是井字棋 井字棋相信大部分人都玩过 规则:双方轮流放子,当某一方的三个子连成一线(行,列,对角)时,该方获胜. 2.游戏前的准备 1. 菜单 游戏正式开始前我们可以为用户提供一个选择菜单,笔者做了一个最简单的游戏开始菜单: 代码: /*菜单*/ int menu() { printf("###########################\n"); printf("## 1.Play

  • 基于C语言实现井字棋游戏

    井字棋游戏要求在3乘3棋盘上,每行都相同或者每列都相同再或者对角线相同,则胜出.因此我们可以使用一个二维数组来表示棋盘,判断胜负只需要判断数组元素是否相同即可.具体我们可以分为以下几步来做: 1.创建维数组并进行初始化,如果仅仅是一个二维数组来表示棋盘,看起来不是很清楚,因此我们可以对棋盘边框用符号打印出来进行优化一下: //初始化棋盘 void init(char board[max_row][max_col]) { for (int row = 0; row < max_row; row++

  • JavaScript实现一个带AI的井字棋游戏源码

    最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个.首先界面应该问题不大,用html稍微写一下就可以.主要是人机对弈时的ai算法,如何使电脑方聪明起来,是值得思考一下的.开始游戏后,由玩家先行.那么站在计算机的角度,可以对多种情况进行分析,并按照重要程度赋予权值. 情况如下: 1.同一排(行.列.对角线)有且只有两个棋子,并且都是自己的,只要再进一步就能获胜,那么剩下的那个位置权值最高,优先级最大.赋予一级权值. 2.同一排(行.列.对角线)有且只有两个棋子,并且都是对

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

    话不多说直接上运行截图: 黑棋是玩家的位置,红色方是电脑.电脑会根据当前棋盘的情况选择一个对自己有利却对玩家不利的情况. 算法可以实现电脑胜利,或者电脑和玩家平局. 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>井字棋AI</title> <style> .title { text-align: center; } .

  • python实现井字棋游戏

    本文实例介绍了python实现井字棋游戏的方法,分享给大家,具体内容如下 windows7下python3.4.0编译运行通过.由于采用了cmd调用,所以与Linux不兼容,无法在Linux下运行. 游戏就是井字棋,小键盘上的数字位置对应棋盘位置. #本游戏python3.4.0下编写调试,只能在windows下运行. import random import subprocess import time #定义函数 def draw_board(the_board): subprocess.c

  • C++实现井字棋游戏

    本文实例为大家分享了C++实现井字棋游戏的具体代码,供大家参考,具体内容如下 初步实现双玩家输入,操作游戏. 下一步将实现人机博弈. #include<iostream> using namespace std; void Player1(void); //玩家1输入(操作)函数 void Player2(void); //玩家2输入(操作)函数 void game_judge(void); //输赢判断 void game_start(void); //游戏开始 int rows = 3,c

  • python实现简单的井字棋游戏(gui界面)

    项目输出 项目先决条件 要使用python构建井字游戏,我们需要tkinter模块和python的基本概念 Tkinter模块是用于渲染图形的标准图形用户界面. Tkinter.messagebox用于显示消息框 要安装tkinter模块,我们在命令提示符下使用了pip install命令: pip install tkinter 项目文件结构 这些是使用python构建井字游戏的步骤: 导入模块 初始化窗口 检查结果的功能 检查获胜者的功能 定义标签和按钮 1.导入模块 from tkinte

  • C语言实现井字棋游戏

    本文实例为大家分享了C语言实现井字棋游戏的具体代码,供大家参考,具体内容如下 首先,我们需要一个大体的思路,先进行宏观规划,再对细节进行实现. 比如: 1.首先需要一个菜单面板作以修饰,在这个面板上,玩家可以选择进入游戏或者退出游戏. 2.需要一个游戏程序,这个是核心. 差不多就是这两个了,我们可以先把这个写下来,这样也可以方便后面使用,像这样: void Game(); int Menu();//这里Menu之所以用int,是为了用返回值来确定是否退出游戏,并非唯一,也非最佳,读者自己尝试 为

  • C语言实现简易井字棋游戏

    井子棋承载了每个人孩童时的美好时光,小到书本.纸张,大到课桌.墙壁,总能找到井字棋盘的痕迹.今天我们就来实际操作一番,用C语言完成一个简单的井字棋游戏,让我们一起重温美好. 棋盘如下: **功能描述:**棋盘共分为九个格子,一方执"O"为棋,一方执"X"为棋,双方依次选择格子.己方棋子率先连成三子的获胜,若棋盘占满仍未分胜负,则打成平局. 具体功能实现: 1.在页面选择玩家vs玩家,或玩家vs电脑 2.玩家下棋时,输入对应格子的坐标 3.电脑下棋时,使用随机值选择坐

随机推荐