JavaScript实现三子棋

2023-11-15

目录

要做的事:

1.初始化棋盘

2.落子操作

3.判断获胜

4.轮流落子

5.重置棋盘

6.棋盘判满

7.源代码

8.效果展示


要做的事:

1.初始化棋盘

首先棋盘是一个3*3的二维数组,而我们的二维数组又是分别由一个一个的一维数组组成的。如下图所示。

2.落子操作

给我们的每个棋盘空间绑定事件hePosition(row,col),表示鼠标下落点的坐标。在这个函数中,我们首先拿到一个棋盘,初始情况是默认空的状态,假定A玩家先走,那么我们就把当前的A玩家走的位置坐标赋给棋盘的(row,col),由于我们使用了一个一维数组来表示3*3的三子棋棋盘格子,我们这里将获取到的二维坐标(row,col)映射到一维数组的索引,这样就可以方便的找到鼠标点击的对应的格子并将其标志为当前玩家的标记。这里我们使用innerText显示文本标记。

3.判断获胜

在处理好获取到指定格子的坐标标记后, 此时我们单独封装一个函数去检查获胜的判定方法。如下图所示获胜判定规则。每一行相同、每一列相同、斜对角相同。

首先我先设置一个只读变量piece让它等于棋盘的某个坐标上的元素,也就是分别从列、行、对角的角度去获取特定行和列位置上的元素。简单来见piect这个变量它可能的值是A、B、空,如果当前位置为空,那么玩家就可以标记显示,不为空,不操作。然后在hePosition(row,col)函数中调用,如果返回的是true那么就会弹出当前哪个玩家获胜了,然后重置棋盘。这里需要注意的是,使用setTimeout()定时器的原因是因为整个页面加载速度非常快,单线程执行,如果不设置定时器延时作用的话那么我们胜利玩家下的最后一个棋子是看不到的,所以设置了延时显示后在重置棋盘。如果棋盘已经下满了,那么就手动触发重置按钮,将棋盘清空。

4.轮流落子

因为我们下棋是A走了换B,所以这里我们处理的条件是使用三目运算符,判断上面的currentPlayer是否获胜,没有获胜,那么就更新到另一个玩家。

5.重置棋盘

同样的也是单独使用一个函数resetBoard()去重置,重置也就是回到初始时候,此时先落子的换成A,然后嵌套for循环分别去遍历行和列,将棋盘board[row][col]置为空(''),同时把每个格子也置为空document.getElementsByClassName('he')[row * 3 + col].innerText = '';当获胜后,或者棋盘满了后我们调用这个函数达到目的。

6.棋盘判满

对于棋盘盘满,和重置棋盘类似,我们也是使用for嵌套循环,去遍历行和列,看每个格子上是否为空,都不为空则说明每个格子都有标志。此时我们就返回true,如果有没满的情况那就返回false。

7.源代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .con {
            width: 600px;
            /* background: pink; */
            height: 400px;
            display: flex;
            flex-direction: row;
            margin: 0 auto;
            justify-content: space-around;
        }
        .con button {
            width: 100px;
            height: 100px;
            border-radius: 50%;
            margin-top: 100px;
            background: yellow;
            font-size: 20px;
        }
        .container {
            width: 300px;
            height: 300px;
            background: pink;
            display: flex;
            flex-direction: column;
            box-sizing: border-box;
            
            border: 2px solid black;
        }
        .row {
            width: 100%;
            height: 100px;
            display: flex;
            flex-direction: row;
        }
        .row .he {
            width: 100px;
            height: 100px;
            border: 2px solid black;
            box-sizing: border-box;
            font-size: 30px;
            line-height: 100px;
        }
        body {
            text-align: center;
        }
        button {
            width: 150px;
            height: 40px;
            background: yellow;
            border: none;
            
        }
    </style>
