20-30 五子棋游戏

20-分析五子棋的实现思路_哔哩哔哩_bilibili20-分析五子棋的实现思路是一次性学会 Canvas 动画绘图(核心精讲+50个案例)2023最新教程的第21集视频,该合集共计53集,视频收藏或关注UP主,及时了解更多相关视频内容。https://www.bilibili.com/video/BV16T411B7kP?spm_id_from=333.788.player.switch&vd_source=9218320e7bcc2e793fa8493559f4acd7&p=21https://www.bilibili.com/video/BV16T411B7kP?spm_id_from=333.788.player.switch&vd_source=9218320e7bcc2e793fa8493559f4acd7&p=21https://www.bilibili.com/video/BV16T411B7kP?spm_id_from=333.788.player.switch&vd_source=9218320e7bcc2e793fa8493559f4acd7&p=21https://www.bilibili.com/video/BV16T411B7kP?spm_id_from=333.788.player.switch&vd_source=9218320e7bcc2e793fa8493559f4acd7&p=21

20-分析五子棋的实现思路

逻辑处理用原生JavaScript写,画布与棋子用canvas画

21-绘制网格棋盘

视频里用的绿色太晃眼了,换了一个更像木质棋盘的颜色 #ebc78f 。

页面底色与棋盘颜色,代码如下:

html,
body {background: #eee;
}canvas {display: block;margin: 0 auto;background-color: #ebc78f;
}

棋盘是由多条横线和纵线组合而成,一格是50px,左右余宽 50px, (800-50-50) / 50 = 14,如果i从0开始算,0到14一共是15条线,为了方便计算,设 i 从1开始,for循环至 i < 16结束。

    // 1.创建canvaslet canvas = document.createElement('canvas')canvas.width = 800canvas.height = 800document.body.append(canvas)// 2.获取 contextlet context = canvas.getContext('2d')// 3.画棋盘// 3.1 棋盘是由多条横线和纵线组合而成,一格按50px算,左右余宽 50px, (800-50-50) / 50 = 14,所以我们需要15条线for (let i = 1; i < 16; i++) {// 把线段的开头表示出来(横线)context.moveTo(50, 50 * i)  // 起点context.lineTo(750, 50 * i)  // 终点context.stroke()}for (let i = 1; i < 16; i++) {// 把线段的开头表示出来(竖线)context.moveTo(50 * i, 50)  // 起点context.lineTo(50 * i, 750)  // 终点context.stroke()}

22-点击棋盘绘制棋子

通过 context.beginPath(),可以避免上图这种情况,要注意 .beginPath() 要写在画圆 .arc() 之前

canvas.addEventListener('click', e => {let { offsetX: x, offsetY: y } = econtext.beginPath()  // 避免起点终点被fill()填充颜色context.arc(x, y, 20, 0, 2 * Math.PI)context.fill()context.closePath()  // 配合 .beginPath()  使用
})

因为一个格子是50px,我们设置 (offsetX+25)/2 ,这样计算后可以让偏左的对齐左边的线偏右的对齐右边的线(offsetY也是同理),在 canvas.addEventListener 中设置如下:

let { offsetX, offsetY } = e
let x = Math.floor((offsetX + 25) / 50) * 50  // 让棋子在网格线正确的位置
let y = Math.floor((offsetY + 25) / 50) * 50

23-棋盘的边界判断

判断点击的位置边界,如果超出棋盘范围则不落棋子。如果offsetX < 25,则不落棋子(因为如果 offsetX >= 25,则可知落棋子在第一列上),offsetY与上下左右四边同理。

// 判断点击的位置边界,如果超出棋盘范围则不落棋子
if (offsetX < 25 || offsetY < 25 || offsetX > 775 || offsetY > 775) {return;
}

24-绘制不不同的棋子

context.beginPath()
context.arc(x, y, 20, 0, 2 * Math.PI)// 设置黑白棋子的渐变色
let gBlack = context.createRadialGradient(x - 8, y - 8, 0, x, y, 20)
gBlack.addColorStop(0, '#999')
gBlack.addColorStop(1, '#000')let gWhite = context.createRadialGradient(x - 5, y - 10, 18, x, y, 40)
gWhite.addColorStop(0, '#fff')
gWhite.addColorStop(1, '#666')// 判断当前棋子颜色变量,给棋子黑白不同颜色
context.fillStyle = isBlack ? gBlack : gWhite// 视频里老师的代码
// let tx = isBlack ? x - 10 : x + 10;
// let ty = isBlack ? y - 10 : y + 10;
// let g = context.createRadialGradient(tx, ty, 0, tx, ty, 30);
// g.addColorStop(0, isBlack ? '#ccc' : '#666');
// g.addColorStop(1, isBlack ? '#000' : '#fff');
// context.fillStyle = g
// 视频里老师的代码 ENDcontext.fill()
context.closePath()

