前端技术搭建扫雷小游戏(内含源码)

news2024/11/26 4:35:58

The sand accumulates to form a pagoda

  • ✨ 写在前面
  • ✨ 功能介绍
  • ✨ 页面搭建
  • ✨ 样式设置
  • ✨ 逻辑部分


✨ 写在前面

上周我们实通过前端基础实现了贪吃蛇游戏,今天还是继续按照我们原定的节奏来带领大家完成一个游戏,功能也比较简单简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript在前端中的作用, 在前面的文章当中我们也提及到我们在本系列的专栏是循序渐进从简单到复杂的过程,后续会带领大家用前端实现翻卡片、扫雷等有趣的小游戏,纯前端语言实现,都会陆续带给大家。欢迎大家订阅我们这份前端小游戏的专栏。订阅链接:https://blog.csdn.net/jhxl_/category_12261013.html


✨ 功能介绍

扫雷是一款经典的单人益智游戏,目标是在雷区中揭开所有非雷方块而避免触雷。以下是游戏的玩法说明和规则:游戏开始时,你将面对一个方块组成的地图,其中包含隐藏的雷方块和非雷方块。你需要逐个点击方块来揭开它们。如果揭开的方块是雷方块,你失败并游戏结束。揭开的方块可能是数字方块,它会显示周围八个方块中雷的数量。根据这些数字,你可以推断其他方块的状态。如果揭开的方块是空白方块,它将自动展开,揭开相邻的空白方块,直到边界或有数字的方块。通过观察数字方块周围的雷的数量,你可以推断出潜在的雷区,并使用右键进行标记,帮助记忆和避免揭开雷方块。如果你成功揭开所有非雷方块,而没有触雷,你将获得胜利。

在这里插入图片描述

在扫雷游戏中,推理、记忆和谨慎是取得胜利的关键。通过观察和推断雷的位置,并运用合适的标记策略,你可以在雷区中探索出更多安全的方块,并最终解开所有的谜题。记住要保持冷静,小心行事,以在这个挑战性的益智游戏中获得成功!


✨ 页面搭建

创建文件

首先呢我们创建我们的HTML文件,这里我就直接命名为 扫雷.html 了,大家可以随意命名, 文件创建生成后我们通过编辑器打开,这里我用的是VScode, 然后初始化我们的代码结构,那在这里告诉大家一个快捷键,就是我们敲上我们英文的一个 ! 我们敲击回车直接就会给我们生成基础版本的前端代码结构。

在这里插入图片描述

文档声明和编码设置: 在HTML文档的头部,使用<!DOCTYPE>声明HTML文档类型,确保浏览器以正确的方式渲染网页内容。同时,设置UTF-8编码,以确保浏览器能够正确地解析和显示中文字符。下面我就开始搭建我们的DOM结构了!

DOM结构搭建

这段HTML代码是一个简单的扫雷游戏界面的布局。让我为你解释一下每个部分的作用: <div class="bigBox">:这是一个包含整个游戏内容的大容器,它用来将游戏界面的各个元素进行组合和布局。 <div id="controls">:这个 <div> 元素包含了游戏的控制面板,用于设置游戏的难度级别和重新开始游戏。<form>:这是一个表单元素,用于包裹控制面板中的各个控件。 <label for="level">难度级别:</label>:这是一个用于显示文本的 <label> 元素,它与下面的下拉菜单(<select>)建立了关联,通过 for 属性指定了关联的控件的 id<select id="level">:这是一个下拉菜单(选择框)控件,用于选择游戏的难度级别。它有三个选项:简单、中等和困难。 <button id="reset">重新开始</button>:这是一个按钮控件,用于重新开始游戏。 <table id="board"></table>:这是一个空的表格元素,用于承载扫雷游戏的方格(格子)。在游戏开始后,这个表格会被动态生成,并显示雷区的方格布局。

总体而言,这段HTML代码定义了一个扫雷游戏的基本界面结构,包括了难度选择、重新开始按钮和雷区的表格容器。通过这些元素,玩家可以进行难度选择,并在雷区中进行游戏操作。

<body>

  <div class="bigBox">
    <div id="controls">
      <form>
        <label for="level">难度级别:</label>
        <select id="level">
          <option value="easy">简单</option>
          <option value="medium">中等</option>
          <option value="hard">困难</option>
        </select>
        <button id="reset">重新开始</button>
      </form>
    </div>

    <table id="board"></table>
  </div>