</head>
<body>
    <div class="con">
        <button>A玩家</button>
        <div class="container">
            <div class="row">
                <div class="he" onclick="hePosition(0,0)"></div>
                <div class="he" onclick="hePosition(0,1)"></div>
                <div class="he" onclick="hePosition(0,2)"></div>
            </div>
            <div class="row">
                <div class="he" onclick="hePosition(1,0)"></div>
                <div class="he" onclick="hePosition(1,1)"></div>
                <div class="he" onclick="hePosition(1,2)"></div>
            </div>
            <div class="row">
                <div class="he" onclick="hePosition(2,0)"></div>
                <div class="he" onclick="hePosition(2,1)"></div>
                <div class="he" onclick="hePosition(2,2)"></div>
            </div>
        </div>
        <button>B玩家</button>
    </div>
    
    <button onclick="resetBoard()">重置棋盘</button>
    
    <script>
        // 初始化棋盘
        const board = [
            ['','',''],
            ['','',''],
            ['','',''],
        ];

        let currentPlayer = 'A'; //设置每次开始的当前要走的棋子
        
        // 落子处理
        function hePosition(row,col) {
            // 初始时候棋盘是空的,开始游戏就把当前第一个走的赋值给初始的位置
            if(board[row][col] === '') {
                board[row][col] = currentPlayer;
                document.getElementsByClassName('he')[row * 3 + col].innerText = currentPlayer;

                // 检查是否获胜
                if(checkWin(row,col)) {
                    // 设置定时器,因为页面加载速度非常快,所以通过设置延时来显示最后一个棋子落地位置
                    setTimeout(() => {
                        alert(currentPlayer + "获胜!");
                        resetBoard();
                    }, 1000); // 延迟 1000 毫秒后重置棋盘
                    
                    // 获胜也就是结束后要重置棋盘
                    
                    return;
                }

                // 如果棋盘满了
                if(isBoardFull()) {
                    alert("棋盘已满,请重新开始!");
                    return;
                }
                // 如果玩家没有获胜,将 currentPlayer 更新为另一个玩家,这样实现了两个玩家在轮流下棋的功能
                currentPlayer = currentPlayer === 'A' ? 'B' : 'A';
            }

        }

        // 检查获胜方法
        function checkWin(row, col) {
            // 使用 board[row] 从 board 中获取第 row 行的一维数组,然后再用 [col] 从该一维数组中获取第 col 列的元素。
            const piece = board[row][col];
            // 检查行
            if (board[row][0] === piece && board[row][1] === piece && board[row][2] === piece) {
                return true;
            }
            // 检查列
            if (board[0][col] === piece && board[1][col] === piece && board[2][col] === piece) {
                return true;
            }
            // 检查对角线
            if ((board[0][0] === piece && board[1][1] === piece && board[2][2] === piece) ||
                (board[0][2] === piece && board[1][1] === piece && board[2][0] === piece)) {
                return true;
            }
        }

        // 重置棋盘
        function resetBoard() {
            currentPlayer = 'A';
            for (let row = 0; row < 3; row++) {
                for (let col = 0; col < 3; col++) {
                board[row][col] = '';
                document.getElementsByClassName('he')[row * 3 + col].innerText = '';
                }
            }
        }

        // 判断棋盘满操作
        function isBoardFull() {
            for(let row = 0; row < 3; row++) {
                for(let col = 0; col < 3; col++) {
                    if(board[row][col] === '') {
                        return false;
                    }
                }
            }
            return true;
        }
    </script>
</body>
</html>

8.效果展示

js实现三子棋演示效果-CSDN直播

