Vue 实现人机五子棋
核心代码
export default { data () { return { chess: {}, context: {}, chessBoard: [], // 记录是否走过 me: true, count: 0, // 所有赢法数量 wins: [], // 赢法数组 myWin: [], // 我方赢法的统计数组 computerWin: [], // 计算机赢法的统计数组 over: false, } }, mounted () { setTimeout(_ => { this.init() }) }, methods: { // 初始化 init () { this.chess = this.$refs.canvas this.context = this.chess.getContext("2d") this.drawImage( _ => { this.drawChessBoard() }) this.fillArray() }, // 填充数组 fillArray () { // 是否走过 for (let i = 0; i < 15; i++) { this.chessBoard[i] = [] for (let j = 0; j < 15; j++) { this.chessBoard[i][j] = 0 } } // 赢法数组 for (let i = 0; i < 15; i++) { this.wins[i] = [] for (let j = 0; j < 15; j++) { this.wins[i][j] = [] } } // 横 for (let i = 0; i < 15; i++) { for (let j = 0; j < 11; j++) { for (let k = 0; k < 5; k++) { this.wins[i][j+k][this.count] = true } this.count++ } } // 竖 for (let i = 0; i < 15; i++) { for (let j = 0; j < 11; j++) { for (let k = 0; k < 5; k++) { this.wins[j+k][i][this.count] = true } this.count++ } } // 斜 for (let i = 0; i < 11; i++) { for (let j = 0; j < 11; j++) { for (let k = 0; k < 5; k++) { this.wins[i+k][j+k][this.count] = true } this.count++ } } // 反斜 for (let i = 0; i < 11; i++) { for (let j = 14; j > 3; j--) { for (let k = 0; k < 5; k++) { this.wins[i+k][j-k][this.count] = true } this.count++ } } // 赢法的统计数组 for (let i = 0; i < this.count; i++) { this.myWin[i] = 0 this.computerWin[i] = 0 } }, // 绘制水印 drawImage (callback) { const { context } = this const img = new Image() img.src = "/images/logo.svg" img.onload = _ => { context.drawImage(img, (450 - img.width)/2, (450 - img.height)/2, img.width, img.height) callback() } }, // 绘制棋盘 drawChessBoard () { const { context } = this context.strokeStyle = '#bfbfbf' for (let i = 0; i < 15; i++) { context.moveTo(15 + i * 30, 15) context.lineTo(15 + i * 30, 435) context.stroke() context.moveTo(15, 15 + i * 30) context.lineTo(435, 15 + i * 30) context.stroke() } }, // 落子实现 onStep (x, y, me) { const { context } = this context.beginPath() context.arc(15 + x * 30, 15 + y * 30, 13, 0, 2 * Math.PI) context.closePath() const gradient = context.createRadialGradient(15 + x * 30 + 2, 15 + y * 30 - 2, 13, 15 + x * 30 + 2, 15 + y * 30 - 2, 0) if (me) { gradient.addColorStop(0, '#0a0a0a') gradient.addColorStop(1, '#636766') } else { gradient.addColorStop(0, '#d1d1d1') gradient.addColorStop(1, '#f9f9f9') } context.fillStyle = gradient context.fill() }, // 我方落子 chessClick (e) { if (this.over) { return } if (!this.me) { return } const ox = e.offsetX const oy = e.offsetY const x = Math.floor(ox/30) const y = Math.floor(oy/30) if (this.chessBoard[x][y] === 0) { this.chessBoard[x][y] = 1 this.onStep(x, y, this.me) // 统计赢法 for (let k = 0; k < this.count; k++) { if (this.wins[x][y][k]) { this.myWin[k]++ this.computerWin[k] = 6 if (this.myWin[k] === 5) { alert('你赢了') this.over = true } } } if (!this.over) { this.me = !this.me this.computerAI() } } }, // 计算机落子 computerAI () { const myScore = [] const computerScore = [] let max = 0 // 最大分数 let u = 0, v = 0 // 所在坐标 for (let i = 0; i < 15; i++) { myScore[i] = [] computerScore[i] = [] for (let j = 0; j < 15; j++) { myScore[i][j] = 0 computerScore[i][j] = 0 } } // 遍历棋盘 for (let i = 0; i < 15; i++) { for (let j = 0; j < 15; j++) { if (this.chessBoard[i][j] === 0) { // 遍历所有赢法 for (let k = 0; k < this.count; k++) { if (this.wins[i][j][k]) { // 我方 if (this.myWin[k] === 1) { myScore[i][j] += 200 } else if (this.myWin[k] === 2) { myScore[i][j] += 400 } else if (this.myWin[k] === 3) { myScore[i][j] += 2000 } else if (this.myWin[k] === 4) { myScore[i][j] += 10000 } // 计算机 if (this.computerWin[k] === 1) { computerScore[i][j] += 220 } else if (this.computerWin[k] === 2) { computerScore[i][j] += 420 } else if (this.computerWin[k] === 3) { computerScore[i][j] += 2100 } else if (this.computerWin[k] === 4) { computerScore[i][j] += 20000 } } } // 比较分数 if (myScore[i][j] > max) { max = myScore[i][j] u = i v = j } else if (myScore[i][j] === max) { if (computerScore[i][j] > computerScore[u][v]) { u = i v = j } } if (computerScore[i][j] > max) { max = computerScore[i][j] u = i v = j } else if (computerScore[i][j] === max) { if (myScore[i][j] > myScore[u][v]) { u = i v = j } } } } } this.onStep(u, v, false) this.chessBoard[u][v] = 2 // 统计赢法 for (let k = 0; k < this.count; k++) { if (this.wins[u][v][k]) { this.computerWin[k]++ this.myWin[k] = 6 if (this.computerWin[k] === 5) { alert('计算机赢了') this.over = true } } } if (!this.over) { this.me = !this.me } } } }
也许是前端
大多是前端方面的内容
推荐阅读
仿抖音APP之微信小程序--00后爆笑动图gif
先上几张图看看 效果如下 未完待续…
jigsaw赞 1阅读 2.6k
从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...
乌柏木赞 172阅读 13.8k评论 10
手把手教你写一份优质的前端技术简历
不知不觉一年一度的秋招又来了,你收获了哪些大厂的面试邀约,又拿了多少offer呢?你身边是不是有挺多人技术比你差,但是却拿到了很多大厂的offer呢?其实,要想面试拿offer,首先要过得了简历那一关。如果一份简...
tonychen赞 152阅读 17.7k评论 5
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...
寒青赞 56阅读 8.4k评论 11
JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...
jenemy赞 48阅读 6.9k评论 12
从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...
乌柏木赞 75阅读 7k评论 16
再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...
libinfs赞 42阅读 6.8k评论 12
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。