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
        }
      }
    }
    }

原文地址:https://buluo.cc/article/50


也许是前端
大多是前端方面的内容

个人网站 buluo.cc

118 声望
2 粉丝
0 条评论
推荐阅读
仿抖音APP之微信小程序--00后爆笑动图gif
先上几张图看看 效果如下 未完待续…

jigsaw1阅读 2.6k

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木172阅读 13.8k评论 10

手把手教你写一份优质的前端技术简历
不知不觉一年一度的秋招又来了,你收获了哪些大厂的面试邀约,又拿了多少offer呢?你身边是不是有挺多人技术比你差,但是却拿到了很多大厂的offer呢?其实,要想面试拿offer,首先要过得了简历那一关。如果一份简...

tonychen152阅读 17.7k评论 5

封面图
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青56阅读 8.4k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy48阅读 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...

libinfs42阅读 6.8k评论 12

封面图

个人网站 buluo.cc

118 声望
2 粉丝
宣传栏