JS五子棋(AI)

2023-05-16

JS五子棋(AI)

跟随算法:白棋始终跟随当前黑棋周围

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>五子棋</title>
		<style>
			#map {
				background-color: saddlebrown;
				border-radius: 10px;
			}
		</style>
	</head>
	<body>
		<canvas id="map" height="800" width="800"></canvas>
		<script>
			//画棋盘
			/** @type {HTMLCanvasElement} */
			var mapcanv = document.getElementById("map");
			var ctx = mapcanv.getContext("2d");
			for (let i = 1; i < 16; i++) {
				ctx.beginPath();
				ctx.moveTo(50 * i, 50);
				ctx.lineTo(50 * i, 750);
				ctx.stroke();
				ctx.beginPath();
				ctx.moveTo(50, 50 * i);
				ctx.lineTo(750, 50 * i);
				ctx.stroke();
			}
			//棋子信息
			var chessinfo = [{
				'name': '黑子',
				'color': 'black'
			}, {
				'name': '白子',
				'color': 'white'
			}];
			var chessrec = [];
			//当前棋子0:黑,1:白
			let chess = 0;
			let win = false;


			//画棋子
			function setChess(x, y, c) {
				ctx.save();
				ctx.beginPath();
				ctx.fillStyle = c;
				ctx.arc(x, y, 25, 0, 2 * Math.PI);
				ctx.fill();
				ctx.restore();
			}

			//点击事件监听
			mapcanv.addEventListener('click', function(ev) {
				let x = Math.round(ev.offsetX / 50);
				let y = Math.round(ev.offsetY / 50);

				if (!putChess(x, y)) {
					return;
				}

				if (win) return;

				aiputChess(x, y);
			})

			//玩家落在子,判断落子的范围与胜负
			function putChess(x, y) {

				let put = false;

				let pos = x + '-' + y;

				if (x * y > 0 && x < 16 && y < 16 && !chessrec.includes(pos)) {

					setChess(x * 50, y * 50, chessinfo[chess].color);

					chessrec.push(pos);

					if (chessrec.length >= 9)
						checkover(x, y, chess);

					chess ^= 1;

					put = true;
				}
				return put;
			}

			// 跟随下算法
			function aiputChess(x, y) {

				outer: for (let i = -1; i < 2; i++) {
					for (let j = -1; j < 2; j++) {
						if (putChess(x + i, y + j))
							break outer;
					}
				}

			}


			function checkover(x, y, ch) {
				let chs = chessrec.filter((n, i) => i % 2 == ch);
				win = judgewin_5(x, y).some(arr => arr.every(n => chs.includes(n)))
				if (win) {
					setTimeout(() => {
						alert(`恭喜${chessinfo[ch].name}获胜`, 100);
						location.reload();
					})
				}
				return win;

			}

			function judgewin_9(x, y) {
				var wins = [
					[],
					[],
					[],
					[]
				];
				for (let i = -4; i <= 4; i++) {
					let hx = (x + i) > 0 && (x + i) < 16,
						zx = (y + i) > 0 && (y + i) < 16,
						zxzx = (y - i) < 16 && (y - i) > 0
					//横向9子,注意${}中为反单引号,用于字符串拼接
					if (hx) wins[0].push(`${x+i}-${y}`);
					//纵向9子
					if (zx) wins[1].push(`${x}-${y+i}`);
					//左上右下
					if (hx && zx) wins[2].push(`${x+i}-${y+i}`);
					//右上左下
					if (hx && zxzx) wins[3].push(`${x+i}-${y-i}`);
				}
				return wins.filter(arr => arr.length >= 5);
			}

			function judgewin_5(x, y) {
				var wins = [];
				judgewin_9(x, y).forEach(arr => {
					for (let i = 0; i < arr.length - 4; i++) {
						wins.push(arr.slice(i, i + 5));
					}
				})
				return wins;
			}
		</script>
	</body>
</html>