</body>

在这里插入图片描述


✨ 样式设置

我们看到了上面的的DOM已经搭建好了,但是页面什么都看不出来,下面我们简单的来配置一下样式吧,其实我们本专栏也是想带领大家掌握一些逻辑所以样式方面我们就一切从简;

  1. .bigBox:这个类选择器用于样式化游戏的大容器。设置了背景颜色、宽度、居中对齐、内边距等样式,使游戏界面具有一定的外观和布局。

  2. #reset:这是一个ID选择器,用于样式化重新开始按钮。设置了按钮的宽度、字体大小等样式。

  3. table:这个选择器用于样式化表格元素。设置了表格的边框合并、居中对齐、外边距等样式,使雷区的方格在表格中呈现出合适的布局。

  4. td:这个选择器用于样式化表格中的单元格(方格)。设置了单元格的宽度、高度、文本对齐、垂直对齐、边框等样式,使方格具有一致的外观。

  5. button:这个选择器用于样式化按钮元素。设置了按钮的宽度、高度、内边距、外边距、字体大小、字体加粗、文本颜色、背景颜色等样式,使按钮呈现出一致的外观和按钮效果。

  6. #controls:这个ID选择器用于样式化控制面板的样式。设置了控制面板的顶部外边距,使其与上方的元素保持一定的间距。

总体而言,这段CSS代码通过设置不同的选择器和样式属性,为扫雷游戏的界面元素和控制面板元素提供了外观和布局的样式。这样可以使游戏界面看起来更加美观、整洁,并提供良好的用户体验。

/* 游戏布局样式 */
.bigBox {
  background-color: rgb(163, 159, 159);
  width: 40%;
  margin: 5% auto;
  text-align: center;
  padding: 20px;
}

#reset {
  width: 100px;
  font-size: 15px;
}

table {
  border-collapse: collapse;
  margin: 30px auto;
}

td {
  width: 30px;
  height: 30px;
  text-align: center;
  vertical-align: middle;
  border: 1px solid #ccc;
}

button {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  font-size: 16px;
  font-weight: bold;
  color: #fff;
  background-color: #333;
  border: none;
}

/* 控制面板样式 */
#controls {
  margin-top: 20px;
}

在这里插入图片描述


✨ 逻辑部分

上面我们搭建了基本的样式,下面呢我们就通过js代码,实现我们游戏的功能吧,下面是对代码的简化解释:

  1. const config = { ... }:这是一个对象,用于存储游戏的参数配置。根据难度级别(简单、中等、困难),配置了每个级别的行数、列数和地雷数量。

  2. 变量声明和初始化:声明了一系列变量用于存储游戏所需的各种信息,如游戏界面元素、游戏状态、地雷数量等。

  3. 事件监听器:通过监听重新开始按钮(reset)和难度级别选择器(level)的点击事件或改变事件,调用相应的初始化函数(init())来重新开始游戏或改变游戏难度。

  4. init() 函数:该函数用于初始化游戏。根据选择的难度级别,设置相应的行数、列数和地雷数量。然后,根据行数和列数动态生成游戏的表格布局,并为每个单元格(方格)添加按钮元素。最后,初始化地雷的位置,并更新地雷数量的显示。

  5. clickCell() 函数:该函数用于处理玩家点击单元格(方格)的操作。根据点击的单元格的位置,判断是否有地雷,如果有地雷则显示所有地雷并结束游戏;如果没有地雷,则根据周围的地雷数量显示相应的数字或递归地显示周围的方格。

  6. revealNeighbors() 函数:该函数用于递归地展开周围的方格,直到周围有地雷或有数字。

  7. countMinesAround() 函数:该函数用于计算给定方格周围的地雷数量。

  8. revealMines() 函数:该函数用于显示所有的地雷,将地雷方格的背景颜色设置为红色。

  9. updateMinesCount() 函数:该函数用于更新剩余地雷数量的显示。

  10. showGameOver() 函数:该函数用于展示游戏结束的提示信息,根据参数 win 的值判断是胜利还是失败。

  11. checkWin() 函数:该函数用于检查玩家是否已经胜利,遍历所有方格,如果有任何未揭示的非地雷方格,则返回 false,否则返回 true

  12. init() 函数调用:在脚本末尾,调用 init() 函数来初始化游戏。