以上就是js实现三子棋的过程啦,我之所以在旁边设置了AB玩家是因为刚开始想通过点击AB生成随机坐标模拟实现,然后想着先把这个自控点击的先实现啦,随机生成的请看下节。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript实现三子棋 的相关文章

  • 在沙盒中的服务器上运行不受信任的 JavaScript 代码

    我似乎不知道如何设置节点沙箱 它可以安全地运行不受信任的代码 并允许用户通过api调用与程序交互 系统输入和输出 我正在尝试在浏览器中设置一个控制台 以便用户从服务器运行自己的代码 是否有任何节点包支持此功能 或者我是否需要编写自己的节点虚
  • 为什么 AngularJS 在使用 ng-bind-html 时会去掉 data- 属性?

    我正在使用 contentEditable div 来使用户能够格式化他们的文章 我对html内容做了一些处理并保留它 我在用ng bind html当观众想要阅读文章时呈现结果 我不想使用 sce trustAsHtml因为我仍然希望 A
  • 错误:#0 轴的数据列不能是字符串类型

    我正在尝试使用谷歌图表和 React JS 创建散点图 我制作了一个测试数组来检查这是否是将数据发送到图表的正确方法并且它有效 但是当我处理真实数据并创建一个类似的数组时 它给我带来错误 轴 0 的数据列不能是字符串类型 这是运行良好的测试
  • 减少 JavaScript 中的对象数组

    我在 javascript 中有一个想要减少的对象数组 请参阅下面的代码 6 位或以上的消息已验证 较少的消息未验证 我将他们按组分组 const myArray group groupA message Text without a nu
  • ExtJs4 Json TreeStore?

    我正在将 ExtJs3 应用程序迁移到 ExtJs4 在 ExtJs3 中 我有一个树网格 它有一个加载器来加载树数据 如下所示 loader new Ext tree TreeLoader dataUrl Department Depar
  • React 测试库:当输入表单上的 fireEvent 更改时,给定元素没有值设置器

    我想改变的值材质用户界面 https material ui com components text fields TextField在反应测试库中 我已经设置了 data testid 然后使用getByTestId我拿起了输入元素 th
  • 使用 JS 和 HTML 将当前 URL 插入链接

    所以 我已经阅读了类似的内容 但我仍然找不到更适合我正在做的事情的答案 我正在尝试使用 JS 获取当前页面 URL 并将其附加到社交媒体共享链接 如下所示 a href target blank 使用 Javascript 我成功地将当前
  • 找不到 firebase-messaging.js laravel

    大家好 我正在使用 firebase 制作一个用于推送通知的应用程序 这是我在 firebase 中的第一个项目 我遇到的问题是当我运行项目并单击它给我的登录按钮时的连接 已授予通知权限 但在此之后它返回一个错误 如下所示 获取脚本时收到错
  • 自定义过滤器在 Angular Hybrid 应用程序中不起作用

    我正在尝试将 AngularJS 1 6 应用程序与 Angular 5 一起转换为混合应用程序 我定义了以下简单过滤器 function use strict var filterId colorPicker angular module
  • 当容器有选择框时 jQuery mouseleave 触发问题

    我有两个容器 一个嵌套在另一个容器内 当我将鼠标悬停在父容器上时 我希望显示子容器 当我鼠标移出时 我希望子容器淡出 我遇到的问题是子容器有一个包含 选择框 的表单 当用户选择选择框时 会意外触发 mouseleave 事件 如何阻止选择框
  • 不明白为什么 Chrome/Safari 无法在此处获取 ScrollHeight

    我只是问了一个问题 为什么某些 js 代码不能 100 在 Chrome 和 Safari 中工作 但经过更多故障排除后 我想我发现这是我应该发布的问题 我有一个页面 其中有一个表单 该表单的目标是同一页面上的 iframe iframe
  • 更改导航栏悬停时 div 的背景图像

    我正在开发一个项目 我对 Javascript 很陌生 所以我想知道是否有 Jquery 代码或只是一个关于如何使背景图像在导航菜单悬停时更改的过程 例如将鼠标悬停在链接一上会将 div 的背景图像更改为图像 1 将鼠标悬停在链接二上会将
  • 调整发散堆积条形图以使用通用更新模式

    我一直在使用可用的堆积条形图示例here https bl ocks org mbostock b5935342c6d21928111928401e2c8608使用以下代码 var data month Q1 2016 apples 384
  • JavaScript 中的自定义“确认”对话框?

    我一直在开发一个使用自定义 模式对话框 的 ASP net 项目 我在这里使用吓人引号 因为我知道 模式对话框 只是我的 html 文档中的一个 div 它被设置为出现在文档其余部分的 顶部 而不是真正意义上的模式对话框 在网站的许多部分
  • 如何在 Android 设备(平板电脑和手机)方向更改时获得正确的窗口宽度

    我正在尝试使用 jquery 函数计算 Android 设备方向变化时的窗口宽度 window outerWidth true 此计算给出了两个方向变化的正确宽度iphone and ipad但在安卓中不行 如果我最初以横向模式或纵向模式加
  • 已安装 cypress npm 软件包,但缺少 Cypress 二进制文件

    大家好 我是 azure devops CI 的新手 我正在尝试通过在作业之间缓存 node modules 来减少管道构建时间 但我遇到了无法解决的错误 我正在使用 cypress 进行测试 这是我的天蓝色管道 Node js Build
  • ajax - 检查用户名是否存在+如果存在则返回消息

    我试图检查用户想要的用户名是否已被使用 而无需发送表单 基本上是用户名字段的模糊 我遇到了一些麻烦 有几个问题 我有我的输入字段加上js
  • 如何在 C# 中通过 JavaScript 回调运行 QUnit 测试并获取测试结果?

    在我的几个项目中 我使用 MVC 模式将代码 关注点 分为 3 层 模型层和控制层都在 C 上运行 因此我使用 MSTest 或 NUnit 等测试框架来验证这些层的功能需求 对于视图层 我使用 QUnit 来测试 JavaScript 文
  • Rails 6 webpack 抛出“未捕获的引用错误:$未定义”

    大家好 我最近开始使用 ruby 2 6 5 开发 Rails 6 由于 Rails 6 引入了 webpack 所以我尝试使用 webpack 加载我的 js 文件 尽管我已经在 appliation js 中需要了 jquery 但我仍
  • CasperJS:如何单击所有选定的按钮?

    我正在尝试使用 CasperJS 作为网络抓取工具 并且有一个带有按钮的页面 单击该按钮将加载数据 因此 我想先单击所有这些按钮 然后等待 然后再实际进行查询以获取所有必要的数据 问题是对于 Casper casper thenClick

