当前位置: 首页 > article >正文

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>

相关文章:

20-30 五子棋游戏

20-分析五子棋的实现思路_哔哩哔哩_bilibili20-分析五子棋的实现思路是一次性学会 Canvas 动画绘图&#xff08;核心精讲50个案例&#xff09;2023最新教程的第21集视频&#xff0c;该合集共计53集&#xff0c;视频收藏或关注UP主&#xff0c;及时了解更多相关视频内容。https:…...

抽象类与抽象方法详解

目录 一、 基本概念 1.抽象类&#xff08;Abstract Class&#xff09;&#xff1a; 2.抽象方法&#xff08;Abstract Method&#xff09;&#xff1a; 二、示例代码 抽象类 抽象方法 三、抽象类的使用场景 四、 抽象类与接口的对比 五、注意事项 六、总结 一、 基本概…...

受击反馈HitReact、死亡效果Death Dissolve、Floating伤害值Text(末尾附 客户端RPC )

受击反馈HitReact 设置角色受击标签 (GameplayTag基本了解待补充) 角色监听标签并设置移动速度 创建一个受击技能&#xff0c;并应用GE 实现设置角色的受击蒙太奇动画 实现角色受击时播放蒙太奇动画&#xff0c;为了保证通用性&#xff0c;将其设置为一个函数&#xff0c;并…...

应用程序中处理文件上传的方法

在应用程序中处理文件上传通常涉及以下几个步骤: 一、前端准备 前端负责收集文件,并通过 HTTP 请求将其发送到服务器。常见的方法包括: ①HTML <form>; 表单:使用 enctype="multipart/form-data" 属性指定表单支持文件上传。 ②JavaScript (AJAX):可以使…...

Java进阶six junit单元测试,反射,注解,动态代理

前言 Java进阶课程的第六篇&#xff0c;也是最后一篇&#xff0c;junit单元测试,反射,注解,动态代理相关内容 包含知识点 junit单元测试 反射 1.内部类Student&#xff1a; 包含私有/公共字段和方法 包含默认构造器和私有构造器 2.获取Class对象的三种方式&#xff1a; .…...

STM32 LED呼吸灯

接线图&#xff1a; 这里将正极接到PA0引脚上&#xff0c;负极接到GND&#xff0c;这样就高电平点亮LED&#xff0c;低电平熄灭。 占空比越大&#xff0c;LED越亮&#xff0c;占空比越小&#xff0c;LED越暗 PWM初始化配置 输出比较函数介绍&#xff1a; 用这四个函数配置输…...

栈和队列特别篇:栈和队列的经典算法问题