通过这段JavaScript代码,扫雷游戏实现了玩家点击方格、展开周围方格、计算地雷数量等功能,并提供了重新开始游戏和切换难度级别的功能。

<script>
  // 游戏参数配置
  const config = {
    easy: {
      rows: 8,
      cols: 8,
      mines: 10,
    },
    medium: {
      rows: 10,
      cols: 10,
      mines: 20,
    },
    hard: {
      rows: 12,
      cols: 12,
      mines: 30,
    },
  };
  // 初始化游戏
  let board = document.getElementById("board");
  let level = document.getElementById("level");
  let reset = document.getElementById("reset");
  let cells = [];
  let gameover = false;
  let minesLeft = 0;
  let minesCount = 0;
  let rows, cols, mines;

  reset.addEventListener("click", init);

  level.addEventListener("change", function () {
    init();
  });

  function init () {
    // 初始化游戏参数
    let levelConfig = config[level.value];
    rows = levelConfig.rows;
    cols = levelConfig.cols;
    mines = levelConfig.mines;
    minesLeft = mines;
    minesCount = 0;
    gameover = false;
    // 初始化游戏布局
    board.innerHTML = "";
    cells = [];
    for (let i = 0; i < rows; i++) {
      let row = [];
      let tr = document.createElement("tr");
      for (let j = 0; j < cols; j++) {
        let td = document.createElement("td");
        let button = document.createElement("button");
        button.addEventListener("click", function () {
          if (!gameover) {
            clickCell(i, j);
          }
        });
        td.appendChild(button);
        tr.appendChild(td);
        row.push({ button: button, hasMine: false, revealed: false });
      }
      cells.push(row);
      board.appendChild(tr);
    }
    // 初始化地雷
    for (let i = 0; i < mines; i++) {
      let row, col;
      do {
        row = Math.floor(Math.random() * rows);
        col = Math.floor(Math.random() * cols);
      } while (cells[row][col].hasMine);
      cells[row][col].hasMine = true;
    }
    // 更新地雷数目显示
    updateMinesCount();
  }

  function clickCell (row, col) {
    let cell = cells[row][col];
    if (cell.revealed) {
      return;
    }
    if (cell.hasMine) {
      revealMines();
      showGameOver(false);
      return;
    }
    cell.revealed = true;
    cell.button.style.backgroundColor = "#ddd";
    let minesAround = countMinesAround(row, col);
    if (minesAround > 0) {
      cell.button.textContent = minesAround;
    } else {
      revealNeighbors(row, col);
    }
    if (checkWin()) {
      showGameOver(true);
    }
  }

  function revealNeighbors (row, col) {
    for (let i = row - 1; i <= row + 1; i++) {
      for (let j = col - 1; j <= col + 1; j++) {
        if (i >= 0 && i < rows && j >= 0 && j < cols && !(i == row && j == col)) {
          clickCell(i, j);
        }
      }
    }
  }

  function countMinesAround (row, col) {
    let count = 0;
    for (let i = row - 1; i <= row + 1; i++) {
      for (let j = col - 1; j <= col + 1; j++) {
        if (i >= 0 && i < rows && j >= 0 && j < cols && cells[i][j].hasMine) {
          count++;
        }
      }
    }
    return count;
  }

  function revealMines () {
    for (let i = 0; i < rows; i++) {
      for (let j = 0; j < cols; j++) {
        if (cells[i][j].hasMine) {
          cells[i][j].button.style.backgroundColor = "#f00";
        }
      }
    }
  }

  function updateMinesCount () {
    console.log('这是哈哈', minesLeft)
    // minesCountElem.textContent = minesLeft;
  }

  function showGameOver (win) {
    gameover = true;
    let message = win ? "You Win!" : "You Lose!";
    alert(message);
  }

  function checkWin () {
    for (let i = 0; i < rows; i++) {
      for (let j = 0; j < cols; j++) {
        let cell = cells[i][j];
        if (!cell.hasMine && !cell.revealed) {
          return false;
        }
      }
    }
    return true;
  }

  init();

</script>

完整代码