跟随算法+防守算法:基本能防住菜鸟的进攻

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>五子棋</title>
		<style>
			#map {
				background-color: saddlebrown;
				border-radius: 10px;
			}
		</style>
	</head>
	<body>
		<canvas id="map" height="800" width="800"></canvas>
		<script>
			//画棋盘
			/** @type {HTMLCanvasElement} */
			var mapcanv = document.getElementById("map");
			var ctx = mapcanv.getContext("2d");
			for (let i = 1; i < 16; i++) {
				ctx.beginPath();
				ctx.moveTo(50 * i, 50);
				ctx.lineTo(50 * i, 750);
				ctx.stroke();
				ctx.beginPath();
				ctx.moveTo(50, 50 * i);
				ctx.lineTo(750, 50 * i);
				ctx.stroke();
			}
			//棋子信息
			var chessinfo = [{
				'name': '黑子',
				'color': 'black'
			}, {
				'name': '白子',
				'color': 'white'
			}];
			var chessrec = [];
			//当前棋子0:黑,1:白
			let chess = 0;
			let win = false;


			//画棋子
			function setChess(x, y, c) {
				ctx.save();
				ctx.beginPath();
				ctx.fillStyle = c;
				ctx.arc(x, y, 25, 0, 2 * Math.PI);
				ctx.fill();
				ctx.restore();
			}

			//点击事件监听
			mapcanv.addEventListener('click', function(ev) {
				let x = Math.round(ev.offsetX / 50);
				let y = Math.round(ev.offsetY / 50);

				if(!putChess(x, y)){
				return;}

				if (win) return;

				if(!aiputChess(x, y)){
					aiputChessfollow(x,y);
				}
			})

			//玩家落在子,判断落子的范围与胜负
			function putChess(x, y) {

				let put = false;

				let pos = x + '-' + y;

				if (x * y > 0 && x < 16 && y < 16 && !chessrec.includes(pos)) {

					setChess(x * 50, y * 50, chessinfo[chess].color);

					chessrec.push(pos);

					if (chessrec.length >= 9)
						checkover(x, y, chess);

					chess ^= 1;

					put = true;
				}
				return put;
			}
			
			// 跟随下算法
					function aiputChessfollow(x,y) {
			
					outer:for (let i = -1; i < 2; i++) {
							for (let j = -1; j < 2; j++) {
								if (putChess(x+i, y+j))
									break outer;
			                }
			            }
			
					}

			// 防守算法
			function aiputChess(x, y) {
				
				//得到目前所有黑棋位置
				let chs = chessrec.filter((n, i) => i % 2 == 0);
				//获取当前位置所有能赢的5子数组
				let arrs = judgewin_5(x,y);
				
				for(let k=0;k<arrs.length;k++){
					let arr = arrs[k];
					//定义一临时数组,如已下黑子中有此数组元素,则删除此元素
					//注意要用浅复制,以下两种方法都可以
					// let temp = arr.slice();
					let temp = arr.concat();
					for (let j = 0; j < arr.length; j++) {
						//从能赢的数组中取出一子
						let pos = arr[j];						
						for (let i = 0; i < chs.length; i++) {							
							if (chs[i] == pos) {
								temp.splice(temp.indexOf(chs[i]),1);								
							}
						}
						//如临时数组中剩下1或2个元素,则说明黑棋已经活三或冲四
						if(temp.length<=2&&temp.length>0){
							let posset=temp[0];
							if(temp.length==2){
							   posset = temp[1];
							}
							
							let posxy = posset.split('-');
							let xp=posxy[0];
							let yp=posxy[1];							
							console.log(posset);
							if(putChess(xp,yp)){
							return true;}
						}
					}
				}
				return false;

			}


			function checkover(x, y, ch) {
				let chs = chessrec.filter((n, i) => i % 2 == ch);
				win = judgewin_5(x, y).some(arr => arr.every(n => chs.includes(n)))
				if (win) {
					setTimeout(() => {
						alert(`恭喜${chessinfo[ch].name}获胜`, 100);
						location.reload();
					})
				}
				return win;

			}

			function judgewin_9(x, y) {
				var wins = [
					[],
					[],
					[],
					[]
				];
				for (let i = -4; i <= 4; i++) {
					let hx = (x + i) > 0 && (x + i) < 16,
						zx = (y + i) > 0 && (y + i) < 16,
						zxzx = (y - i) < 16 && (y - i) > 0
					//横向9子,注意${}中为反单引号,用于字符串拼接
					if (hx) wins[0].push(`${x+i}-${y}`);
					//纵向9子
					if (zx) wins[1].push(`${x}-${y+i}`);
					//左上右下
					if (hx && zx) wins[2].push(`${x+i}-${y+i}`);
					//右上左下
					if (hx && zxzx) wins[3].push(`${x+i}-${y-i}`);
				}
				return wins.filter(arr => arr.length >= 5);
			}

			function judgewin_5(x, y) {
				var wins = [];
				judgewin_9(x, y).forEach(arr => {
					for (let i = 0; i < arr.length - 4; i++) {
						wins.push(arr.slice(i, i + 5));
					}
				})
				return wins;
			}
		</script>
	</body>