随机推荐

  • flutter_blue + MethodChannel.invokeMethod + java.lang.NullPointerException

    友盟崩溃日志报了这样一个问题 说是扫描蓝牙设备回调时 MethodChannel 为空 java lang NullPointerException Attempt to invoke virtual method void io flut
  • Logrotate日志切分

    logrotate 程序是一个日志文件管理工具 用来把旧的日志文件更名或删除 并创建新的日志文件 我们把它叫做 转储 是个使日志轮替的程序 有了它就不用看着自己的日志体积一天天的变大 而可以根据你自己的需求来设定日志转储 这个工具对于像ng
  • discuz设置伪静态

    discuz设置伪静态 环境为 centos Apache mysql php 操作后台 点击提交 点击右上角的查看规则 复制一段到新建文件 htaccess中 注 WIN主机就另存为httpd ini Linux主机就另存为 htacce
  • python遍历文件夹下的所有子文件夹,并将指定的文件复制到指定目录

    python遍历文件夹下的所有子文件夹 并将指定的文件复制到指定目录 需求 复制单个文件夹 遍历所有子文件夹中的文件 并复制 代码封装 需求 在1文件夹中有1 2两个文件夹 将这两个文件夹中的文件复制到 after copy中 复制单个文件
  • Deathnote

    Deathnote 1 主机发现 arp scan l 2 扫描端口 nmap Pn sV P A 192 168 80 132 开放了80 22端口 3 访问80端口 修改host文件访问80端口时进行了跳转到deathnote vuln
  • Allegro 17.4设置中文界面

    一 Allegro 17 4 中文界面效果 二 Allegro 17 4 中文界面设置方法 2 1 需要打上此时 20210820 最新的S019的升级补丁 2 2 设置环境变量 变量名 intl enabled 变量值 1 要去除中文显示
  • LeetCode刷题-1

    数组 1 两数之和 题目描述 题目样例 Java方法 暴力枚举 思路及算法 代码 执行结果 复杂度 Java方法 哈希表 思路及算法 代码 执行结果 复杂度 题目描述 给定一个整数数组 nums 和一个整数目标值 target 请你在该数组
  • StarCraft开发:用肮脏的技巧解决难题

    http www csdn net article 2013 02 28 2814299 the starcraft path finding hack 摘要 在之前的文章中 Warcraft之父讲述了自己是如何以及为何重启StarCraf
  • Linux中的fork()函数

    Linux中的fork 函数 在Linux中 fork 函数是创建进程的基础 它是一个系统调用 用于创建一个新的进程作为当前进程的副本 新进程将拥有与原进程相同的代码 数据和堆栈 但是拥有不同的进程ID PID 并且它是原进程的子进程 函数
  • 【debug】(0, slice(None, None, None))‘ is an invalid key

    简单介绍 我获取了一个dataframe里的符合条件的多个index 想通过index对dataframe进行筛选 在筛选的时候反馈错误 原始代码为 input index df select df select item input in
  • 【word】如何设置交叉引用标注参考文献

    文章目录 1 定义参考文献编号格式 2 设置交叉引用 插入正文位置 3 修改连续多个参考文献的格式 4 更新正文标注 1 定义参考文献编号格式 开始 gt 编号 gt 定义新编号格式 2 设置交叉引用 插入正文位置 设置好固定的参考文献格式
  • 【vscode,python】pip成功的包却不能导入(import)问题

    第一次遇到这个问题 在网上找了些资料 网上的教程大致上都是需要去修改settings json这个文件 我问了我朋友 然后轻松地解决了这个问题 方法一 关掉编译软件重新打开即可解决问题 方法二 我认为造成这个问题的原因是在另一个新的路径上新
  • 真实GPS转腾讯/高德地图坐标系,百度地图与腾讯/高德地图坐标系转换

    1 获取真实坐标GPS wgs84转为gcj编码方式 positiontransform array manual 定义常量 var GPS PI 3 14159265358979324 x pi 3 14159265358979324 3
  • 对称矩阵的压缩存储、基于压缩矩阵的矩阵乘法

    def disp A 输出方阵A n len A for i in range n for j in range n print d A i j end print def compression A a 压缩矩阵A到a中 A是一个对称矩阵
  • 面试总结(五):搜索引擎

    问题导读 1 搜索引擎有哪些特点 优势 2 搜索引擎使用到哪些场景中 3 如何将原文档传给分次组件 4 如何将得到的词 Term 传给索引组件 Indexer 搜索引擎概述全文搜索就是对文本数据的一种搜索方式 文本数据的都多 可以分为顺序搜
  • 基于verilog语言的SPI协议实现

    前言 关于SPI协议的基础知识这里就不在叙述了 感兴趣的小伙伴可以自行百度 本文基于verilog语言 实现SPI的四种通信模式 封装成通用模块 更新时间 2023年7月11日 更新原因 之前的版本存在bug 通用性不够 模块端口如下 sp
  • java设计模式--[创建模式]--简单工厂[simple factory]

    一 簡單工廠 其實它不是一個設計模式 反而比較像是一種編程習慣 由于經常被使用 有些人把這個習慣誤認為是 工廠模式 在談論工廠模式前 先將簡單工廠熟悉一下 二 簡單工廠的UML類圖如下 三 在此用一個事例說明簡單工廠的用法 在一個酒店里可以
  • 爬虫使用Selenium生成Cookie

    在爬虫的世界中 有时候我们需要模拟登录来获取特定网站的数据 而使用Selenium登录并生成Cookie是一种常见且有效的方法 本文将为你介绍如何使用Selenium进行登录 并生成Cookie以便后续的爬取操作 让我们一起探索吧 一 Se
  • 关系数据库——关系操作和关系完整性

    文章目录 一 关系操作 1 基本的关系操作 2 关系数据语言的分类 关系代数语言 关系演算语言 具有关系代数和关系演算双重特点的语言 二 关系的完整性 1 实体完整性 Entity Integrity 实体完整性规则 2 参照完整性 Ref
  • JavaScript实现三子棋

    目录 要做的事 1 初始化棋盘 2 落子操作 3 判断获胜 4 轮流落子 5 重置棋盘 6 棋盘判满 7 源代码 8 效果展示 要做的事 1 初始化棋盘 首先棋盘是一个3 3的二维数组 而我们的二维数组又是分别由一个一个的一维数组组成的 如