<!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>
    /* 游戏布局样式 */
    .bigBox {
      background-color: rgb(163, 159, 159);
      width: 40%;
      margin: 5% auto;
      text-align: center;
      padding: 20px;
    }

    #reset {
      width: 100px;
      font-size: 15px;
    }

    table {
      border-collapse: collapse;
      margin: 30px auto;
    }

    td {
      width: 30px;
      height: 30px;
      text-align: center;
      vertical-align: middle;
      border: 1px solid #ccc;
    }

    button {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      font-size: 16px;
      font-weight: bold;
      color: #fff;
      background-color: #333;
      border: none;
    }

    /* 控制面板样式 */
    #controls {
      margin-top: 20px;
    }
  </style>
</head>

<body>

  <div class="bigBox">
    <div id="controls">
      <form>
        <label for="level">难度级别:</label>
        <select id="level">
          <option value="easy">简单</option>
          <option value="medium">中等</option>
          <option value="hard">困难</option>
        </select>
        <button id="reset">重新开始</button>
      </form>
    </div>

    <table id="board"></table>
  </div>


</body>

<script>
  // 游戏参数配置
  const config = {
    easy: {
      rows: 8,
      cols: 8,
      mines: 10,
    },
    medium: {
      rows: 10,
      cols: 10,
      mines: 20,
    },
    hard: {
      rows: 12,
      cols: 12,
      mines: 30,
    },
  };
  // 初始化游戏
  let board = document.getElementById("board");
  let level = document.getElementById("level");
  let reset = document.getElementById("reset");
  let cells = [];
  let gameover = false;
  let minesLeft = 0;
  let minesCount = 0;
  let rows, cols, mines;

  reset.addEventListener("click", init);

  level.addEventListener("change", function () {
    init();
  });

  function init () {
    // 初始化游戏参数
    let levelConfig = config[level.value];
    rows = levelConfig.rows;
    cols = levelConfig.cols;
    mines = levelConfig.mines;
    minesLeft = mines;
    minesCount = 0;
    gameover = false;
    // 初始化游戏布局
    board.innerHTML = "";
    cells = [];
    for (let i = 0; i < rows; i++) {
      let row = [];
      let tr = document.createElement("tr");
      for (let j = 0; j < cols; j++) {
        let td = document.createElement("td");
        let button = document.createElement("button");
        button.addEventListener("click", function () {
          if (!gameover) {
            clickCell(i, j);
          }
        });
        td.appendChild(button);
        tr.appendChild(td);
        row.push({ button: button, hasMine: false, revealed: false });
      }
      cells.push(row);
      board.appendChild(tr);
    }
    // 初始化地雷
    for (let i = 0; i < mines; i++) {
      let row, col;
      do {
        row = Math.floor(Math.random() * rows);
        col = Math.floor(Math.random() * cols);
      } while (cells[row][col].hasMine);
      cells[row][col].hasMine = true;
    }
    // 更新地雷数目显示
    updateMinesCount();
  }

  function clickCell (row, col) {
    let cell = cells[row][col];
    if (cell.revealed) {
      return;
    }
    if (cell.hasMine) {
      revealMines();
      showGameOver(false);
      return;
    }
    cell.revealed = true;
    cell.button.style.backgroundColor = "#ddd";
    let minesAround = countMinesAround(row, col);
    if (minesAround > 0) {
      cell.button.textContent = minesAround;
    } else {
      revealNeighbors(row, col);
    }
    if (checkWin()) {
      showGameOver(true);
    }
  }

  function revealNeighbors (row, col) {
    for (let i = row - 1; i <= row + 1; i++) {
      for (let j = col - 1; j <= col + 1; j++) {
        if (i >= 0 && i < rows && j >= 0 && j < cols && !(i == row && j == col)) {
          clickCell(i, j);
        }
      }
    }
  }

  function countMinesAround (row, col) {
    let count = 0;
    for (let i = row - 1; i <= row + 1; i++) {
      for (let j = col - 1; j <= col + 1; j++) {
        if (i >= 0 && i < rows && j >= 0 && j < cols && cells[i][j].hasMine) {
          count++;
        }
      }
    }
    return count;
  }

  function revealMines () {
    for (let i = 0; i < rows; i++) {
      for (let j = 0; j < cols; j++) {
        if (cells[i][j].hasMine) {
          cells[i][j].button.style.backgroundColor = "#f00";
        }
      }
    }
  }

  function updateMinesCount () {
    console.log('这是哈哈', minesLeft)
    // minesCountElem.textContent = minesLeft;
  }

  function showGameOver (win) {
    gameover = true;
    let message = win ? "You Win!" : "You Lose!";
    alert(message);
  }

  function checkWin () {
    for (let i = 0; i < rows; i++) {
      for (let j = 0; j < cols; j++) {
        let cell = cells[i][j];
        if (!cell.hasMine && !cell.revealed) {
          return false;
        }
      }
    }
    return true;
  }

  init();

