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

自学系列之小游戏---贪吃蛇(vue3+ts+vite+element-plus+sass)(module.scss + tsx)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、逻辑设计分析
  • 二、代码实现
    • 1.TS interface
    • 2.javascript
    • 3.页面样式(Sass)
  • 三、截图展示
  • 四、总结


前言

主要技术如下:vue3 、vite 、ts、element-plus 、 tsx、sass、xxx.module.scss


一、逻辑设计分析

数据定义定义

index  : 总下标
colNum : 列数
colIdx : 列下标
rowNum : 行数
rowIdx : 行下标
isSnake: 是否属于模型内容
isHead : 是否属于模型头部
isTail : 是否属于模型尾部

生成网格

1、生成整体网格数据单位
2、生成所有行数据
3、生成所有列数据

初始化snake

1、生成默认snake长度
2、生成默认snake位置
3、定义snake首尾

速度

1、定义初始速度
2、定义加速度模型

生成目标

1、随机生成
2、新增eat目标单元* 生成时排除snake模型部分,随机生成位置

snake移动逻辑

1、移动UI方案* 网格背景变化* 变化速度取移动速度间隔值
2、移动方向方案* 记录移动方向 默认向右* 当前方向向右`向上取当前snake头部行数加一与行下标取下一次位移目标位置为头部数据改变前进方向为向上撞自己身体判断向右操作无效向右撞墙判断撞自己身体判断(后期加入向右加速度,keydown加速度,keyup取消加速度)向下取当前snake头部行数减一与行下标取下一次位移目标位置为头部数据改变前进方向为向下撞自己身体判断向左操作无效`* 当前方向向左`向上取当前snake头部行数加一与行下标取下一次位移目标位置为头部数据改变前进方向为向上撞自己身体判断向右操作无效向下取当前snake头部行数减一与行下标取下一次位移目标位置为头部数据改变前进方向为向下撞自己身体判断向左操作无效向左撞墙判断撞自己身体判断(后期加入向左加速度,keydown加速度,keyup取消加速度)`* 当前方向向上`向上操作无效向上撞墙判断撞自己身体判断(后期加入向上加速度,keydown加速度,keyup取消加速度)向右取当前snake头部列数加一与列下标取下一次位移目标位置为头部数据改变前进方向为向右撞自己身体判断向下操作无效向左操作取当前snake头部列数减一与列下标取下一次位移目标位置为头部数据改变前进方向为向左撞自己身体判断`* 当前方向向下`向上操作无效向右取当前snake头部列数加一与列下标取下一次位移目标位置为头部数据改变前进方向为向右撞自己身体判断向下操作无效向下撞墙判断撞自己身体判断(后期加入向上加速度,keydown加速度,keyup取消加速度)向左操作取当前snake头部列数减一与列下标取下一次位移目标位置为头部数据改变前进方向为向左撞自己身体判断`

游戏结束判断

1、撞墙死亡
2、撞自己身体死亡
3、身体占满网格游戏通关

分数计算

1、身总长度减去初始身体长度

二、代码实现

1.TS interface

代码如下(示例):

declare namespace Ad{namespace Game{namespace Snake {interface BaseItem {/** 下标 */index:number,/** 列数 */colNum:number,/** 列坐标 */colIdx:number,/** 行数 */rowNum:number,/** 行坐标 */rowIdx:number,/** 是否属于目标得分点 */newSpot:boolean,/** 是否属于模型内容 */isSnake:boolean,/** 是否属于模型头部 */isHead:boolean,/** 是否属于模型尾部 */isTail:boolean}}}
}

2.javascript

代码如下:

import { Ref, computed, defineComponent, reactive, ref } from "vue";
import SnakeScss from './greedySnake.module.scss'
import '../game.scss'
import { ElMessageBox } from 'element-plus'
import { secondsToDate } from "@/utils/utils";export default defineComponent({setup(props, ctx) {/** 行-基点数 */const row    = 29/** 列-基点数 */const column = 29/** 时间 */let timer    = ref(0)/** 当前游戏状态 */let curState = ref(false)/** 贪吃蛇数据模型 */let snakeData:Ref<Array<Ad.Game.Snake.BaseItem>> = ref([])/** 时间记录器 */let timeStamp: undefined | NodeJS.Timer;/** 速度移动记录器 */let timeStampMove: undefined | NodeJS.Timer;/** 前进方向 */let direction = ref('right')/** 能用做得分点的框 */let canCreatStops:Ref<Array<number>> = ref([])/** 得分 */let score = computed(() => snakeData.value.length - 5 )/** 移动速度 */let speed = computed(() => {const baseSpeed = 500return baseSpeed - score.value * ((500 - 40) / gridData.length)})const snakeMove = () => {let nextItem:Ad.Game.Snake.BaseItem | null = nullconst curLastSpot = snakeData.value[snakeData.value.length-1]switch(direction.value){case 'top':nextItem = gridData[curLastSpot.index - row]break;case 'right':nextItem = gridData[curLastSpot.index + 1]if(nextItem.rowNum !== curLastSpot.rowNum) nextItem = nullbreak;case 'bottom':nextItem = gridData[curLastSpot.index + row]break;case 'left':nextItem = gridData[curLastSpot.index - 1]if(nextItem.rowNum !== curLastSpot.rowNum) nextItem = nullbreak;default:console.error('方向错误:', direction.value)}if(nextItem?.isSnake || !nextItem){gameOver()} else {updateSnake(nextItem)}}const windowKeyDown = (ev:KeyboardEvent) => {const { keyCode } = evev.preventDefault()switch(keyCode){case 37: //左键if(direction.value === 'right') returnelse direction.value = 'left'break;case 38://上键if(direction.value === 'bottom') returnelse direction.value = 'top'break;case 39://右键if(direction.value === 'left') returnelse direction.value = 'right'break;case 40://下键if(direction.value === 'top') returnelse direction.value = 'bottom'break;default:console.log('keyCode:', keyCode)}snakeMove()}/** 设置运动时间更新机制 */const setSpeedTime = () => {if(!curState.value) returnif(timeStampMove)clearTimeout(timeStampMove)timeStampMove = setTimeout(() => {snakeMove()setSpeedTime()}, speed.value)}/** 开始游戏 */const startGame = () => {window.addEventListener('keydown', windowKeyDown)initNewSpot()curState.value = truesetSpeedTime()timeStamp = setInterval(() => timer.value += 1, 1000)}/** 重置 */const resetGame = () => {window.removeEventListener('keydown', windowKeyDown)clearInterval(timeStamp)clearTimeout(timeStampMove)curState.value  = false}/** 游戏结束 */const gameOver = () => {resetGame()ElMessageBox.confirm(`本次存活时间${secondsToDate(timer.value, 'HH*mm*ss', true )},本次得分${score.value},再接再厉。`,'游戏结束',{confirmButtonText: 'OK',showCancelButton:false,showClose:false,closeOnClickModal:false,closeOnPressEscape:false,type: 'warning',}).then(res => {timer.value     = 0snakeData.value = []direction.value = 'right'initGrid()})}/** 得分、计时、操作面板生成 */const renderHeader = () => {return <div class='header'><div class='header-item'><div>时间:</div><div class='number-value'>{ secondsToDate(timer.value, 'HH:mm:ss', true) || '00:00:00' }</div></div><div class='header-item'><div>得分:</div><div class='number-value'>{ score.value || 0 }</div></div><div class='header-item'>{curState.value ? <div class='btn' onClick={ gameOver }>结束游戏</div> : <div class='btn' onClick={ startGame }>开始游戏</div>}</div></div>}/** 网格数据 */let gridData:Array<Ad.Game.Snake.BaseItem> = reactive([])const renderGrid = () => {return <div class={SnakeScss['snake-grid']}>{ gridData.map(gridItem => renderGridItem(gridItem)) }</div>}const renderGridItem = (gridItem:Ad.Game.Snake.BaseItem) => {const activeClass = gridItem.isSnake ? SnakeScss['grid-item_active'] : ''let directionClass:{[key:string]:string} = {top:'snake-title_top',right:'snake-title_right',bottom:'snake-title_bottom',left:'snake-title_left'}const headClass = gridItem.isHead ? SnakeScss[directionClass[direction.value]] : ''const newSpotClass = gridItem.newSpot ? SnakeScss['grid-item_new-spot'] : ''return <div class={[SnakeScss['grid-item'], activeClass, headClass, newSpotClass] }>{gridItem.isHead && [<div class={SnakeScss['eye']}></div>,<div class={SnakeScss['eye']}></div>]}</div>}/** 初始化网格 */const initGrid = () => {gridData = []const allGridNums = row * columnfor (let index = 0; index < allGridNums; index++) {let currentRow    = Math.ceil((index + 1) / row)let currentColumn = (index+1) % rowlet currentGrid:Ad.Game.Snake.BaseItem = {index:index,rowNum:currentRow,rowIdx:currentColumn,colNum:currentColumn,colIdx:currentRow,newSpot:false,isSnake:false,isHead:false,isTail:false}gridData.push(currentGrid)}initSnakePosition()}/** 初始化贪吃蛇数据模型 */const initSnakePosition = () => {const rowMidDrop    = Math.ceil(row / 2)const columnMidDrop = Math.ceil(column / 2)const mindSpotIdx = ((rowMidDrop - 1) * row) + (columnMidDrop - 1)const snakeDefaultSpotIdxs = [mindSpotIdx-2, mindSpotIdx-1, mindSpotIdx, mindSpotIdx+1, mindSpotIdx+2]for (let index = 0; index < snakeDefaultSpotIdxs.length; index++) {gridData[snakeDefaultSpotIdxs[index]].isSnake = trueif(index === 0){gridData[snakeDefaultSpotIdxs[index]].isTail = true}if(index === snakeDefaultSpotIdxs.length - 1){gridData[snakeDefaultSpotIdxs[index]].isHead = true}snakeData.value.push(gridData[snakeDefaultSpotIdxs[index]])}}/*** 更新贪吃蛇位置和长度* @param nextItem 下一个目标位置*/const updateSnake = (nextItem:Ad.Game.Snake.BaseItem) => {const preIdx = snakeData.value[snakeData.value.length - 1].indexgridData[preIdx].isHead = falsesnakeData.value.push(nextItem)if(snakeData.value.length == gridData.length){resetGame()ElMessageBox.confirm(`本次存活时间${secondsToDate(timer.value, 'HH*mm*ss', true )},本次得分${score.value},太厉害了,游戏通关。`,'通关',{confirmButtonText: 'OK',showCancelButton:false,showClose:false,closeOnClickModal:false,closeOnPressEscape:false,type: 'success',}).then(res => {timer.value     = 0snakeData.value = []direction.value = 'right'initGrid()})return}gridData[nextItem.index].isHead = truegridData[nextItem.index].isSnake = trueif(!nextItem.newSpot) {const delItme:Ad.Game.Snake.BaseItem = snakeData.value.shift() as Ad.Game.Snake.BaseItemgridData[delItme.index].isSnake = false} else {gridData[snakeData.value[snakeData.value.length - 1].index].newSpot = falseinitNewSpot()}}/** 生成新的目标得分点 */const initNewSpot = () => {const snakeDataIdxs = snakeData.value.map(item => item.index)canCreatStops.value = gridData.filter(item => !snakeDataIdxs.includes(item.index)).map(item => item.index)const idx = Number((Math.random() * canCreatStops.value.length - 1).toFixed(0))gridData[canCreatStops.value[idx]].newSpot = true}initGrid()return () => <div class='game-content'>{ renderHeader() }{ renderGrid() }</div>}
})

3.页面样式(Sass)

greedySnake.module.scss

.snake-grid{display: flex;flex-wrap: wrap;border: 1px solid #eee;border-radius: 4px;margin: 0 auto;margin-top: 20px;width: 580px;.grid-item{width: 20px;height: 20px;.eye{width: 5px;height: 5px;background-color: #fff;border-radius: 50%;margin-left: 10px;margin-top: 3px;}}.grid-item:nth-child(2n){background-color:rgb(248, 248, 248)}.grid-item:nth-child(2n-1){background-color:rgb(255, 255, 255)}.grid-item_active{background-color: rgb(0, 0, 0) !important;}.snake-title_top{border-top-right-radius: 50%;border-top-left-radius: 50%;}.snake-title_right{border-top-right-radius: 50%;border-bottom-right-radius: 50%;}.snake-title_bottom{border-bottom-right-radius: 50%;border-bottom-left-radius: 50%;}.snake-title_left{border-top-left-radius: 50%;border-bottom-left-radius: 50%;}.grid-item_new-spot{background-color: rgb(0, 0, 0) !important;}
}

game.scss

.game-content{width: 900px;margin: 0 auto;height: 700px;margin-top: 40px;box-shadow: 0px 1px 10px 4px #ccc;border-radius: 10px;user-select: none;.header{display: flex;justify-content: space-around;height: 60px;border-bottom: 1px solid #eee;margin: 0 20px;align-items: center;.header-item{display: flex;align-items: center;font-weight: bold;font-size: 16px;.number-value{font-size: 18px;}.btn{width: 120px;border-radius: 10px;height: 36px;text-align: center;line-height: 36px;box-shadow: 0px 1px 10px 0px #ccc;cursor: pointer;}}}
}

三、截图展示

在这里插入图片描述
在这里插入图片描述

四、总结

实现贪吃蛇小游戏使用的技术有为了使用而使用的嫌疑,使用还有些不太熟练,望大家多多理解,如有建议欢迎多多评论或私信指教。

相关文章:

自学系列之小游戏---贪吃蛇(vue3+ts+vite+element-plus+sass)(module.scss + tsx)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、逻辑设计分析二、代码实现1.TS interface2.javascript3.页面样式&#xff08;Sass&#xff09; 三、截图展示四、总结 前言 主要技术如下&#xff1a;vue3…...

JAVA项目中什么是DTO、DAO、PO、Controller、Common

DTO&#xff08;Data Transfer Object&#xff09;和DAO&#xff08;Data Access Object&#xff09;是Java中常用的两种设计模式&#xff0c;它们在软件开发中扮演着不同的角色。 1. **DTO (Data Transfer Object)**&#xff1a;数据传输对象&#xff0c;主要用于在远程调用等…...

Alibaba Druid整合

文章目录 方式一&#xff1a;自定义整合方式二&#xff1a;使用 Druid 官方的 Starter Druid官网&#xff1a;https://github.com/alibaba/druidDruid官网文档&#xff08;中文&#xff09;&#xff1a;https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%…...

SpringCloud 微服务全栈体系(三)

第五章 Nacos 注册中心 国内公司一般都推崇阿里巴巴的技术&#xff0c;比如注册中心&#xff0c;SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心。 一、认识和安装 Nacos 1. 认识 Nacos Nacos是阿里巴巴的产品&#xff0c;现在是SpringCloud中的一个组件。相比Eure…...

VScode连接的服务器上使用jupyter显示请选择内核源

问题复现 我实在VScode上用ssh-remote连接的服务器&#xff0c;想用.ipynb文件上写东西&#xff0c;结果窗口上方弹出一个输入框&#xff0c;“请键入以选择内核”&#xff1b; 在扩展里找到jupyter更新一下 之前左边的图标是灰色的&#xff0c;后来我下下载了新的版本&#…...

新能源汽车展厅用哪些种类的显示屏比较好?

现在有越来越多的新能源汽车展厅开到了商场、购物中心当中。在新能源汽车展厅中&#xff0c;显示屏已经成为不可或缺的设备设施&#xff0c;可以用来展现产品介绍、优惠信息、文化宣传等。那么新能源汽车展厅的显示大屏用什么屏比较好呢&#xff1f; LED大屏幕&#xff1a;LED显…...

proxmox pve /dev/mapper/pve-root扩容

vgs3 pvs4 vgs5 lvs6 lvremove /dev/pve/data8 lvresize -l 100%FREE /dev/pve/root9 resize2fs /dev/mapper/pve-root 10 history...

【ECS游戏架构】逻辑帧驱动带来的性能和即时性问题分析

1024水一篇~ 个人拙见&#xff0c;如有错误希望大佬拔刀纠正。 根据守望先锋在GDC会议上对ECS架构的描述&#xff0c;所有的系统(system)都是由逻辑帧驱动的&#xff1a;每帧遍历所有的system&#xff0c;并调用system的update()更新游戏世界的状态。 在实际应用中这可能会存…...

数据库监控:关键指标和注意事项

【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 听到模糊的说法“我们的数据库有问题”对于任何数据库管理员或管理员来说都是一场噩梦。有时是真的&#xff0c;有时不是&#xff0c;到底问题出在哪里呢&#xff1f;真…...

高防回源ip被源站拦截怎么办

​  在进行网站运营过程中&#xff0c;我们经常会遇到DDoS攻击等网络安全威胁。为了保护网站的正常运行&#xff0c;很多企业选择使用高防服务来应对这些攻击。有时候我们可能会遇到一个问题&#xff0c;就是高防回源IP被源站拦截的情况。 那么&#xff0c;当我们发现高防回源…...

关于集群和分布式部署

EJB的RPC是同步调用可实现分布式计算&#xff0c;是SessionBean和EntityBean用的&#xff0c;而JMS是异步调用。RMI&#xff0c;和webservice也可以实现分布式计算。 举例说明&#xff0c;假设我们的系统有三个EJB组件&#xff1a;人事、财务、销售&#xff0c;都是开放远程接口…...

XIlinx提供的DDR3 IP与 UG586

DDR系统需要关注的三样东西&#xff1a;控制器、PHY、SDRAM颗粒&#xff0c;但这是实现一个DDR3 IP所需要的&#xff0c;如果只希望调用IP的话&#xff0c;则只需要调用IP即可&#xff0c;目前时间紧急&#xff0c;我先学一学如何使用IP&#xff0c;解决卡脖子的问题&#xff0…...

C++数据结构X篇_19_排序基本概念及冒泡排序(重点是核心代码)

文章目录 1. 排序基本概念2. 冒泡排序2.1 核心代码2.2 冒泡排序代码2.3 查看冒泡排序的时间消耗2.4 冒泡排序改进版减小时间消耗 1. 排序基本概念 现实生活中排序很重要&#xff0c;例如:淘宝按条件搜索的结果展示等。 概念 排序是计算机内经常进行的一种操作&#xff0c;其目…...

LeetCode LCR 179. 查找总价格为目标值的两个商品

和为 s 的两个数字 题目链接 LCR 179. 查找总价格为目标值的两个商品 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况&#xff0c;返回任一结果即可。 示例 1&#xff1a; 输入&#xff1a;price [3, 9, 12, …...

上架用的SDK三方应用隐私

SDK名称&#xff1a;华为推送 使用目的&#xff1a;用于向华为手机用户推送消息 使用场景&#xff1a;用户账号相关促销活动、消息提醒更新时 信息收集类型&#xff1a;设备相关信息&#xff08;Android_ID&#xff09;使用的敏感权限&#xff1a;不涉及 使用的敏感权限&am…...

从REST到GraphQL:升级你的Apollo体验

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…...

Jupyter使用技巧-环境篇

不同于其他IDE&#xff0c;有时会出现找不到文件路径&#xff0c;通常是因为当前工作目录&#xff08;working directory&#xff09;不同所导致的。Jupyter Notebook 会在启动时选择一个初始的工作目录&#xff0c;而这个目录可能与你运行 .py 文件时所在的目录不同。 import…...

软件项目管理【UML-组件图】

目录 一、组件图概念 二、组件图包含的元素 1.组件&#xff08;Component&#xff09;->构件 2.接口&#xff08;Interface&#xff09; 3.外部接口——端口 4.连接器&#xff08;Connector&#xff09;——连接件 4.关系 5.组件图表示方法 三、例子 一、组件图概念…...

npm版本错误——npm ERR! code ERESOLVE 解决方法

起因 项目中echart版本过低&#xff0c;导致某些图表不能正确显示&#xff0c;所以大手一挥&#xff0c;将echart版本从4升级到了5&#xff0c; 再去运行项目的时候 就发现项目报错了 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! …...

基于卷积神经网络的乳腺癌分类 深度学习 医学图像 计算机竞赛

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…...

颠覆式内容访问:Bypass Paywalls Clean的智能突破与无界阅读方案

颠覆式内容访问&#xff1a;Bypass Paywalls Clean的智能突破与无界阅读方案 在信息爆炸的数字时代&#xff0c;优质内容的获取却日益受到付费墙的限制。学术研究人员需要追踪最新文献&#xff0c;媒体从业者需要监控多源信息&#xff0c;普通读者渴望深度阅读——但复杂的订阅…...

Claude读论文系列(七)

SkillSieve 精读笔记 论文标题&#xff1a; SkillSieve: A Hierarchical Triage Framework for Detecting Malicious AI Agent Skills arXiv&#xff1a; 2604.06550 | 2026-04-09 作者&#xff1a; Yinghan Hou&#xff08;Imperial College London&#xff09; Zongyou Yang…...

墨语灵犀保姆级教程:Windows/Mac/Linux三端镜像部署与使用详解

墨语灵犀保姆级教程&#xff1a;Windows/Mac/Linux三端镜像部署与使用详解 1. 开篇引言&#xff1a;当古典美学遇见AI翻译 你是否曾经遇到过这样的场景&#xff1a;需要阅读外文文献&#xff0c;但机器翻译的结果生硬冰冷&#xff0c;完全失去了原文的韵味&#xff1f;或者需…...

从“人海战术”到“算法军团”:TVA引发的劳动力革命(4)

——岗位重构&#xff1a;TVA时代&#xff0c;制造业劳动力的岗位迭代与技能升级TVA“算法军团”的普及&#xff0c;不仅替代了传统的体力型、重复型劳动力&#xff0c;更引发了制造业岗位体系的颠覆性重构——大量传统岗位被淘汰&#xff0c;一批全新岗位应运而生&#xff0c;…...

3步快速部署通义千问1.8B对话模型:无需复杂配置

3步快速部署通义千问1.8B对话模型&#xff1a;无需复杂配置 1. 为什么选择通义千问1.8B对话模型 通义千问1.5-1.8B-Chat-GPTQ-Int4是阿里云推出的轻量级对话模型&#xff0c;特别适合资源有限的部署场景。这个版本经过GPTQ-Int4量化后&#xff0c;显存需求大幅降低到仅4GB左右…...

OpenClaw+Qwen3.5-9B组合优势:3个不可替代的使用场景

OpenClawQwen3.5-9B组合优势&#xff1a;3个不可替代的使用场景 1. 为什么选择OpenClawQwen3.5-9B组合 去年夏天&#xff0c;当我第一次尝试用Python脚本自动化处理医疗研究数据时&#xff0c;遇到了一个尴尬的问题&#xff1a;要么忍受公有云API的数据隐私风险&#xff0c;要…...

OpenClaw任务监控:Qwen3-14b_int4_awq模型执行日志分析

OpenClaw任务监控&#xff1a;Qwen3-14b_int4_awq模型执行日志分析 1. 为什么需要关注OpenClaw任务日志 上周我在用OpenClaw自动处理一批技术文档时&#xff0c;遇到了一个奇怪的现象&#xff1a;任务明明显示"已完成"&#xff0c;但输出的文件内容却是空的。这个问…...

Vibe Coding 程序员何去何从?最大的价值是质疑能力

当 AI 成为强力执行者&#xff0c;细节做得好不好、快不快&#xff0c;都不再重要。模型会越来越智能、越来越快。但真正决定你能用好 AI 还是被 AI 牵着走的&#xff0c;是你的思考能力。 专业能力的本质是质疑能力 很多人以为用好 AI 的关键是写好提示词&#xff08;Prompt&…...

Linux相关概念和易错知识点(52)(基于System V的信号量和消息队列)

目录1、System V信号量&#xff08;1&#xff09;信号量的本质与核心原理&#xff08;2&#xff09;PV原语&#xff08;均为原子操作&#xff09;a. P原语&#xff08;申请资源&#xff09;b. V原语&#xff08;归还资源&#xff09;&#xff08;3&#xff09;System V信号量接…...

加州大学洛杉矶分校、腾讯混元等推出Unify-Agent

这项由加州大学洛杉矶分校、腾讯混元、香港中文大学和香港科技大学联合研究团队发表于2026年3月的研究&#xff08;arXiv:2603.29620v1&#xff09;&#xff0c;彻底改变了我们对AI图像生成的认知。想象一下&#xff0c;如果你请AI画一个不太知名的动漫角色或者某个地方的特色小…...