耀极客论坛

 找回密码
 立即注册
查看: 780|回复: 0

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

[复制链接]

336

主题

318

帖子

22万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
220555
发表于 2022-5-9 01:00:51 | 显示全部楼层 |阅读模式
  极小极大值搜索算法是一种零和算法,是用来最小化对手的利益,最大化自己的利益的算法。极小极大之搜索算法常用于棋类游戏等双方较量的游戏和程序,算是一种电脑AI算法。本文将介绍通过这个算法实现的一个井字棋游戏,需要的可以参考一下
  话不多说直接上运行截图:

  黑棋是玩家的位置,红色方是电脑。电脑会根据当前棋盘的情况选择一个对自己有利却对玩家不利的情况。
  算法可以实现电脑胜利,或者电脑和玩家平局。
  代码如下:
  1. ‹!DOCTYPE html>
  2. ‹html>
  3. ‹head>
  4. ‹meta charset="UTF-8">
  5. ‹title>井字棋AI‹/title>
  6. ‹style>
  7. .title {
  8. text-align: center;
  9. }
  10. .chess {
  11. display: block;
  12. /*变成块级元素,使用margin居中*/
  13. margin: 50px auto;
  14. box-shadow: 5px 5px 5px #B9B9B9, -2px -2px 2px #EFEFEF;
  15. cursor: pointer;
  16. }
  17. div {
  18. text-align: center;
  19. }
  20. .restart {
  21. padding: 10px 20px;
  22. background-color: #EE82EE;
  23. border-radius: 5px;
  24. color: white;
  25. cursor: pointer;
  26. }
  27. ‹/style>
  28. ‹/head>
  29. ‹body>
  30. ‹h3 class="title">--井字棋--‹/h3>
  31. ‹canvas class="chess" width="450px" height="450px">‹/canvas>
  32. ‹div>
  33. ‹a class="restart" >重新开始‹/a>
  34. ‹/div>
  35. ‹/body>
  36. ‹script>
  37. var chess = document.getElementsByClassName("chess")[0];
  38. var title = document.getElementsByClassName("title")[0];
  39. var context = chess.getContext("2d");
  40. context.strokeStyle = "#B9B9B9"
  41. window.onload = function() {
  42. drawChessBoard();
  43. Init()
  44. }
  45. function drawChessBoard() {
  46. for(var i = 0; i ‹ 4; i++) {
  47. //设置横线起始点坐标
  48. context.moveTo(15, 15 + i * 140)
  49. //设置横线结束点坐标
  50. context.lineTo(435, 15 + i * 140)
  51. //连接2点
  52. context.stroke();
  53. //设置竖线
  54. context.moveTo(15 + i * 140, 15)
  55. //设置横线结束点坐标
  56. context.lineTo(15 + i * 140, 435)
  57. //连接2点
  58. context.stroke();
  59. }
  60. }
  61. //定义二维数组标记棋子
  62. var chessboard = []
  63. for(var i = 0; i ‹ 4; i++) {
  64. chessboard[i] = [];
  65. for(var j = 0; j ‹ 4; j++) {
  66. chessboard[i][j] = 0;
  67. }
  68. }
  69. const NUMBER = 3
  70. const STEP = 9
  71. const MAN = 1
  72. const COMPUTER = -1
  73. const SEARCHDEPTH = 9
  74. const INT_MAX = 999999
  75. const INT_MIN = -1000000
  76. var player = 0
  77. var isGameOver = false
  78. var currentDepth = 0
  79. var bestPosition = {
  80. x: 0,
  81. y: 0
  82. }
  83. function Init() {
  84. for(let i = 0; i ‹ NUMBER; i++) {
  85. for(let j = 0; j ‹ NUMBER; j++) {
  86. chessboard[i][j] = 0
  87. }
  88. }
  89. player = MAN
  90. isGameOver = false
  91. currentDepth = 0
  92. }
  93. function isEnd() {
  94. let i = 0
  95. let j = 0
  96. var count = 0
  97. for(i = 0; i ‹ NUMBER; i++) { //行
  98. count = 0;
  99. for(j = 0; j ‹ NUMBER; j++)
  100. count += chessboard[i][j];
  101. if(count == 3 || count == -3)
  102. return count / 3;
  103. }
  104. for(j = 0; j ‹ NUMBER; j++) { //列
  105. count = 0;
  106. for(i = 0; i ‹ NUMBER; i++)
  107. count += chessboard[i][j];
  108. if(count == 3 || count == -3)
  109. return count / 3;
  110. }
  111. count = 0;
  112. count = chessboard[0][0] + chessboard[1][1] + chessboard[2][2];
  113. if(count == 3 || count == -3)
  114. return count / 3;
  115. count = chessboard[0][2] + chessboard[1][1] + chessboard[2][0];
  116. if(count == 3 || count == -3)
  117. return count / 3;
  118. return 0;
  119. }
  120. function MaxMinSearch(depth) {
  121. var value = 0;
  122. if(player == MAN) value = INT_MIN;
  123. if(player == COMPUTER) value = INT_MAX;
  124. if(isEnd() != 0) {
  125. return Evaluate();
  126. }
  127. if(depth == SEARCHDEPTH) {
  128. value = Evaluate();
  129. return value;
  130. }
  131. for(let i = 0; i ‹ NUMBER; i++) {
  132. for(let j = 0; j ‹ NUMBER; j++) {
  133. if(chessboard[i][j] == 0) {
  134. if(player == MAN) {
  135. chessboard[i][j] = MAN;
  136. player = COMPUTER;
  137. var nextvalue = MaxMinSearch(depth + 1);
  138. player = MAN;
  139. if(value ‹ nextvalue) {
  140. value = nextvalue;
  141. if(depth == currentDepth) {
  142. bestPosition.x = i;
  143. bestPosition.y = j;
  144. }
  145. }
  146. } else if(player == COMPUTER) {
  147. chessboard[i][j] = COMPUTER;
  148. player = MAN;
  149. var nextvalue = MaxMinSearch(depth + 1);
  150. player = COMPUTER;
  151. if(value > nextvalue) {
  152. value = nextvalue;
  153. if(depth == currentDepth) {
  154. bestPosition.x = i;
  155. bestPosition.y = j;
  156. }
  157. }
  158. }
  159. chessboard[i][j] = 0;
  160. }
  161. }
  162. }
  163. return value;
  164. }
  165. function Logic(){
  166. if (isGameOver) {
  167. if (isEnd() == MAN) {
  168. alert("游戏结束 玩家胜利")
  169. } else if (isEnd() == COMPUTER) {
  170. alert("游戏结束 电脑胜利")
  171. } else {
  172. alert("游戏结束 平局")
  173. }
  174. }
  175. }
  176. function Evaluate() {
  177. var value = isEnd();
  178. if(value == MAN) return INT_MAX;
  179. if(value == COMPUTER) return INT_MIN;
  180. }
  181. chess.onclick = function(event) {
  182. if(player != MAN) {
  183. return;
  184. }
  185. //获取坐标
  186. var x = event.offsetX;
  187. var y = event.offsetY;
  188. x = Math.trunc((x - 15) / 140)
  189. y = Math.trunc((y - 15) / 140)
  190. ManPlay(x, y)
  191. if(isEnd() == 0 && currentDepth ‹ 8) {
  192. ComputerPlay()
  193. if(isEnd() != 0) {
  194. isGameOver = true
  195. }
  196. } else {
  197. isGameOver = true
  198. }
  199. Logic()
  200. }
  201. function ManPlay(x, y) {
  202. chessboard[x][y] = MAN
  203. DrawBroad(x,y,MAN)
  204. currentDepth++
  205. player = COMPUTER
  206. }
  207. function ComputerPlay() {
  208. MaxMinSearch(currentDepth)
  209. chessboard[bestPosition.x][bestPosition.y] = COMPUTER
  210. DrawBroad(bestPosition.x,bestPosition.y,COMPUTER)
  211. currentDepth++
  212. player = MAN
  213. }
  214. //落子时绘画棋盘
  215. function DrawBroad(i, j, player) {
  216. context.beginPath();
  217. context.arc(85 + i * 140, 85 + j * 140, 40, 0, 2 * Math.PI); //画圆
  218. context.closePath();
  219. var color;
  220. if(player == MAN) {
  221. color = "#000";
  222. } else {
  223. color = "red"
  224. }
  225. context.fillStyle = color;
  226. context.fill();
  227. }
  228. function rst() {
  229. window.location.reload();
  230. }
  231. ‹/script>
  232. ‹/html>
复制代码
  其中,代码的242行和244行中的
  1. context.beginPath();
  2. context.arc(85 + i * 140, 85 + j * 140, 40, 0, 2 * Math.PI); //画圆
  3. context.closePath();
复制代码
  分别是落笔和抬笔的操作。这样可以避免canvas上画圆时路径相连的问题。 
  到此这篇关于JavaScript通过极大极小值算法实现AI井字棋游戏的文章就介绍到这了,更多相关JavaScript井字棋游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2022-12-10 04:00 , Processed in 0.138959 second(s), 32 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表