资讯专栏INFORMATION COLUMN

Vue 实现人机五子棋

Object / 2005人阅读

摘要:预览效果源码核心代码记录是否走过所有赢法数量赢法数组我方赢法的统计数组计算机赢法的统计数组初始化填充数组是否走过赢法数组横竖斜反斜赢法的统计数组绘制水印绘制棋盘落子实现我方落子统计赢法你赢了计算机落子最大分数所在坐标遍历棋盘遍

预览效果

github源码

核心代码

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://unnue.com/article/50

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/19865.html

相关文章

  • Vue 实现人机子棋

    摘要:预览效果源码核心代码记录是否走过所有赢法数量赢法数组我方赢法的统计数组计算机赢法的统计数组初始化填充数组是否走过赢法数组横竖斜反斜赢法的统计数组绘制水印绘制棋盘落子实现我方落子统计赢法你赢了计算机落子最大分数所在坐标遍历棋盘遍 预览效果 github源码 showImg(https://segmentfault.com/img/bVbk02l?w=450&h=450); 核心代码 ...

    codeGoogle 评论0 收藏0
  • JS+canvas实现子棋人机大战

    摘要:五子棋人机大战创建实例是否结束我电脑所有棋子已经落下的棋子赢法总数所有赢法统计我的赢法统计电脑赢法统计初始化初始化生成棋盘棋盘初始化鼠标移动聚焦功能实现算法初始化落子功能实现生成棋盘初始化生成不是的倍数棋盘列初始化棋盘棋盘初始化画棋盘画 JS+canvas五子棋人机大战 1. 创建实例 function Gobang () { this.over = false; // 是否结...

    sutaking 评论0 收藏0
  • java子棋项目

    摘要:由于二维数组中代表黑棋,代表白棋,,的数字集合即可代表棋盘上的棋子情况,可以对整个棋盘数组进行遍历,得到每一个可以下的位置的八个方向的棋子情况。 java基本入门之后,迎来第一个挑战——五子棋设计 寒假的时候,靠着看java手册,实现了双人对战并判断输赢的功能。但是一直卡在了人机对战上面。 之后随着学习的深入,终于实现。 以下详细的叙述一下整体的设计过程: 首先是五子棋窗口界面的设计,...

    coordinate35 评论0 收藏0

发表评论

0条评论

Object

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<