25-处理重复落子的问题

第1个数组代表第一列的棋子内容(原点 (0,0) 在左上角,row 相当于 X轴,向右方向为正方向, col 是 Y轴,向下方向为正方向)。

使用一个二维数组,把所有的棋子位置存储起来。棋盘有15横列,每个 i 代表一列,循环15次,设置 circles[i] 为一个空数组。

// 6. 使用一个二维数组把所有的棋子位置存储起来
let circles = [];
// 棋盘有15列,每个i指代每一列
for (let i = 1; i < 16; i++) {// circles[i]里的每一项都是一个空数组circles[i] = []
}
console.log(circles);

设置 x = i * 50, y = j * 50 ,可以让棋子在网格线十字中心的位置上,添加一个布尔变量 isBlack,用来控制棋子黑白颜色的切换。

let x = i * 50  // 让棋子在网格线十字中心的位置
let y = j * 50
context.beginPath()
context.arc(x, y, 20, 0, 2 * Math.PI)// 6.1 把棋子的坐标存到二维数组里
circles[i][j] = isBlack ? 'black' : 'white'
// console.log(circles);   

如果 circles[i][j] 不为空,说明里面已经有内容,那么不允许重复落子。

// 6.2 判断当前位置是否已经存在棋子
if (circles[i][j]) {// 提醒用户, 这里已有棋子tip.innerText = `不能重复落子!当前是${isBlack ? '黑' : '白'}棋的回合`return;
}

设置顶部的文字提示。

 <div class="tip">请黑棋落子</div>// ...
// 提醒用户换人
let text = isBlack ? '请黑棋落子' : '请白棋落子'
tip.innerText = text
// ...

26-纵向判断棋子连续

连成线的4种情况:

将坐标(row,col)视作(x,y)更加直观,在纵轴(竖轴)方向上检索是否有5个连续的棋子可以想象为:在X轴位置不变,Y轴加减坐标上下移动,在此期间判断各个棋子是否为同一种颜色

代码逻辑草稿:

// 以 row, col 为起点,在二维数组里向上和向下查找
circles[row][col-1]
circles[row][col-2]
circles[row][col-3]
circles[row][col-4]circles[row][col+1]
circles[row][col+2]
circles[row][col+3]
// ...

设置一个 checkVertical 函数,来判断在竖轴方向上是否有五子相连,它的返回值是 return count >=5 ,如果 count 是 5,那么函数结果返回 true,会在下面的步骤中将结果传递给一个 endGame变量作为判断结束游戏的依据(其他三个方向的设计逻辑也是这样)。

【b站视频内提供的代码(有bug)】

// 纵向查找是否有5个连续相同的棋子
function checkVertical(row, col) {// 记录向上的次数let up = 0;// 记录向下的次数let down = 0;let times = 0;// 定义当前总共有几个已经连在一起let count = 1; // 初始值,自己本身算1个// 为避免出现死循环,设置一个循环上限 10000while (times < 17) {times++;// 如果棋子已经大于一个指定的次数,就不找了if (count >= 5) {break;}let target = isBlack ? 'black' : 'white';// 以 row, col 为起点,在二维数组里向上查找up++;if (circles[row][col - up] && circles[row][col - up] == target) {count++;};// 以 row, col 为起点,在二维数组里向下查找down++;if (circles[row][col + down] && circles[row][col + down] == target) {count++;};}return count >= 5;
}

27-处理获胜的逻辑

添加一个 endGame 布尔值变量,初始值为 false, 通过将当前棋子的(i, j) 值传递给四个方向的五子相连函数来判断是否有 true 值存在,如果有,那么游戏结束,棋盘无法再被点击。

// 8.1 定义一个变量标识,是否结束游戏
let endGame = false// ...
// 8. 判断是否有人已经获胜,endGame为true,则无法点击
if (endGame) {// 游戏结束return
}// ...
// 7.判断当前是否已有对应的棋子连成5颗,endGame为true则出现获胜提示字
endGame = checkVertical(i, j)
if(endGame) {tip.innerText = `${isBlack?'黑': '白'}方获胜!`return
}