</script>

</html>

本期推荐 查看详情

在这里插入图片描述

原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/596054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

钉钉斜杠“/”开启邀请测试;用ChatGPT写一个数据采集程序

&#x1f989; AI新闻 &#x1f680; 钉钉斜杠“/”开启邀请测试&#xff0c;AI全面智能化助力企业生产 摘要&#xff1a;钉钉斜杠“/”邀请测试开启&#xff0c;应用于文档、群聊、视频会议、应用开发等场景&#xff0c;为企业用户提供多项AI智能能力&#xff0c;如创作、汇…

【AUTOSAR】Com通讯栈配置说明(五)---- ComM模块

ComM模块 ComMConfigSet ComMChannels ComMBusType&#xff1a;定义总线类型 ComMChannelId&#xff1a;通道号 ComMFullCommRequestNotificationEnabled&#xff1a;未使用 ComMComMGlobalNvmBlockDescriptor&#xff1a;未使用 ComMMainFunctionPeriod&#xff1a;ComM的…

【云原生•监控】mtail轻量日志监控系统

【云原生•监控】mtail轻量日志监控系统 前言 「笔者已经在公有云上搭建了一套临时环境&#xff0c;可以先登录体验下&#xff1a;」 http://124.222.45.207:17000/login 账号&#xff1a;root/root.2020 简介 「可观测性平台三大支柱&#xff1a;日志监控、调用链监控和度量指…

2023年05月小结

5月一晃即将过去&#xff0c;先看看5月份都写了哪些文章&#xff1a; 往期推荐 国内手机号如何注册Google账号 Python中的布尔类型以及布尔值介绍 Python中深拷贝与浅拷贝介绍 Python中的集合介绍 Python中的字典学习笔记 Python学习历程-元组的基本操作回顾 记录我的Python学习…

初学prometheus监控(一)

初学prometheus监控(一) 1、promethues 介绍 1.1 监控的分类 监控重要性由高到低 业务监控&#xff1a;公司领导比较关心的指标&#xff0c;如电商平台的订单数量&#xff0c;用户的日活等系统监控&#xff1a;主要是跟操作系统相关的基本监控项&#xff0c;比如CPU,内存&#…

ChatGPT能解决信息抽取吗?一份关于性能、评估标准、鲁棒性和错误的分析

深度学习自然语言处理 原创作者&#xff1a;qazw 信息抽取(IE)旨在从非结构化文本中抽取出结构化信息&#xff0c;该结果可以直接影响很多下游子任务&#xff0c;比如问答和知识图谱构建。因此&#xff0c;探索ChatGPT的信息抽取能力在一定程度上能反映出ChatGPT生成回复时对任…

Office project 2019安装

哈喽&#xff0c;大家好。今天一起学习的是project 2019的安装&#xff0c;Microsoft Office project项目管理工具软件&#xff0c;凝集了许多成熟的项目管理现代理论和方法&#xff0c;可以帮助项目管理者实现时间、资源、成本计划、控制。有兴趣的小伙伴也可以来一起试试手。…

英伟达股票大涨,对应 GPU 产品有哪些型号?

英伟达&#xff08;NVIDIA&#xff09;是一家知名的 GPU&#xff08;图形处理器&#xff09;制造商&#xff0c;其 GPU 产品线非常丰富&#xff0c;涵盖了从消费级到专业级的各种型号。 最近英伟达股票大涨&#xff0c;高端 GPU 供不应求&#xff0c;搞大模型的团队都要疯狂进货…

机器学习入门基础:机器学习实践

目录 7.1 数据集划分 7.1.1 训练集、验证集和测试集划分7.1.2 交叉验证7.1.3 不平衡数据处理7.2 评价指标 7.2.1 回归的评价指标7.2.2 分类的评价指标7.2.3 评价指标案例7.3 正则化、偏差和方差 7.3.1 欠拟合和过拟合7.3.2 正则化7.3.3 偏差和方差参考文献 7.1 数据集划分 7.1…

通过python采集1688app商品详情数据,1688app商品详情数据接口,1688API接口