</html>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JS五子棋(AI) 的相关文章

  • Android 11 update-api 遇到的问题

    1 缺少 非空判断 error log Missing nullability on method 96 getSecurityRestrictPwd 96 return MissingNullability import android
  • linux 文件 目录 默认权限

    结论 在linux系统中任何文件 目录都有一定的权限 xff0c 对于新创建的文件或目录 xff0c 也会有默认的访问权限 可能是出于安全的考虑 xff0c linux系统新建文件默认没有执行权限 xff0c 其最大权限为rw rw rw
  • centos 7 安装xfce 4桌面环境

    默认情况下 xff0c 完整安装的CentOS 7将安装GNOME图形用户界面 xff08 GUI xff09 xff0c 并且将在系统启动后加载 但是 xff0c 如果我们安装的CentOS没有安装GUI xff0c 那么我们总是可以稍后
  • Android 屏幕处于横屏状态 旋转180度界面切换显示

    span span public SreenOrientationListener mSreenOrientationListener span span mSreenOrientationListener 61 new SreenOrie
  • linux 桌面管理器 xfce 用户自动登录

    vi etc lightdm lightdm conf SeatDefaults autologin user 61 username 需要登录的用户名 autologin user timeout 61 delay
  • python 并行计算 pathos模块 简介

    目录 pathos模块 1 pathos自身的多进程方法 xff08 pathos multiprocessing ProcessPool pathos multiprocessing ProcessingPool pathos pools
  • 自然对数的底“e”的由来

    目录 一 神奇的 加减术 二 约翰 纳皮尔 xff08 John Napier xff09 的伟大贡献 发明对数 三 e在哪里 xff1f 是如何出现并逐步确认的呢 xff1f xff08 一 xff09 在制作对数表的过程中更加深入认识e
  • postgresql 报错 FATAL: no pg_hba.conf entry for host 未配置允许远程连接 解决方法

    目录 错误现象 问题原因 解决方案 1 进入到data目录下 xff0c 找到pg hba conf文件 2 修改文件 3 进入到postgres用户下 xff0c 执行命名 4 连接成功 错误现象 问题原因 这是在远程连接时pg hba
  • js javascript 解决 强制关注才能阅读

    问题现象 xff1a 强制关注 才能展开看文章 解决方法 xff1a chrome浏览器 打开文章网页 快捷键F12 然后切换到Console界面 复制一下代码回车 就可以阅读全部文章了 var article content 61 doc
  • linux 查看系统已安装内核

    目录 1 RHEL CentOS Fedora 2 Debian Ubuntu Linux Mint 3 SUSE openSUSE 4 Arch Linux 1 RHEL CentOS Fedora 在终端中执行如下命令查看已安装的 Li
  • win11 报错 你的IT管理员已经限制对此应用一些区域的访问 解决方法

    你的IT管理员已经限制对此应用一些区域的访问 你尝试访问的项目不可用 有关详细 请与你的IT支持人员联系 1 按下win 43 s xff0c 在框中输入cmd xff0c 右键管理员身份运行 2 在命令提示符中输入 reg add HKE
  • HTTPS和HTTP的区别

    什么是 HTTPS HTTPS 基于安全套接字层的超文本传输协议 或者是 HTTP over SSL 是一个 Netscape 开发的 Web 协议 你也可以说 xff1a HTTPS 61 HTTP 43 SSL HTTPS 在 HTTP
  • 正则表达式在线自动生成器

    正则表达式的强大众所周知 xff0c 它令程序员的头痛程度也数一数二的 最近我发现了一个网站 xff0c txt2re xff0c 能够自动为你生成正则表达式 xff0c 而且很灵活 xff0c 在这里推荐一下 网址 https www t
  • transfer-encoding:chunked的含义

    Transfer Encoding chunked 表示输出的内容长度不能确定 xff0c 普通的静态页面 图片之类的基本上都用不到这个 但动态页面就有可能会用到 xff0c 但我也注意到大部分asp php asp net动态页面输出的时
  • 回首2013,展望2014

    此刻值此2013年末 xff0c 明天便是元旦 近日浏览CSDN论坛时 xff0c 发现有许多的坛友都在写2013年度总结 xff0c 博客作为个人的名片 xff0c 也决定开始尝试写博客 xff0c 我的第一篇博客就是关于2013年度总结
  • i tell you 微软各种 操作系统 应用程序 开发工具 下载

    I tell you 提供微软系各种操作系统 xff08 win7 xp win10 xff09 应用程序 xff08 office project visio等 xff09 开发人员工具 xff08 visual C 43 43 visu
  • docker 设置国内镜像源

    目录 国内加速地址 修改方法 国内加速地址 1 Docker中国区官方镜像 https registry docker cn com 2 网易 http hub mirror c 163 com 3 ustc https docker mi
  • Docker网络代理设置

    背景 在一些实验室环境 xff0c 服务器没有直接连接外网的权限 xff0c 需要通过网络代理 我们通常会将网络代理直接配置在 etc environment etc profile之类的配置文件中 xff0c 这对于大部分操作都是可行的
  • android布局优化(ViewStub)

    页面中有些布局在初始化时没必要显示 xff0c 但是又不得不事先在布局文件中写好 xff0c 虽然设置成了invisible或gone xff0c 但是在初始化时还是会加载 xff0c 这无疑会影响页面加载速度 针对这一情况 xff0c A
  • iOS类似Android的ViewPager

    WhdeViewPager 类似安卓的 ViewPager Android ViewPager GitHub https github com whde WhdeViewPager 效果如下 使用 viewPager 61 WhdeView