28-处理棋子非连续的情况

如果相邻的棋子都不是同色的,直接 break 这次的判断循环。

// 如果棋子已经大于一个指定的次数,或者相邻棋子不是同色的(同色棋子不连续),就不找了
if (count >= 5 || (circles[row][col - up] != target && circles[row][col + down] != target)) {break;
}

29-横向判断是否获胜

【b站视频内提供的代码(有bug)】

// 横向查找是否有5个连续相同的棋子
function checkHorizontal(row, col) {// 记录向左的次数let left = 0;// 记录向右的次数let right = 0;let times = 0;// 定义当前总共有几个已经连在一起let count = 1; // 初始值,自己本身算1个// 为避免出现死循环,设置一个循环上限 10000while (times < 17) {times++;let target = isBlack ? 'black' : 'white';// 以 row, col 为起点,在二维数组里向左查找left++;if (circles[row-left][col] && circles[row-left][col] == target) {count++;};// 以 row, col 为起点,在二维数组里向右查找right++;if (circles[row+right][col] && circles[row+right][col] == target) {count++;};// 如果棋子已经大于一个指定的次数,或者相邻棋子不是同色的(同色棋子不连续),就不找了if (count >= 5 || (circles[row-left][col] != target && circles[row+right][col] != target)) {break;}}return count >= 5;
}

 最终我们需要4个方向的判断,所以这里会有4个判断函数,上下、左右、左上右下、右上左下。

// 7.判断当前是否已有对应的棋子连成5颗,endGame为true则出现获胜提示字
endGame = checkVertical(i, j) || checkHorizontal(i, j)

30-斜向判断是否获胜

判断方向在左上右下时,方向往左上延伸,那么X-, Y-,方向往右下延伸,那么X+, Y+。

判断方向在右上左下时,方向往右上延伸,那么X+, Y-,方向往左下延伸,那么X-, Y+。

【完整代码-bug修复版本】

落子靠近棋盘四周一圈时,如果要判断(不存在的)超出棋盘范围的棋子代码会报错,所以进行了 if 判断。