要通过Python采集1688app商品详情数据&#xff0c;你可以使用以下步骤&#xff1a; 安装必要的 Python 模块&#xff1a;requests, BeautifulSoup4 和 lxml。使用 requests 模块发送 HTTP 请求获取网站 HTML 内容。使用 BeautifulSoup4 模块解析 HTML 页面并提取所需的数据。编…

主路由设置静态路由后,能ping通,但无法访问网页服务和ssh等

主路由设置静态路由后&#xff0c;能ping通&#xff0c;但无法访问网页服务和ssh等 静态路由 主路由是istoreos软路由&#xff0c; AP使用华为AX3路由器做ap和wifi&#xff0c; 二级路由使用蒲公英路由X5 前置条件&#xff1a;已在主路由设置静态路由 静态路由 问 主路由设置静…

项目管理新手常见误区揭秘~

点击上方 "JavaEdge"关注, 星标或置顶一起成长 后台回复“面试”有惊喜礼包&#xff01; 这是一个纷杂而无规则的世界&#xff0c;越想忘掉的事情&#xff0c;越难忘记。 如何完成新手项目经理的角色转换呢&#xff1f; 成为项目经理前&#xff0c;我做了四五年的“码…

一起看 I/O | Jetpack 新功能一览

作者 / Android 产品经理 Amanda Alexander Android Jetpack 是现代 Android 开发 (Modern Android Development) 的关键组成支柱。Android Jetpack 套件包含超 100 个库、工具及指南&#xff0c;可帮助开发者遵循最佳实践、减少样板代码&#xff0c;并编写可在各种 Android 版…

chatgpt赋能python:Python修改配置文件:实现自动配置与简化运维

Python修改配置文件&#xff1a;实现自动配置与简化运维 介绍 配置文件是软件开发中不可缺少的一部分&#xff0c;它不仅包含应用程序的基本设置&#xff0c;还提供了一种简单的方式来管理这些设置。如何有效地修改配置文件已经成为了每个开发者必备的技能之一&#xff0c;而…

这8个NumPy函数可以解决90%的常见问题

NumPy是一个用于科学计算和数据分析的Python库&#xff0c;也是机器学习的支柱。可以说NumPy奠定了Python在机器学习中的地位。NumPy提供了一个强大的多维数组对象&#xff0c;以及广泛的数学函数&#xff0c;可以对大型数据集进行有效的操作。这里的“大”是指数百万行。 Nump…

MGR网络抖动问题分析和group_replication_unreachable_majority_timeout等参数分析

导言 本文主要从测试的角度来阐明group_replication_unreachable_majority_timeout和group_replication_member_expel_timeout参数对集群网络分区的影响&#xff0c;首先这里放一张大图&#xff0c;为多年前学习MGR的时候留下的&#xff0c;也就是这两个参数对集群的影响&…

穷途末路的阿里中台

观点| Mr.K 主笔| Wendy.L 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 对于关注K哥公众号多年的朋友来说&#xff0c;“中台”早就是老生常谈的东西了&#xff0c;如果你还不知道它是什么&#xff0c;可以看看之前的中台文章先恶补一下。 关于中台&#xff0c;这些年翻…

chatgpt赋能python:Python倒序range的完整指南

Python倒序range的完整指南 Python是一种高级编程语言&#xff0c;很多人认为它非常容易学习和使用。其中一个非常有用的功能是range()函数&#xff0c;可以生成数字序列。然而&#xff0c;有时候我们需要以相反的顺序生成这个数字序列&#xff0c;这时候倒序range()函数就派上…

5G NTN技术概述及演进分析(下)

5G NTN因其广泛的服务覆盖能力、应对物理攻击或自然灾害的健壮性和灵活性&#xff0c;在交通、公共安全、电子健康、农业、金融、汽⻋等领域有广泛的应用前景。5G NTN与地面通信的差异主要体现在高时延、广覆盖和卫星的运动等方面&#xff0c;这使得其在传输时延、多普勒频移、…

Ae:蒙版跟踪(含脸部跟踪)

蒙版跟踪&#xff0c;就是通过记录画面上蒙版区域的变化&#xff0c;生成蒙版路径 Mask Path的关键帧。 常用于完成合成中的遮挡关系&#xff0c;或者局部添加动态效果&#xff0c;以及实现人物的脸部特效。 蒙版跟踪 要使用蒙版跟踪器&#xff0c;需要先创建并选中蒙版&#x…