图均为手绘,代码基于vs2022实现 系列文章目录 数据结构初探: 顺序表 数据结构初探:链表之单链表篇 数据结构初探:链表之双向链表篇 链表特别篇:链表经典算法问题 数据结构:栈篇 数据结构:队列篇 文章目录 系列文章目录前言一.有效的括号(leetcode 20)二.用队列实现栈(leetcode…...

用一个例子详细说明python单例模式

单例模式是一种设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。这在需要控制资源&#xff08;如数据库连接、文件系统等&#xff09;的访问时非常有用。 下面是一个使用Python实现单例模式的例子&#xff1a; class Singleton:…...

Kotlin 委托详解

Kotlin 委托详解 引言 Kotlin 作为一种现代化的编程语言&#xff0c;在 Android 开发等领域得到了广泛的应用。在 Kotlin 中&#xff0c;委托&#xff08;Delegation&#xff09;是一种强大的特性&#xff0c;它可以让我们以更简洁的方式实现代码的复用和扩展。本文将详细解析…...

什么是词嵌入?Word2Vec、GloVe 与 FastText 的区别

自然语言处理(NLP)领域的核心问题之一,是如何将人类的语言转换成计算机可以理解的数值形式,而词嵌入(Word Embedding)正是为了解决这个问题的重要技术。本文将详细讲解词嵌入的概念及其经典模型(Word2Vec、GloVe 和 FastText)的原理与区别。 1. 什么是词嵌入(Word Em…...

2024年数据记录

笔者注册时间超过98.06%的用户 CSDN 原力是衡量一个用户在 CSDN 的贡献和影响力的系统&#xff0c;笔者原力值超过99.99%的用户 其他年度数据...

DBO优化最近邻分类预测matlab

蜣螂优化算法&#xff08;Dung Beetle Optimizer&#xff0c;简称 DBO&#xff09;作为一种新兴的群智能优化算法&#xff0c;于 2022 年末被提出&#xff0c;其灵感主要来源于蜣螂的滚球、跳舞、觅食、偷窃以及繁殖等行为。 本次使用的数据为 Excel 格式的分类数据集。该数据…...

Harbor 部署

harbor镜像仓库搭建 版本v2.10.3 文章目录 一. docker 安装 harbor1. harbor 配置http访问1.1 下载harbor二进制包1.2 修改配置文件1.3 运行1.4 访问 2.【可选】harbor 配置https访问2.1 自签证书2.1 修改配置文件2.3 修改hosts文件2.4 运行2.5 访问 二. k8s 安装harbor1 .安装…...

PSpice for TI体验

前言 基于 从零开始学 PSpice for TI 仿真工具 - 手把手操作实训课程_哔哩哔哩_bilibili 体验PSpice for TI的功能&#xff0c;并记录下来。文章内容大部分都参考自视频&#xff0c;可以理解成图文版。目前发现是没有支持中文语言&#xff0c;而且部分仿真&#xff0c;时间消耗…...

数据结构与算法 —— 常用算法模版

数据结构与算法 —— 常用算法模版 二分查找素数筛最大公约数与最小公倍数 二分查找 人间若有天堂&#xff0c;大马士革必在其中&#xff1b;天堂若在天空&#xff0c;大马士革必与之齐名。 —— 阿拉伯谚语 算法若有排序&#xff0c;二分查找必在其中&#xff1b;排序若要使用…...

苯乙醇苷类化合物的从头生物合成-文献精读108

Complete pathway elucidation of echinacoside in Cistanche tubulosa and de novo biosynthesis of phenylethanoid glycosides 管花肉苁蓉中松果菊苷全生物合成途径解析及苯乙醇苷类化合物的从头生物合成 摘要 松果菊苷&#xff08;ECH&#xff09;是最具代表性的苯乙醇苷…...

【C++】设计模式详解:单例模式

文章目录 Ⅰ. 设计一个类&#xff0c;不允许被拷贝Ⅱ. 请设计一个类&#xff0c;只能在堆上创建对象Ⅲ. 请设计一个类&#xff0c;只能在栈上创建对象Ⅳ. 请设计一个类&#xff0c;不能被继承Ⅴ. 请设计一个类&#xff0c;只能创建一个对象&#xff08;单例模式&#xff09;&am…...

CAN总线数据采集与分析

CAN总线数据采集与分析 目录 CAN总线数据采集与分析1. 引言2. 数据采集2.1 数据采集简介2.2 数据采集实现3. 数据分析3.1 数据分析简介3.2 数据分析实现4. 数据可视化4.1 数据可视化简介4.2 数据可视化实现5. 案例说明5.1 案例1:数据采集实现5.2 案例2:数据分析实现5.3 案例3…...

解决vsocde ssh远程连接同一ip,不同端口情况下,无法区分的问题

一般服务器会通过镜像分身或者容器的方式&#xff0c;一个ip分出多个端口给多人使用&#xff0c;但如果碰到需要连接同一user&#xff0c;同一个ip,不同端口的情况&#xff0c;vscode就无法识别&#xff0c;如下图所示&#xff0c;vscode无法区分该ip下不同端口的连接&#xff…...

AJAX案例——图片上传个人信息操作

黑马程序员视频地址&#xff1a; AJAX-Day02-11.图片上传https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p26 图片上传 <!-- 文件选择元素 --><input type"file"…...

团体程序设计天梯赛-练习集——L1-029 是不是太胖了

前言 5分级别里面目前做到的最难的一道题&#xff0c;但是非常简单&#xff0c;5分的题看看写点代码就行了。 L1-029 是不是太胖了 据说一个人的标准体重应该是其身高&#xff08;单位&#xff1a;厘米&#xff09;减去100、再乘以0.9所得到的公斤数。已知市斤的数值是公斤数…...

ubuntu20.04.6下运行VLC-Qt例子simple-player

下载examples-master.zip&#xff08;https://github.com/vlc-qt/examples&#xff09;&#xff0c;编译运行simple-player 参考链接&#xff1a; https://blog.csdn.net/szn1316159505/article/details/143743735 本文运行环境 Qt 5.15.2 Qt creator 5.0.2 主要步骤&#xf…...

LabVIEW温度修正部件测试系统

LabVIEW温度修正部件测试系统 这个基于LabVIEW的温度修正部件测试系统旨在解决飞行器温度测量及修正电路的测试需求。该系统的意义在于提供一个可靠的测试平台&#xff0c;用于评估温度修正部件在实际飞行器环境中的性能表现&#xff0c;从而确保飞行器的安全性和可靠性。 系统…...

细说机器学习算法之ROC曲线用于模型评估

系列文章目录 第一章&#xff1a;Pyhton机器学习算法之KNN 第二章&#xff1a;Pyhton机器学习算法之K—Means 第三章&#xff1a;Pyhton机器学习算法之随机森林 第四章&#xff1a;Pyhton机器学习算法之线性回归 第五章&#xff1a;Pyhton机器学习算法之有监督学习与无监督…...

Python3 【装饰器】项目实战:5个新颖的学习案例

Python3 【装饰器】项目实战&#xff1a;5个新颖的学习案例 以下是 5 个使用 Python 装饰器的综合应用项目&#xff0c;这些项目具有新颖性、前瞻性和实用性。每个项目都包含完整的代码、解释说明、测试案例和执行结果。 项目 1&#xff1a;API 请求限流器 描述&#xff1a;实…...

【深度学习】 UNet详解

UNet 是一种经典的卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;架构&#xff0c;专为生物医学图像分割任务设计。该模型于 2015 年由 Olaf Ronneberger 等人在论文《U-Net: Convolutional Networks for Biomedical Image Segmentation》中首次提出&…...

DeepSeek本地部署(windows)

一、下载并安装Ollama 1.下载Ollama Ollama官网:Ollama 点击"Download",会跳转至下载页面。 点击"Download for Windows"。会跳转Github进行下载,如下载速度过慢,可在浏览器安装GitHub加速插件。 2.安装Ollama 双击下载的安装文件,点击"Inst…...

简要介绍C语言/C++的三目运算符

三元运算符是C语言和C中的一种简洁的条件运算符&#xff0c;它的形式为&#xff1a; 条件表达式 ? 表达式1 : 表达式2; 三元运算符的含义 条件表达式&#xff1a;这是一个布尔表达式&#xff0c;通常是一个比较操作&#xff08;如 >、<、 等&#xff09;。 表达式1&am…...

SpringCloud系列教程:微服务的未来(十九)请求限流、线程隔离、Fallback、服务熔断

前言 前言 在现代微服务架构中&#xff0c;系统的高可用性和稳定性至关重要。为了解决系统在高并发请求或服务不可用时出现的性能瓶颈或故障&#xff0c;常常需要使用一些技术手段来保证服务的平稳运行。请求限流、线程隔离、Fallback 和服务熔断是微服务中常用的四种策略&…...

STM32 对射式红外传感器配置

这次用的是STM32F103的开发板&#xff08;这里面的exti.c文件没有how to use this driver 配置说明&#xff09; 对射式红外传感器 由一个红外发光二极管和NPN光电三极管组成&#xff0c;M3固定安装孔&#xff0c;有输出状态指示灯&#xff0c;输出高电平灯灭&#xff0c;输出…...