* 如果还有其他bug,建议自己修正一下。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>html,body {background: #eee;}canvas {display: block;margin: 0 auto;background-color: #ebc78f;}.tip {text-align: center;padding: 16px;color: #666;}</style>
</head><body><div class="tip">请黑棋落子</div><script>// 1.创建canvaslet canvas = document.createElement('canvas')canvas.width = 800canvas.height = 800document.body.append(canvas)// 获取文字提示 tip 元素let tip = document.querySelector('.tip')// 2.获取 contextlet context = canvas.getContext('2d')// 3.画棋盘// 3.1 棋盘是由多条横线和纵线组合而成,一格按50px算,左右余宽 50px, (800-50-50) / 50 = 14,所以我们需要14条线for (let i = 1; i < 16; i++) {// 把线段的开头表示出来(横线)context.moveTo(50, 50 * i)  // 起点context.lineTo(750, 50 * i)  // 终点context.stroke()}for (let i = 1; i < 16; i++) {// 把线段的开头表示出来(竖线)context.moveTo(50 * i, 50)  // 起点context.lineTo(50 * i, 750)  // 终点context.stroke()}// 6. 使用一个二维数组把所有的棋子位置存储起来let circles = [];// 棋盘有15列,每个i指代每一列for (let i = 1; i < 16; i++) {// circles[i]里的每一项都是一个空数组circles[i] = []}// console.log(circles);// 5.使用一个变量保存当前的棋子颜色let isBlack = true// 8.1 定义一个变量标识,是否结束游戏let endGame = false// 4. 当点击在棋盘里的时候,绘制一个棋子canvas.addEventListener('click', e => {let { offsetX, offsetY } = e// 判断点击的位置边界,如果超出棋盘范围则不落棋子if (offsetX < 25 || offsetY < 25 || offsetX > 775 || offsetY > 775) {return;}// 格子所在的位置let i = Math.floor((offsetX + 25) / 50)let j = Math.floor((offsetY + 25) / 50)// 8. 判断是否有人已经获胜,endGame为true,则无法点击if (endGame) {// 游戏结束return}// 6.2 判断当前位置是否已经存在棋子if (circles[i][j]) {// 提醒用户, 这里已有棋子tip.innerText = `不能重复落子!当前是${isBlack ? '黑' : '白'}棋的回合`return;}let x = i * 50  // 让棋子在网格线正确的位置let y = j * 50context.beginPath()context.arc(x, y, 20, 0, 2 * Math.PI)// 6.1 把棋子的坐标存到二维数组里circles[i][j] = isBlack ? 'black' : 'white'// console.log(circles);        // 设置黑白棋子的渐变色let gBlack = context.createRadialGradient(x - 8, y - 8, 0, x, y, 20)gBlack.addColorStop(0, '#999')gBlack.addColorStop(1, '#000')let gWhite = context.createRadialGradient(x - 5, y - 10, 18, x, y, 40)gWhite.addColorStop(0, '#fff')gWhite.addColorStop(1, '#666')// 判断当前棋子颜色变量,给棋子黑白不同颜色context.fillStyle = isBlack ? gBlack : gWhite// 视频里老师的代码// let tx = isBlack ? x - 10 : x + 10;// let ty = isBlack ? y - 10 : y + 10;// let g = context.createRadialGradient(tx, ty, 0, tx, ty, 30);// g.addColorStop(0, isBlack ? '#ccc' : '#666');// g.addColorStop(1, isBlack ? '#000' : '#fff');// context.fillStyle = g// 视频里老师的代码 ENDcontext.fill()context.closePath()// 7.判断当前是否已有对应的棋子连成5颗,endGame为true则出现获胜提示字endGame = checkVertical(i, j) || checkHorizontal(i, j) || checkNWtoSE(i, j) || checkNEtoSW(i, j)if (endGame) {tip.innerText = `${isBlack ? '黑' : '白'}方获胜!`return}// 提醒用户换人let text = isBlack ? '请白棋落子' : '请黑棋落子'tip.innerText = textisBlack = !isBlack})// // 开始判断4个方向的棋子相连情况//// 纵向查找是否有5个连续相同的棋子function checkVertical(row, col) {// 记录向上的次数let up = 0;// 记录向下的次数let down = 0;let target = isBlack ? 'black' : 'white';let times = 0;// 定义当前总共有几个已经连在一起let count = 1; // 初始值,自己本身算1个// 5个棋子连成线即可结束 times < 6while (times < 6) {times++;// 探寻上边up++;// 当col - up > 0,说明棋子的上侧还在棋盘内,开始进行判断if (col - up > 0) {if (circles[row][col - up] == target) {count++;}}// 探寻下边down++;// 当col+down < 16,说明棋子的下侧还在棋盘内,开始进行判断if (col + down < 16) {if (circles[row][col + down] == target) {count++;}}// 在col - up与col + down都在棋盘里的情况在,如果相邻棋子不是target,则break,或如果count已满足5颗相连,则breakif (col - up > 0 && col + down < 16) {if (count >= 5 || (circles[row][col - up] != target && circles[row][col + down] != target)) {break;}}}return count >= 5;}// 横向查找是否有5个连续相同的棋子function checkHorizontal(row, col) {// 记录向左的次数let left = 0;// 记录向右的次数let right = 0;let target = isBlack ? 'black' : 'white';let times = 0;// 定义当前总共有几个已经连在一起let count = 1; // 初始值,自己本身算1个// 为避免出现死循环,设置一个循环上限 5while (times < 6) {times++;// 探寻左边left++;// 当row-left>0,说明棋子的左侧还在棋盘内,开始进行判断if (row - left > 0) {if (circles[row - left][col] == target) {count++;}}right++;// 当row+right<16,说明棋子的右侧还在棋盘内,开始进行判断if (row + right < 16) {if (circles[row + right][col] == target) {count++;}}if (row + right < 16 && row - left > 0) {if (count >= 5 || (circles[row + right][col] != target && circles[row - left][col] != target)) {break;}}}return count >= 5;}// 判断 \ 左上到右下的方向function checkNWtoSE(row, col) {let lt = 0; // 左上let rb = 0; // 右下let target = isBlack ? 'black' : 'white';let times = 0;let count = 1; // 初始值,自己本身算1个while (times < 5) {times++;// 探寻左上方向lt++;if (col - lt > 0 && row - lt > 0) {if (circles[row - lt][col - lt] == target) {count++;}}// 探寻右下方向rb++;if (row + rb < 16 && col + rb < 16) {if (circles[row + rb][col + rb] == target) {count++;}}if (row - lt > 0 && col - lt && row + rb < 16 && col + rb < 16) {if (count >= 5 || (circles[row - lt][col - lt] != target && circles[row + rb][col + rb] != target)) {break;}}}return count >= 5;}// 判断 / 右上到左下的方向function checkNEtoSW(row, col) {let rt = 0; // 右上let lb = 0; // 左下let target = isBlack ? 'black' : 'white';let times = 0;let count = 1; // 初始值,自己本身算1个while (times < 5) {times++;// 探寻右上rt++;if (col - rt > 0 && row + rt < 16) {if (circles[row + rt][col - rt] && circles[row + rt][col - rt] == target) {count++;};}// 探寻左下lb++;if (row - lb > 0 && col + lb < 16) {if (circles[row - lb][col + lb] && circles[row - lb][col + lb] == target) {count++;};}if (row - lb > 0 && col + lb < 16) {if (count >= 5 || (circles[row + rt][col - rt] != target && circles[row - lb][col + lb] != target)) {break;}}}return count >= 5;}</script>
</body></html>

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HTML入门】Sublime Text 4与 Phpstorm

文章目录 前言一、环境基础1.Sublime Text 42.Phpstorm(1)安装(2)启动Phpstorm(3)“启动”码 二、HTML1.HTML简介(1)什么是HTML(2)HTML版本及历史(3)HTML基本结构 2.HTML简单语法(1)HTML标签语法(2)HTML常用标签(3)表格(4)特殊字符 总结 前言 在当今的软件开发领域&#xff0c…

Kubernetes学习之包管理工具(Helm)

一、基础知识 1.如果我们需要开发微服务架构的应用&#xff0c;组成应用的服务可能很多&#xff0c;使用原始的组织和管理方式就会非常臃肿和繁琐以及较难管理&#xff0c;此时我们需要一个更高层次的工具将这些配置组织起来。 2.helm架构&#xff1a; chart:一个应用的信息集合…

Kamailio 不通过 dmq 实现注册复制功能

春节期间找到一篇文章&#xff0c;需要 fg 才能看到&#xff1a; https://medium.com/tumalevich/kamailio-registration-replication-without-dmq-65e225f9a8a7 kamailio1 192.168.56.115 kamailio2 192.168.56.116 kamailio3 192.168.56.117 route[HANDLE_REPLICATION] {i…

grpc 和 http 的区别---二进制vsJSON编码

gRPC 和 HTTP 是两种广泛使用的通信协议&#xff0c;各自适用于不同的场景。以下是它们的详细对比与优势分析&#xff1a; 一、核心特性对比 特性gRPCHTTP协议基础基于 HTTP/2基于 HTTP/1.1 或 HTTP/2数据格式默认使用 Protobuf&#xff08;二进制&#xff09;通常使用 JSON/…

Intel 与 Yocto 项目的深度融合:全面解析与平台对比

在嵌入式 Linux 领域&#xff0c;Yocto 项目已成为构建定制化 Linux 发行版的事实标准&#xff0c;广泛应用于不同架构的 SoC 平台。Intel 作为 x86 架构的领导者&#xff0c;在 Yocto 生态中投入了大量资源&#xff0c;为其嵌入式处理器、FPGA 和 AI 加速硬件提供了完整的支持…

kubernetes(二)

文章目录 NamespacePodLabelDeploymentService Namespace 在Kubernetes系统中&#xff0c;Namespace是一种至关重要的资源类型&#xff0c;其主要功能在于实现多套环境的资源隔离或者多租户的资源隔离&#xff0c;默认情况下所有的Pod都能够相互访问&#xff0c;但如果不想让两…

巧妙利用数据结构优化部门查询

目录 一、出现的问题 部门树接口超时 二、问题分析 源代码分析 三、解决方案 具体实现思路 四、优化的效果 一、出现的问题 部门树接口超时 无论是在A项目还是在B项目中&#xff0c;都存在类似的页面&#xff0c;其实就是一个部门列表或者叫组织列表。 从页面的展示形式…

【数据分析】案例04:豆瓣电影Top250的数据分析与Web网页可视化(numpy+pandas+matplotlib+flask)

豆瓣电影Top250的数据分析与Web网页可视化(numpy+pandas+matplotlib+flask) 豆瓣电影Top250官网:https://movie.douban.com/top250写在前面 实验目的:实现豆瓣电影Top250详情的数据分析与Web网页可视化。电脑系统:Windows使用软件:PyCharm、NavicatPython版本:Python 3.…

【线程】基于环形队列的生产者消费者模型

1 环形队列 环形队列采用数组来模拟&#xff0c;用取模运算来模拟环状特性。 1.如何判断环形队列为空或者为满? 当环形队列为空时&#xff0c;头和尾都指向同一个位置。当环形队列为满时&#xff0c;头和尾也都指向同一个位置。 因此&#xff0c; 可以通过加计数器或者标记…

Vue指令v-html

目录 一、Vue中的v-html指令是什么&#xff1f;二、v-html指令与v-text指令的区别&#xff1f; 一、Vue中的v-html指令是什么&#xff1f; v-html指令的作用是&#xff1a;设置元素的innerHTML&#xff0c;内容中有html结构会被解析为标签。 二、v-html指令与v-text指令的区别…

OPENGLPG第九版学习 - 着色器基础

文章目录 2.1 着色器与OpenGL2.2 0penGL的可编程管线2.3 OpenGL着色语言GLSL概述2.3.1 使用GLSL构建着色器变量的声明变量的作用域变量的初始化构造函数 、 类型转换聚合类型访问向量和矩阵中的元素结构体数组多维数组 2.3.2 存储限制符const 存储限制符in 存储限制符out 存储限…

路径规划之启发式算法之二十九:鸽群算法(Pigeon-inspired Optimization, PIO)

鸽群算法(Pigeon-inspired Optimization, PIO)是一种基于自然界中鸽子群体行为的智能优化算法,由Duan等人于2014年提出。该算法模拟了鸽子在飞行过程中利用地标、太阳和磁场等导航机制的行为,具有简单、高效和易于实现的特点,适用于解决连续优化问题。 更多的仿生群体算法…

Docker Compose的使用

文章首发于我的博客&#xff1a;https://blog.liuzijian.com/post/docker-compose.html 目录 Docker Compose是什么Docker Compose安装Docker Compose文件Docker Compose常用命令案例&#xff1a;部署WordPress博客系统 Docker Compose是什么 Docker Compose是Docker官方的开源…

AP单类平均准确率

P_true N_true P_pred TP Fp N_pred FN TNP NTP&#xff08;真正样本&#xff0c;与真实框IoU大于阈值的框&#xff09; FP&#xff08;假正样本&#xff0c;与真实框IoU小于阈值的框&#xff09; TN&#xff08;真负样本&#xff0c;背景&#xff09;…

Leetcode—1427. 字符串的左右移【简单】Plus

2025每日刷题&#xff08;206&#xff09; Leetcode—1427. 字符串的左右移 实现代码 class Solution { public:string stringShift(string s, vector<vector<int>>& shift) {// shift[i] [dir, amount]// dir 0(左) or 1(右)// 左表示正, 右表示负int len…

机器学习10

自定义数据集 使用scikit-learn中svm的包实现svm分类 代码 import numpy as np import matplotlib.pyplot as pltclass1_points np.array([[1.9, 1.2],[1.5, 2.1],[1.9, 0.5],[1.5, 0.9],[0.9, 1.2],[1.1, 1.7],[1.4, 1.1]])class2_points np.array([[3.2, 3.2],[3.7, 2.9],…

股票入门知识

股票入门&#xff08;更适合中国宝宝体制&#xff09; 股市基础知识 本文介绍了股票的基础知识&#xff0c;股票的分类&#xff0c;各板块发行上市条件&#xff0c;股票代码&#xff0c;交易时间&#xff0c;交易规则&#xff0c;炒股术语&#xff0c;影响股价的因素&#xf…

Golang 并发机制-3:通道(channels)机制详解

并发编程是一种创建性能优化且响应迅速的软件的强大方法。Golang&#xff08;也称为 Go&#xff09;通过通道&#xff08;channels&#xff09;这一特性&#xff0c;能够可靠且优雅地实现并发通信。本文将揭示通道的概念&#xff0c;解释其在并发编程中的作用&#xff0c;并提供…

C#,入门教程(11)——枚举(Enum)的基础知识和高级应用

上一篇&#xff1a; C#&#xff0c;入门教程(10)——常量、变量与命名规则的基础知识https://blog.csdn.net/beijinghorn/article/details/123913570 不会枚举&#xff0c;就不会编程&#xff01; 枚举 一个有组织的常量系列 比如&#xff1a;一个星期每一天的名字&#xf…

读书笔记--分布式架构的异步化和缓存技术原理及应用场景

本篇是在上一篇的基础上&#xff0c;主要对分布式应用架构下的异步化机制和缓存技术进行学习&#xff0c;主要记录和思考如下&#xff0c;供大家学习参考。大家知道原来传统的单一WAR应用中&#xff0c;由于所有数据都在同一个数据库中&#xff0c;因此事务问题一般借助数据库事…