随机推荐

  • ubuntu怎么切换到root用户,切换到root账号方法

    ubuntu怎么切换到root用户 xff0c 使用su root命令 xff0c 去切换到root权限 xff0c 会提示输入密码 xff0c 可是如何也输不对 xff0c 提示 Authentication failure 或者是提示认
  • left join 基本用法

    废话不多说 xff0c 来看例子 一 建表 xff0c 导入测试数据 create table temp1 aid VARCHAR2 5 not null car VARCHAR2 10 not null create table temp
  • Ubuntu系统与Linux常用命令

    目录 一 Ubuntu系统 xff1a 1 Ubuntu目录的简介2 Ubuntu与人交互3 人与Linux系统进行交互1 如何打开一个终端 xff1a 2 终端命令提示 4 Ubuntu命令的组成1 命令目的 xff1a 2 命令的格式
  • STM32串口打印输出乱码的解决办法

    前言 最近在试用uFUN开发板 xff0c 下载配套的Demo程序 xff0c 串口数据输出正常 xff0c 当使用另一个模板工程 xff0c 调用串口printf调试功能时 xff0c 输出的却是乱码 xff0c 最后发现是外部晶振频率不
  • 扬州大学信息工程学院2022届考研情况分析(主要针对专业课为858程序设计与数据结构的专业)

    作者 xff1a 64 江上 酒 23扬大信工考研交流群 xff1a 714584589 今年初试专业课为858程序设计与数据结构的人数达475人 xff0c 进入复试的共计118人 xff08 含计科 软工及电子信息各个方向 xff09
  • Android(12)浅析 偏好设置 Preference(一)

    Android 12 浅析 偏好设置 Preference xff08 一 xff09 官方基本用法 xff1a https developer android google cn guide topics ui settings 效果演示
  • 扬州大学信息工程学院2023届考研情况分析(针对858计算机专业基础的所有考生)

    扬州大学信息工程学院2023届考研情况分析 xff08 针对858计算机专业基础的所有考生 xff09 作者 xff1a 64 江上 酒 24扬大信工考研交流群 xff1a 714584589 进入复试的基本要求及各方向招生的详细计划如下图
  • Spring启动类源码学习小记

    现在面试Java 的 xff0c 都必备SpringBoot了 xff0c 一说SpringBoot xff0c 面试官又喜欢问底层 xff0c 我也是这种形式主义的受害者之一 xff0c 但是还别说 xff0c 自从看了底层源码 xff0
  • 电脑桌面美化(Win10)

    这是你的电脑桌面 而有人的桌面是这样的 这样的 有的人会把桌面图标放到dock栏里 xff0c 再把任务栏变成透明的 xff0c 再换个动态壁纸 xff0c 在加个频谱听听音乐 各种花里胡哨的 xff0c 是不是很羡慕 而电脑桌面完全取决于
  • 总结2014——迷茫以及迷茫过后的坚持

    首先 xff0c 借用一句话和大家共勉 xff1a 少一些功利主义的追求 xff0c 多一些不为什么的坚持 xff01 xff01 不知不觉15年也快过了1个月了 xff0c 还是想着要为14年做一下总结 xff1a 记录一下自己的历程 今
  • 无人机运动学控制中的坐标系,及惯性坐标系与机体坐标系之间的矩阵转换 欧拉角

    一 无人机控制中的坐标系 无人机运动学中 xff0c 有三种需要了解的坐标系 1 1 地球中心坐标系 xff08 ECEF xff09 地球中心坐标系 xff0c 即坐标系原点位于地心 X轴通过格林尼治线和赤道线的交点 xff0c 正方向为
  • 无人机飞控算法-姿态估计-欧拉角-旋转矩阵-四元数

    无人机飞控算法 姿态估计 此系列记录了我理解的卡尔曼滤波从0到1的过程 xff0c 从姿态估计到位置估计 xff0c 我们从核心点一个个出发 xff0c 并结合实际模块的应用来一一揭开卡尔曼滤波的神秘面纱 提示 xff1a 在系列文章中 x
  • bash下变量PS1的完整理解

    本文并不会讲解如何设置PS1以获得你喜欢的提示符 xff1b 本文会围绕PS1这个变量 xff0c 就其涉及到的一些概念展开讨论 导言 ubuntu 的默认 shell 是 bash xff0c bash 下有个变量 PS1 xff0c 我
  • 我的世界Mod整合包中的Mod下载

    MC中Mod整合包有时通过启动器无法正常安装 xff0c 此时可以其中通过提供的manifest json文件获取其在curseforge网站中的信息 文件中的projectID是Mod的ID fileID是对应版本文件的ID 通过这两个值
  • 使用OpenCV给图片添加Logo

    import cv2 import numpy as np imgcat 61 cv2 imread 34 d img cat jpg 34 imglogo 61 cv2 imread 34 d img logo jpg 34 imglog
  • Minecraft中Python编程

    安装Raspberry Jam Mod Raspberry Jam Mod是arpruss为Minecraft开发的插件 xff0c 在PC版Minecraft中的实现了树莓派版的Python接口 可以从这里下载最新版本 作者提供了自动安装
  • 打开AS提示错误弹框缺少com.android.tools.design.org.jetbrains.android插件

    打开AS提示错误弹框缺少com android tools design org jetbrains android插件 今个准备升级一下AS来着 xff0c 然后出现了这个问题 xff0c 原因是我屏蔽了Kotlin插件 解决方法 xff
  • 推箱子游戏JS实现

    参考以下教学视频编写 教学视频 xff1a Canvas画布实现推箱子游戏 HTML5前端设计JavaScript原生开发 哔哩哔哩 bilibili 箱子地图 Boxdata js 1 xff1a 围墙 2 xff1a 目标点 3 xff
  • 五子棋游戏JS实现

    参考教学视频 xff1a Canvas画布案例 五子棋 1 基础 哔哩哔哩 bilibili 1 棋盘设计 xff0c 落子功能 lt DOCTYPE html gt lt html gt lt head gt lt meta charse
  • JS五子棋(AI)

    JS五子棋 AI xff09 跟随算法 xff1a 白棋始终跟随当前黑棋周围 span class token doctype span class token punctuation lt span span class token do