js小游戏 - 五子棋人机

github地址
在线地址

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="shortcut icon" href="" type="image/x-icon" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <style>
    canvas {
      display: block;
      margin: 50px auto;
      box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;
    }
  </style>
  <title>五子棋</title>
</head>

<body>
  <canvas id='chess' width="450px" height="450px"></canvas>
</body>
<script>
  var me = true;
  var over = false;
  var chessBoard = [];
  //赢法数组
  var win = [];
  //赢法统计数组
  var myWin = [];
  var computerWin = [];

  for (var i = 0; i < 15; i++) {
    chessBoard[i] = [];
    for (var j = 0; j < 15; j++) {
      chessBoard[i][j] = 0;
    }
  }
  for (var i = 0; i < 15; i++) {
    win[i] = [];
    for (var j = 0; j < 15; j++) {
      win[i][j] = [];
    }
  }

  var count = 0;
  //横线赢法
  for (var i = 0; i < 15; i++) {
    for (var j = 0; j < 11; j++) {
      for (var k = 0; k < 5; k++) {
        win[i][j + k][count] = true;
      }
      count++;
    }
  }
  //竖线赢法
  for (var i = 0; i < 15; i++) {
    for (var j = 0; j < 11; j++) {
      for (var k = 0; k < 5; k++) {
        win[j + k][i][count] = true;
      }
      count++;
    }
  }
  //斜线赢法
  for (var i = 0; i < 11; i++) {
    for (var j = 0; j < 11; j++) {
      for (var k = 0; k < 5; k++) {
        win[i + k][j + k][count] = true;
      }
      count++;
    }
  }
  //反斜线赢法
  for (var i = 0; i < 11; i++) {
    for (var j = 14; j > 3; j--) {
      for (var k = 0; k < 5; k++) {
        win[i + k][j - k][count] = true;
      }
      count++;
    }
  }
  console.log(count)
  //初始化统计数组
  for (var i = 0; i < count; i++) {
    myWin[i] = 0;
    computerWin[i] = 0;
  }
  var chess = document.getElementById('chess');
  var context = chess.getContext('2d');
  context.strokeStyle = '#bfbfbf';

  var logo = new Image();
  logo.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAAAA' +
    'AAeW/F+AAAACXBIWXMAAAABAAAAAQBPJcTWAAAC2UlEQVR4nG3SW0hTcRwH8ANTKF8qEHro' +
    'tYdE0IzKCEHxRaGsEJ+iIDAwwzKMIoQMBcOSbJSXlHCpxNS5LW9tznk9m+6W2/RMNzebcxd' +
    'd3nbXec7/t/5T0CZ9X87//D/8/5zf73eICE7IbjSY1lDkMCG3a303uiAAQjMiAZtd1Txq90I' +
    '0jM/A+8rlj82FAAjwDvWUFlQ2NgvGedQ++3vJvvp3xYXfhwNAMBODGUWC6ZVVy6IjjKKM3Ba' +
    'z3TpWl9EsYwiH+kXmoAPvI4eaJOd3fXNqvZMG2FM9u0M6iRnLtTItVsYw0VJY2NhfWV9cIaGw' +
    'e9vSpmcJhe5CrQufNfJvJ7BYZ2t667JOXOSYEKCBdLGSUFBJb1cBlvi5caz4uMQSz9z7M6y0' +
    'njVAwvTRSUJhulSmoa0995Nvvmmqk6spjZpdlJ0v2VzjpMonCK3pRhZP3PSg2hokS3U7Yi1X0' +
    '6FcK8lv/3nvilZNOBWvE66XJH0Mg4X7xTxjXHC1f1YFV9LPXz39hHQRjFz5MDE+cx2X69/orBqf' +
    'Dw68qg2hmpPnHpNKhgCfVMO9y8Ht8DltNflUmLHdqgiAuYCvJoO4qeCbHGqxYNYtIrfJGgYka1' +
    'lGaKRrYTfac1yzt3sbwNO4GJ1HwI922rrUrlXeFhww/Ondgw0hhcsHfceoKqAXDMmm8NUHHBYbKH' +
    'GtBDGIhlaOaF7jcWln94e3z2b2t3K5VorbbA25Z1tlOyGwKo/Yv7TavWLn0oDCM78BtmnGKn' +
    'QfMY7AxnDt+Gkno6NdF0xBDEsooBoc+MNles+mSS4VMDG8MAwwIsKLHVXfkFz6aT32dEgYAEuTFP' +
    '8FtNsgV0pQLINJhZC1XGmHrabq57otOMaMbhl5X+Y99cGer38XjjPQNh+S52WraHPnj/8w4JYFGz7ktF' +
    '7OccJ/GGf7lyglhXXqkR4dcuTfMA5OanJa7uLhRixHIrTFuOykD1//Ao5d36oMbdkaAAAAAElFTkSuQmCC';
  logo.onload = function () {
    context.drawImage(logo, 150, 150, 150, 150);
    drawChessBoard();
  }

  var drawChessBoard = function () {
    for (var 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();
    }
  }

  var oneStep = function (i, j, me) {
    context.beginPath();
    context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);
    context.closePath();
    var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 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();
  }

  chess.onclick = function (e) {
    //如果结束不生效
    if (over) {
      return
    }
    //如果不是我的回合结束
    if (!me) {
      return
    }
    //获取点击位置
    var i = Math.floor(e.offsetX / 30);
    var j = Math.floor(e.offsetY / 30);
    //判断是否已经有棋子
    if (chessBoard[i][j] == 0) {
      //画棋子
      oneStep(i, j, me);
      //记录我的棋子
      chessBoard[i][j] = 1;
      //判断点击位置所有赢法
      for (var k = 0; k < count; k++) {
        //第k种赢法上新增了一个子
        if (win[i][j][k]) {
          //k种赢法上一共的子数
          myWin[k]++;
          computerWin[k] = 6;
          if (myWin[k] == 5) {
            setTimeout(function () {
              window.alert("你赢了!!");
            })
            over = true;
          }
        }
      }
      if (!over) {
        me = !me
        computerAI()
      }
    }
  }

  var computerAI = function () {
    var myScore = [];
    var computerScore = [];
    var max = 0, u = 0, v = 0;

    //初始化每个可落子位置的权重
    for (var i = 0; i < 15; i++) {
      myScore[i] = [];
      computerScore[i] = [];
      for (var j = 0; j < 15; j++) {
        myScore[i][j] = 0;
        computerScore[i][j] = 0;
      }
    }
    //遍历整个棋盘
    for (var i = 0; i < 15; i++) {
      for (var j = 0; j < 15; j++) {
        //如果该位置可以落子
        if (chessBoard[i][j] == 0) {
          //遍历整个赢法数组
          for (var k = 0; k < count; k++) {
            if (win[i][j][k]) {
              //统计我方第k种赢法已有颗子则加上相应权重分
              if (myWin[k] == 1) {
                myScore[i][j] += 200
              } else if (myWin[k] == 2) {
                myScore[i][j] += 400
              } else if (myWin[k] == 3) {
                myScore[i][j] += 2000
              } else if (myWin[k] == 4) {
                myScore[i][j] += 10000
              }
              //统计计算机方第k种赢法已有颗子则加上相应权重分
              if (computerWin[k] == 1) {
                computerScore[i][j] += 200
              } else if (computerWin[k] == 2) {
                computerScore[i][j] += 400
              } else if (computerWin[k] == 3) {
                computerScore[i][j] += 2000
              } else if (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;
            }
          }
        }
      }
    }

    oneStep(u, v, false);
    chessBoard[u][v] = 2;
    //判断点击位置所有赢法
    for (var k = 0; k < count; k++) {
      //第k种赢法上新增了一个子
      if (win[u][v][k]) {
        //k种赢法上一共的子数
        computerWin[k]++;
        myWin[k] = 6;
        if (computerWin[k] == 5) {
          setTimeout(function () {
            window.alert("你输了!!");
          })
          over = true;
        }
      }
    }
    if (!over) {
      me = !me
    }
  }
</script>

</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值