纯JS实现五子棋游戏兼容各浏览器(附源码)

下面是详细讲解“纯JS实现五子棋游戏兼容各浏览器(附源码)”的完整攻略。

1. 实现概述

该游戏是基于纯JS实现的,实现思路如下:

  1. 初始化画布,绘制棋盘;
  2. 监听鼠标点击事件,判断点击位置是否合法;
  3. 判断当前玩家是否胜利;
  4. 实现AI逻辑,即电脑自动下棋的过程。

2. 实现过程

2.1 初始化画布,绘制棋盘

首先,在HTML中定义一个canvas元素用于绘制游戏界面,然后通过JS获取canvas元素,设置画布大小、线条颜色等样式。接着,绘制棋盘。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>五子棋游戏</title>
  <style>
    canvas {
      border: 1px solid #999;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="600" height="600"></canvas>
  <script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var ROW = 15;
    var GAP = canvas.width / (ROW + 1);
    var qizi = {};

    for (var i = 0; i < ROW; i++) {
      ctx.moveTo(GAP, GAP * (i + 1));
      ctx.lineTo(canvas.width - GAP, GAP * (i + 1));
      ctx.stroke();
      ctx.moveTo(GAP * (i + 1), GAP);
      ctx.lineTo(GAP * (i + 1), canvas.width - GAP);
      ctx.stroke();
    }
  </script>
</body>
</html>

2.2 监听鼠标点击事件,判断点击位置是否合法

我们需要监听鼠标点击事件,获取鼠标点击的坐标,并将坐标转换成棋盘交叉点的坐标。由于棋盘是一个二维数组,因此将获取的坐标作为数组的下标,将棋子信息存储在二维数组中。完整代码如下:

canvas.onclick = function(e) {
  var x = e.offsetX;
  var y = e.offsetY;
  var i = Math.round(x / GAP) - 1;
  var j = Math.round(y / GAP) - 1;
  if (qizi[i + '-' + j]) {
    return;
  }
  drawQizi(i, j, true);
  qizi[i + '-' + j] = true;
}

其中,drawQizi函数用于绘制棋子。

2.3 判断当前玩家是否胜利

当玩家下完一步棋时,需要判断当前玩家是否胜利。这里使用一个五位数的二进制数表示棋盘上的落子情况,其中1表示黑子,0表示白子。比如,如果一行连成了五个黑子,则该行的二进制数为11111,即31;而如果该行只连成了四个黑子,则该行的二进制数为11110,即30。判断胜负时,只需要检查当前玩家的落子情况是否满足五子连珠即可。完整代码如下:

// 判断当前玩家是否胜利
function check(pos, color) {
  var table = {};
  for (var i in qizi) {
    if (qizi[i] === color) {
      table[i] = true;
    }
  }
  var sp = pos.split('-');
  var i = sp[0], j = sp[1];
  var num1 = 1, num2 = 1, num3 = 1, num4 = 1;
  var table2 = {};
  table2[i + '-' + j] = true;
  // 横向
  for (var k = 1; table[(+i + k) + '-' + j]; k++) {
    num1++;
    table2[(+i + k) + '-' + j] = true;
  }
  for (var k = 1; table[(+i - k) + '-' + j]; k++) {
    num1++;
    table2[(+i - k) + '-' + j] = true;
  }
  if (num1 >= 5) return true;
  // 竖向
  for (var k = 1; table[i + '-' + (+j + k)]; k++) {
    num2++;
    table2[i + '-' + (+j + k)] = true;
  }
  for (var k = 1; table[i + '-' + (+j - k)]; k++) {
    num2++;
    table2[i + '-' + (+j - k)] = true;
  }
  if (num2 >= 5) return true;
  // 左斜线
  for (var k = 1; table[(+i + k) + '-' + (+j + k)]; k++) {
    num3++;
    table2[(+i + k) + '-' + (+j + k)] = true;
  }
  for (var k = 1; table[(+i - k) + '-' + (+j - k)]; k++) {
    num3++;
    table2[(+i - k) + '-' + (+j - k)] = true;
  }
  if (num3 >= 5) return true;
  // 右斜线
  for (var k = 1; table[(+i - k) + '-' + (+j + k)]; k++) {
    num4++;
    table2[(+i - k) + '-' + (+j + k)] = true;
  }
  for (var k = 1; table[(+i + k) + '-' + (+j - k)]; k++) {
    num4++;
    table2[(+i + k) + '-' + (+j - k)] = true;
  }
  if (num4 >= 5) return true;
  return false;
}

2.4 实现AI逻辑

实现AI逻辑,让电脑自动下棋。思路是根据已有的落子情况,计算每个空位的得分,选择得分最高的点为电脑下一步落子的位置。完整代码如下:

canvas.onclick = function(e) {
  var x = e.offsetX;
  var y = e.offsetY;
  var i = Math.round(x / GAP) - 1;
  var j = Math.round(y / GAP) - 1;
  if (qizi[i + '-' + j]) {
    return;
  }
  drawQizi(i, j, true);
  qizi[i + '-' + j] = true;
  if (check(i + '-' + j, true)) {
    alert('恭喜您,您赢了!');
    canvas.onclick = null;
    return;
  } else {
    paita();
    if (check(ai.x + '-' + ai.y, false)) {
      alert('很遗憾,您输了!');
      canvas.onclick = null;
      return;
    }
  }
}
function paita() {
  var zuobiao = {};
  var max = -Infinity;
  for (var i in qizi) {
    var x = parseInt(i.split('-')[0]);
    var y = parseInt(i.split('-')[1]);
    var hang = {}, lie = {}, x1xie = {}, x2xie = {};
    for (var j in qizi) {
      if (parseInt(j.split('-')[0]) === x) {
        hang[j] = true;
      }
      if (parseInt(j.split('-')[1]) === y) {
        lie[j] = true;
      }
      if (parseInt(j.split('-')[0]) - x === parseInt(j.split('-')[1]) - y) {
        x1xie[j] = true;
      }
      if (parseInt(j.split('-')[0]) - x === y - parseInt(j.split('-')[1])) {
        x2xie[j] = true;
      }
    }
    var hs = check2(hang);
    var ls = check2(lie);
    var s1s = check2(x1xie);
    var s2s = check2(x2xie);
    if (hs > max) {
      max = hs;
      zuobiao = {x: x, y: y};
    }
    if (ls > max) {
      max = ls;
      zuobiao = {x: x, y: y};
    }
    if (s1s > max) {
      max = s1s;
      zuobiao = {x: x, y: y};
    }
    if (s2s > max) {
      max = s2s;
      zuobiao = {x: x, y: y};
    }
  }
  drawQizi(zuobiao.x, zuobiao.y, false);
  qizi[zuobiao.x + '-' + zuobiao.y] = false;
  ai.x = zuobiao.x;
  ai.y = zuobiao.y;
}
function check2(obj) {
  var max = -Infinity, count = 0;
  for (var i = 0; i < ROW; i++) {
    if (obj[i + '-0'] && obj[i + '-1'] && obj[i + '-2'] && obj[i + '-3'] && obj[i + '-4']) {
      count++;
    } else {
      max = count > max ? count : max;
      count = 0;
    }
  }
  max = count > max ? count : max;
  count = 0;
  for (var i = 0; i < ROW; i++) {
    if (obj['0-' + i] && obj['1-' + i] && obj['2-' + i] && obj['3-' + i] && obj['4-' + i]) {
      count++;
    } else {
      max = count > max ? count : max;
      count = 0;
    }
  }
  max = count > max ? count : max;
  count = 0;
  for (var i = 0; i < ROW; i++) {
    if (obj[i + '-' + i]) {
      count++;
    } else {
      max = count > max ? count : max;
      count = 0;
    }
  }
  max = count > max ? count : max;
  count = 0;
  for (var i = 0; i < ROW; i++) {
    if (obj[(ROW - 1 - i) + '-' + i]) {
      count++;
    } else {
      max = count > max ? count : max;
      count = 0;
    }
  }
  max = count > max ? count : max;
  count = 0;
  return max;
}

3. 示例说明

3.1 示例一:实现对战模式

可以通过添加对战模式,让两个玩家进行互动。例如,添加一个按钮用于切换到对战模式,点击后需要提示先后手,并且落子颜色会随着先后手的不同而变化。修改后的完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>五子棋游戏</title>
  <style>
    canvas {
      border: 1px solid #999;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="600" height="600"></canvas>
  <button onclick="modeChange()">切换到对战模式</button>
  <script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var ROW = 15;
    var GAP = canvas.width / (ROW + 1);
    var qizi = {};
    var mode = 1;

    for (var i = 0; i < ROW; i++) {
      ctx.moveTo(GAP, GAP * (i + 1));
      ctx.lineTo(canvas.width - GAP, GAP * (i + 1));
      ctx.stroke();
      ctx.moveTo(GAP * (i + 1), GAP);
      ctx.lineTo(GAP * (i + 1), canvas.width - GAP);
      ctx.stroke();
    }

    canvas.onclick = function(e) {
      var x = e.offsetX;
      var y = e.offsetY;
      var i = Math.round(x / GAP) - 1;
      var j = Math.round(y / GAP) - 1;
      if (qizi[i + '-' + j]) {
        return;
      }
      if (mode === 1) {
        drawQizi(i, j, true);
        qizi[i + '-' + j] = true;
        if (check(i + '-' + j, true)) {
          alert('恭喜您,您赢了!');
          canvas.onclick = null;
          return;
        }
        mode = 2;
      } else if (mode === 2) {
        drawQizi(i, j, false);
        qizi[i + '-' + j] = false;
        if (check(i + '-' + j, false)) {
          alert('恭喜电脑赢了!');
          canvas.onclick = null;
          return;
        }
        mode = 1;
      }
    }

    function modeChange() {
      alert('您执黑,电脑执白。');
      mode = 1;
    }
  </script>
</body>
</html>

3.2 示例二:添加音效和动画效果

可以通过添加音效和动画效果,提高游戏的趣味性。例如,添加音效用于提示棋子落下的声音;添加动画效果用于提示玩家哪里可以下棋。修改后的完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>五子棋游戏</title>
  <style>
    canvas {
      border: 1px solid #999;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="600" height="600"></canvas>
  <button onclick="modeChange()">切换到对战模式</button>
  <audio src="https://www.w3school.com.cn/i/horse.ogg" id="music"></audio>
  <script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var ROW = 15;
    var GAP = canvas.width / (ROW + 1);
    var qizi = {};
    var mode = 1;
    var music = document.getElementById("music");

    for (var i = 0; i < ROW; i++) {
      ctx.moveTo(GAP, GAP * (i + 1));
      ctx.lineTo(canvas.width - GAP, GAP * (i + 1));
      ctx.stroke();
      ctx.moveTo(GAP * (i + 1), GAP);
      ctx.lineTo(GAP * (i + 1), canvas.width - GAP);
      ctx.stroke();
    }

    canvas.onclick = function(e) {
      var x = e.offsetX;
      var y = e.offsetY;
      var i = Math.round(x / GAP) - 1;
      var j = Math.round(y / GAP) - 1;
      if (qizi[i + '-' + j]) {
        return;
      }
      if (mode === 1) {
        drawQizi(i, j, true);
        qizi[i + '-' + j] = true;
        if (check(i + '-' + j, true)) {
          alert('恭喜您,您赢了!');
          canvas.onclick = null;
          return;
        }
        mode = 2;
      } else if (mode === 2) {
        drawQizi(i, j, false);
        qizi[i + '-' + j] = false;
        if (check(i + '-' + j, false)) {
          alert('恭喜电脑赢了!');
          canvas.onclick = null;
          return;
        }
        mode = 1;
      }
      music.play();
      animate(i, j);
    }

    function modeChange() {
      alert('您执黑,电脑执白。');
      mode = 1;
    }

    function animate(x, y) {
      ctx.save();
      ctx.beginPath();
      ctx.arc((x + 1) * GAP, (y + 1) * GAP, GAP / 3, 0, Math.PI * 2);
      ctx.closePath();
      ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
      ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
      ctx.fill();
      ctx.stroke();
      ctx.restore();
    }
  </script>
</body>
</html>

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:纯JS实现五子棋游戏兼容各浏览器(附源码) - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • django admin 使用SimpleUI自定义按钮弹窗框示例

    下面是“django admin 使用SimpleUI自定义按钮弹窗框示例”的完整攻略以及其中的两个示例说明。 1. 什么是SimpleUI SimpleUI是一个漂亮的开源后台管理系统框架,提供了众多易于扩展和修改的组件和插件,能够使开发者快速开发高效的后台管理系统。 2. 使用SimpleUI自定义按钮弹窗框示例 在django admin中,我们可以利…

    JavaScript 2023年6月11日
    00
  • 关于JavaScript数组对象去重的几种方法

    没问题,以下是关于JavaScript数组对象去重的几种方法的完整攻略。 关于JavaScript数组对象去重的几种方法 方法一:使用Set对象 Set对象可以快速去除数组中的重复元素。具体做法是将数组转换成Set对象,再将Set对象转换成数组。这种方法的优点是简洁高效,也符合函数式编程的原则。 示例代码如下: let arr = [1, 2, 3, 2, …

    JavaScript 2023年5月27日
    00
  • 建设网站教程(4):JavaScript初级教程

    针对“建设网站教程(4):JavaScript初级教程”的完整攻略,我提供如下说明。 一、JavaScript是什么? JavaScript是一种客户端脚本语言,常被用于在网页前端增加交互性和动态效果。它是一种解释性语言,不需要预编译,可以在所有现代的浏览器上执行。 二、 JavaScript基础语法 在JavaScript中,所有语句都必须以分号(;)结尾…

    JavaScript 2023年5月18日
    00
  • JavaScript极简入门教程(二):对象和函数

    当你在学习JavaScript时,你会发现对象和函数是JavaScript中最重要的两个概念。对象和函数的概念是面向对象编程(OOP)的核心。本文将为你提供一个JavaScript对象和函数的极简入门教程。 什么是JavaScript对象? 在JavaScript中,对象是一种数据类型,用于存储多个值并描述其特征。对象可以是大型的或小型的,简单的或复杂的。对…

    JavaScript 2023年5月18日
    00
  • JavaScript构造函数详解

    JavaScript构造函数详解 什么是构造函数? 构造函数是一种特殊类型的函数,用于创建对象。构造函数通常情况下的命名都以大写字母开头。构造函数可以被用于创建多个相同类型的对象。 构造函数的语法 function ConstructorName(param1, param2) { this.property1 = param1; this.property…

    JavaScript 2023年5月27日
    00
  • js实现一个猜数字游戏

    下面是JS实现猜数字游戏的完整攻略。 步骤 1. 随机生成一个数字 首先,我们需要随机生成一个1~100之间的数字作为游戏答案,可以使用Math.random()和Math.floor()函数来实现: let answer = Math.floor(Math.random() * 100) + 1; // 生成1~100之间的整数 2. 获取用户输入 然后,…

    JavaScript 2023年6月11日
    00
  • Bootstrap表单Form全面解析

    Bootstrap表单Form全面解析 什么是Bootstrap表单Form? Bootstrap表单Form是Bootstrap前端框架中一个用于构建表单的组件,用于简化表单的开发过程。通过使用Bootstrap表单Form,开发者可以快速构建出漂亮、易用、兼容性好的表单,提高工作效率。Bootstrap表单Form主要包括水平布局和垂直布局两种形式,以及…

    JavaScript 2023年6月10日
    00
  • JavaScript仿百度图片浏览效果

    介绍JavaScript仿百度图片浏览效果所需要遵循的完整攻略: 步骤一:网页结构设计 要实现JavaScript仿百度图片浏览效果,需要先设计网页的结构。具体来说,需要将每个图片都包装在一个链接标签内部,然后这些链接标签再放置在一个父级div标签中。这样,每次点击一个链接标签,就会打开一个图片的浏览界面。 下面是一个示例代码: <div class=…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部