Go Ebiten小游戏开发:俄罗斯方块
在这篇文章中,我们将一起开发一个简单的俄罗斯方块游戏,使用Go语言和Ebiten游戏库。Ebiten是一个轻量级的游戏库,适合快速开发2D游戏。我们将逐步构建游戏的基本功能,包括游戏逻辑、图形绘制和用户输入处理。
项目结构
我们的项目将包含以下主要部分:
- 游戏状态管理
- 方块生成与移动
- 碰撞检测
- 行消除与计分
- 游戏界面绘制
游戏状态管理
首先,我们定义一个 Game
结构体来管理游戏的状态。它包含游戏板、当前方块、下一个方块、分数、等级等信息。
type Game struct {board [][]intcurrentPiece *PiecenextPiece *Piece // 下一个方块gameOver booldropTimer intscore int // 得分level int // 当前等级lines int // 已消除的行数paused bool // 暂停状态
}
我们还需要定义一个 Piece
结构体来表示俄罗斯方块的形状和位置。
type Piece struct {shape [][]intx, y intcolor int
}
初始化游戏
在 NewGame
函数中,我们初始化游戏状态,包括创建游戏板和生成初始方块。
func NewGame() *Game {game := &Game{board: make([][]int, boardHeight),dropTimer: 0,level: 1,score: 0,lines: 0,}for i := range game.board {game.board[i] = make([]int, boardWidth)}game.nextPiece = game.generateNewPiece()game.spawnNewPiece()return game
}
游戏逻辑
在 Update
方法中,我们处理游戏逻辑,包括用户输入、方块移动和下落。
func (g *Game) Update() error {// 处理键盘输入if inpututil.IsKeyJustPressed(ebiten.KeyLeft) {g.moveLeft()}if inpututil.IsKeyJustPressed(ebiten.KeyRight) {g.moveRight()}if ebiten.IsKeyPressed(ebiten.KeyDown) {g.moveDown()}if inpututil.IsKeyJustPressed(ebiten.KeyUp) {g.rotate()}// 控制方块下落速度g.dropTimer++if g.dropTimer >= dropSpeed {g.dropTimer = 0g.moveDown()}return nil
}
碰撞检测
我们需要检查方块是否可以移动或旋转,这通过 isValidPosition
方法实现。
func (g *Game) isValidPosition() bool {for y := 0; y < len(g.currentPiece.shape); y++ {for x := 0; x < len(g.currentPiece.shape[y]); x++ {if g.currentPiece.shape[y][x] != 0 {newX := g.currentPiece.x + xnewY := g.currentPiece.y + yif newX < 0 || newX >= boardWidth || newY < 0 || newY >= boardHeight {return false}if g.board[newY][newX] != 0 {return false}}}}return true
}
行消除与计分
当方块锁定到游戏板时,我们需要检查是否有完整的行,并进行消除和计分。
func (g *Game) clearLines() {linesCleared := 0for y := boardHeight - 1; y >= 0; y-- {isFull := truefor x := 0; x < boardWidth; x++ {if g.board[y][x] == 0 {isFull = falsebreak}}if isFull {for moveY := y; moveY > 0; moveY-- {copy(g.board[moveY], g.board[moveY-1])}for x := 0; x < boardWidth; x++ {g.board[0][x] = 0}linesCleared++y++}}if linesCleared > 0 {g.lines += linesClearedg.score += []int{100, 300, 500, 800}[linesCleared-1] * g.levelg.level = g.lines/10 + 1}
}
绘制游戏界面
最后,我们在 Draw
方法中绘制游戏界面,包括游戏板、当前方块、下一个方块和游戏信息。
func (g *Game) Draw(screen *ebiten.Image) {// 绘制游戏板for y := 0; y < boardHeight; y++ {for x := 0; x < boardWidth; x++ {if g.board[y][x] != 0 {drawBlock(screen, x, y, g.board[y][x])}}}// 绘制当前方块if g.currentPiece != nil {for y := 0; y < len(g.currentPiece.shape); y++ {for x := 0; x < len(g.currentPiece.shape[y]); x++ {if g.currentPiece.shape[y][x] != 0 {drawBlock(screen, g.currentPiece.x+x, g.currentPiece.y+y, g.currentPiece.color)}}}}// 绘制下一个方块预览if g.nextPiece != nil {for y := 0; y < len(g.nextPiece.shape); y++ {for x := 0; x < len(g.nextPiece.shape[y]); x++ {if g.nextPiece.shape[y][x] != 0 {drawBlock(screen, boardWidth+2+x, 4+y, g.nextPiece.color)}}}}// 绘制游戏信息ebitenutil.DebugPrint(screen, fmt.Sprintf("\nScore: %d\nLevel: %d\nLines: %d", g.score, g.level, g.lines))
}
结论
通过以上步骤,我们已经实现了一个基本的俄罗斯方块游戏。你可以在此基础上添加更多功能,比如音效、菜单、不同的方块形状等。希望这篇文章能帮助你入门Go语言游戏开发,并激发你创造更复杂的游戏项目!
完整代码
main.go
package mainimport ("fmt""image/color""log""math/rand""github.com/hajimehoshi/ebiten/v2""github.com/hajimehoshi/ebiten/v2/ebitenutil""github.com/hajimehoshi/ebiten/v2/inpututil""github.com/hajimehoshi/ebiten/v2/vector"
)const (screenWidth = 320screenHeight = 640blockSize = 32boardWidth = 10boardHeight = 20
)// Game 表示游戏状态
type Game struct {board [][]intcurrentPiece *PiecenextPiece *Piece // 下一个方块gameOver booldropTimer intscore int // 得分level int // 当前等级lines int // 已消除的行数paused bool // 暂停状态// 添加动画相关字段clearingLines []int // 正在消除的行clearAnimation int // 动画计时器isClearing bool // 是否正在播放消除动画
}// Piece 表示俄罗斯方块的一个方块
type Piece struct {shape [][]intx, y intcolor int
}// NewGame 创建新游戏实例
func NewGame() *Game {game := &Game{board: make([][]int, boardHeight),dropTimer: 0,level: 1,score: 0,lines: 0,}// 初始化游戏板for i := range game.board {game.board[i] = make([]int, boardWidth)}// 创建初始方块和下一个方块game.nextPiece = game.generateNewPiece()game.spawnNewPiece()return game
}// Update 处理游戏逻辑
func (g *Game) Update() error {// 重启游戏if g.gameOver && inpututil.IsKeyJustPressed(ebiten.KeySpace) {*g = *NewGame()return nil}// 暂停/继续if inpututil.IsKeyJustPressed(ebiten.KeyP) {g.paused = !g.pausedreturn nil}if g.gameOver || g.paused {return nil}// 更新消除动画if g.isClearing {g.updateClearAnimation()return nil}// 处理键盘输入if inpututil.IsKeyJustPressed(ebiten.KeyLeft) {g.moveLeft()}if inpututil.IsKeyJustPressed(ebiten.KeyRight) {g.moveRight()}if ebiten.IsKeyPressed(ebiten.KeyDown) {g.moveDown()}if inpututil.IsKeyJustPressed(ebiten.KeyUp) {g.rotate()}// 根据等级调整下落速度g.dropTimer++dropSpeed := 60 - (g.level-1)*5 // 每提升一级,加快5帧if dropSpeed < 20 { // 最快速度限制dropSpeed = 20}if g.dropTimer >= dropSpeed {g.dropTimer = 0g.moveDown()}return nil
}// Draw 绘制游戏画面
func (g *Game) Draw(screen *ebiten.Image) {// 绘制游戏板for y := 0; y < boardHeight; y++ {for x := 0; x < boardWidth; x++ {if g.board[y][x] != 0 {// 检查是否是正在消除的行isClearing := falsefor _, clearY := range g.clearingLines {if y == clearY {isClearing = truebreak}}if isClearing {// 闪烁效果if (g.clearAnimation/3)%2 == 0 {// 绘制发光效果drawGlowingBlock(screen, x, y, g.board[y][x])}} else {drawBlock(screen, x, y, g.board[y][x])}}}}// 绘制当前方块if g.currentPiece != nil {for y := 0; y < len(g.currentPiece.shape); y++ {for x := 0; x < len(g.currentPiece.shape[y]); x++ {if g.currentPiece.shape[y][x] != 0 {drawBlock(screen,g.currentPiece.x+x,g.currentPiece.y+y,g.currentPiece.color)}}}}// 绘制下一个方块预览if g.nextPiece != nil {for y := 0; y < len(g.nextPiece.shape); y++ {for x := 0; x < len(g.nextPiece.shape[y]); x++ {if g.nextPiece.shape[y][x] != 0 {drawBlock(screen,boardWidth+2+x,4+y,g.nextPiece.color)}}}}// 绘制游戏信息ebitenutil.DebugPrint(screen, fmt.Sprintf("\nScore: %d\nLevel: %d\nLines: %d",g.score, g.level, g.lines))// 绘制游戏状态if g.gameOver {ebitenutil.DebugPrint(screen,"\n\n\n\nGame Over!\nPress SPACE to restart")} else if g.paused {ebitenutil.DebugPrint(screen,"\n\n\n\nPAUSED\nPress P to continue")}
}// drawBlock 绘制单个方块
func drawBlock(screen *ebiten.Image, x, y, colorIndex int) {vector.DrawFilledRect(screen,float32(x*blockSize),float32(y*blockSize),float32(blockSize-1),float32(blockSize-1),color.RGBA{R: uint8((colors[colorIndex] >> 24) & 0xFF),G: uint8((colors[colorIndex] >> 16) & 0xFF),B: uint8((colors[colorIndex] >> 8) & 0xFF),A: uint8(colors[colorIndex] & 0xFF),},false)
}// drawGlowingBlock 绘制发光的方块
func drawGlowingBlock(screen *ebiten.Image, x, y, colorIndex int) {vector.DrawFilledRect(screen,float32(x*blockSize-2),float32(y*blockSize-2),float32(blockSize+3),float32(blockSize+3),color.RGBA{255, 255, 255, 128},false)drawBlock(screen, x, y, colorIndex)
}// moveLeft 向左移动当前方块
func (g *Game) moveLeft() {if g.currentPiece == nil {return}g.currentPiece.x--if !g.isValidPosition() {g.currentPiece.x++}
}// moveRight 向右移动当前方块
func (g *Game) moveRight() {if g.currentPiece == nil {return}g.currentPiece.x++if !g.isValidPosition() {g.currentPiece.x--}
}// moveDown 向下移动当前方块
func (g *Game) moveDown() {if g.currentPiece == nil {return}g.currentPiece.y++if !g.isValidPosition() {g.currentPiece.y--g.lockPiece()}
}// isValidPosition 检查当前方块位置是否有效
func (g *Game) isValidPosition() bool {for y := 0; y < len(g.currentPiece.shape); y++ {for x := 0; x < len(g.currentPiece.shape[y]); x++ {if g.currentPiece.shape[y][x] != 0 {newX := g.currentPiece.x + xnewY := g.currentPiece.y + yif newX < 0 || newX >= boardWidth ||newY < 0 || newY >= boardHeight {return false}if g.board[newY][newX] != 0 {return false}}}}return true
}// Layout 实现必要的 Ebiten 接口方法
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {return screenWidth, screenHeight
}// rotate 旋转当前方块
func (g *Game) rotate() {if g.currentPiece == nil {return}// 创建新的旋转后的形状oldShape := g.currentPiece.shapeheight := len(oldShape)width := len(oldShape[0])newShape := make([][]int, width)for i := range newShape {newShape[i] = make([]int, height)}// 执行90度旋转for y := 0; y < height; y++ {for x := 0; x < width; x++ {newShape[x][height-1-y] = oldShape[y][x]}}// 保存原来的形状,以便在新位置无效时恢复originalShape := g.currentPiece.shapeg.currentPiece.shape = newShape// 如果新位置无效,恢复原来的形状if !g.isValidPosition() {g.currentPiece.shape = originalShape}
}// lockPiece 将当前方块锁定到游戏板上
func (g *Game) lockPiece() {if g.currentPiece == nil {return}// 将方块添加到游戏板for y := 0; y < len(g.currentPiece.shape); y++ {for x := 0; x < len(g.currentPiece.shape[y]); x++ {if g.currentPiece.shape[y][x] != 0 {boardY := g.currentPiece.y + yboardX := g.currentPiece.x + xg.board[boardY][boardX] = g.currentPiece.color}}}// 检查并清除完整的行g.clearLines()// 生成新的方块g.spawnNewPiece()// 检查游戏是否结束if !g.isValidPosition() {g.gameOver = true}
}// clearLines 检查完整的行
func (g *Game) clearLines() {if g.isClearing {return}// 检查完整的行g.clearingLines = nilfor y := boardHeight - 1; y >= 0; y-- {isFull := truefor x := 0; x < boardWidth; x++ {if g.board[y][x] == 0 {isFull = falsebreak}}if isFull {g.clearingLines = append(g.clearingLines, y)}}// 如果有要消除的行,开始动画if len(g.clearingLines) > 0 {g.isClearing = trueg.clearAnimation = 0}
}// updateClearAnimation 更新消除动画
func (g *Game) updateClearAnimation() {if !g.isClearing {return}g.clearAnimation++// 动画结束后执行实际的消除if g.clearAnimation >= 30 { // 0.5秒动画(30帧)// 执行实际的消除for _, y := range g.clearingLines {// 从当前行开始,将每一行都复制为上一行的内容for moveY := y; moveY > 0; moveY-- {copy(g.board[moveY], g.board[moveY-1])}// 清空最上面的行for x := 0; x < boardWidth; x++ {g.board[0][x] = 0}}// 更新分数和等级linesCleared := len(g.clearingLines)g.lines += linesClearedg.score += []int{100, 300, 500, 800}[linesCleared-1] * g.levelg.level = g.lines/10 + 1// 重置动画状态g.isClearing = falseg.clearingLines = nil}
}// generateNewPiece 生成一个新的随机方块
func (g *Game) generateNewPiece() *Piece {pieceIndex := rand.Intn(len(tetrominoes))return &Piece{shape: tetrominoes[pieceIndex],x: boardWidth/2 - len(tetrominoes[pieceIndex][0])/2,y: 0,color: pieceIndex + 1,}
}// spawnNewPiece 生成新的方块
func (g *Game) spawnNewPiece() {g.currentPiece = g.nextPieceg.nextPiece = g.generateNewPiece()
}func main() {game := NewGame()ebiten.SetWindowSize(screenWidth, screenHeight)ebiten.SetWindowTitle("俄罗斯方块")if err := ebiten.RunGame(game); err != nil {log.Fatal(err)}
}
piece.go
package mainimport ("math/rand""time"
)// 在init函数中初始化随机数种子
func init() {rand.Seed(time.Now().UnixNano())
}// 定义所有可能的方块形状
var tetrominoes = [][][]int{{ // I{1, 1, 1, 1},},{ // O{1, 1},{1, 1},},{ // T{0, 1, 0},{1, 1, 1},},{ // L{1, 0, 0},{1, 1, 1},},{ // J{0, 0, 1},{1, 1, 1},},{ // S{0, 1, 1},{1, 1, 0},},{ // Z{1, 1, 0},{0, 1, 1},},
}// 方块颜色定义
var colors = []int{1: 0xFF0000FF, // 红色2: 0x00FF00FF, // 绿色3: 0x0000FFFF, // 蓝色4: 0xFFFF00FF, // 黄色5: 0xFF00FFFF, // 紫色6: 0x00FFFFFF, // 青色7: 0xFFA500FF, // 橙色
}
相关文章:
Go Ebiten小游戏开发:俄罗斯方块
在这篇文章中,我们将一起开发一个简单的俄罗斯方块游戏,使用Go语言和Ebiten游戏库。Ebiten是一个轻量级的游戏库,适合快速开发2D游戏。我们将逐步构建游戏的基本功能,包括游戏逻辑、图形绘制和用户输入处理。 项目结构 我们的项…...
Github 2025-03-12 C开源项目日报Top5
根据Github Trendings的统计,今日(2025-03-12统计)共有5个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目5C++项目1Lean的LEDE源码:为国产龙芯LOONGSON SoC loongarch64/飞腾Phytium腾锐2000系列架构添加支持 创建周期:2338 天开发语言:C协议类…...
【机器学习-基础知识】统计和贝叶斯推断
1. 概率论基本概念回顾 1. 概率分布 定义: 概率分布(Probability Distribution)指的是随机变量所有可能取值及其对应概率的集合。它描述了一个随机变量可能取的所有值以及每个值被取到的概率。 对于离散型随机变量,使用概率质量函数来描述。对于连续型随机变量,使用概率…...
Unity3D 着色器优化(Shader Optimization)
前言 Unity3D 着色器(Shader)优化是提升渲染性能的关键环节,尤其是在移动设备或复杂场景中。以下是系统的优化策略和实践建议: 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经…...
基于SpringBoot的“体育购物商城”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“体育购物商城”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体模块设计 前台用户登录界面 系统首页界面…...
数据库约束
数据库约束 1. NULL约束2. UNIQUE:唯一约束3. DEFAULT:默认值约束4. PRIMARY KEY:主键约束5. FOREIGN KEY:外键约束6. CHECK约束 数据库约束是关系型数据库的一个重要功能,主要作用是保证数据的正确性,也就…...
【经典算法】Leetcode-零钱兑换问题
一、题目 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的…...
Go 语言使用Protobuf 进行序列化详解
文章目录 Go 语言使用Protobuf 进行序列化详解1. Protobuf是什么?2. 安装Protobuf 及 Go 依赖3. 编写.proto 文件4. 实现序列化和反序列化 Go 语言使用Protobuf 进行序列化详解 1. Protobuf是什么? 以下是 Protobuf 官方中文文档的概述: Protobuf(Protocol Buffers) 是一种…...
Windows控制台函数:标准输入输出流交互函数GetStdHandle()
目录 什么是 GetStdHandle? 它长什么样? 怎么用它? 它跟 std::cout 有什么不一样? GetStdHandle 是一个 Windows API 函数,用于获取标准输入、标准输出或标准错误设备的句柄。它定义在 Windows 的核心头文件 <…...
自然语言处理初学者指南
文章目录 一、说明二、自然语言处理发展史2.1 最早的自然语言处理简介2.2 历史2.3 NLP 的早期工作 三、NLP的现代方法3.1 单词编码3.2 循环神经网络3.3 强化学习3.4 深度学习 四、更进一步的方法 一、说明 对于初学者来说,自然语言处理的发展历史非常有必要了解&am…...
Kubernetes教程(七)了解集群、标签、Pod和Deployment
了解集群、标签、Pod和Deployment 一、K8s资源对象二、K8s集群1. Master2. Node 三、Namespace(命名空间)四、Label(标签)五、Pod1. 共享网络命名空间2. 共享数据 六、工作负载1. 设置副本数2. 应用升级 结语 Kubernetes的知识真的…...
【BUG分析】微服务无法读取Nacos中的共享配置
项目场景 基于Spring Cloud微服务的商城系统。 使用Nacos进行统一配置管理,在bootstrap.xml中读取配置参数。 问题描述 购物车微服务可以读取Nacos中的共享mybatis配置,商品管理微服务却读不到,启动报错提示无法配置数据库源: …...
SpringMVC (一)基础
目录 SpringMVC 一 简单使用 1 新建模块选择指定参数 2 创建实现类 3 将项目启动 4 运行结果:在浏览器当中响应执行 二 RequestMapping 三 请求限定 SpringMVC SpringMVC是Spring的web模块,用来开发Web应用,SpringMVC应用最终作为B/…...
【ES6】ES6中的类
基础定义和使用 class Animal {constructor(name, species, age) {this.name namethis.species speciesthis.age age} }let dog new Animal("Spot", "Dog", 4)私有变量 变量名前带#即可。 Getter 和Setter方法 继承 // 父类 class Point{construc…...
兴达易控Profinet 转 ModbusTCP跨网段通信模块
Profinet 转 ModbusTCP/跨网段通信模块 Profinet转ModbusTCP/跨网段通信模块,作为现代工业自动化系统中不可或缺的重要组件,正日益受到广泛关注和应用。 这种模块的核心功能是将Profinet网络协议转换为Modbus TCP协议,实现不同网络之间的无缝…...
linux 的免密切换用户PAM配置
/etc/pam.d/su是Linux系统中与用户切换(su命令)相关的PAM(Pluggable Authentication Modules,可插拔认证模块)配置文件。以下是对它的详细介绍: 简介 作用 PAM是一种用于管理系统认证的机制,…...
使用 Python pandas操作 Excel 文件
使用 Python pandas 操作 Excel 文件 flyfish pandas 是 Python 中一个强大的数据处理和分析库,它提供了丰富的数据结构(如 Series 和 DataFrame)和数据操作方法,能够方便地处理各种数据格式,包括 Excel 文件。 安装…...
UE5.5 Niagara 发射器粒子更新模块
Particle State (粒子状态)模块 Particle State 主要用于控制粒子的生存状态,包括死亡、消失、响应事件等。 Particle State Kill Particles When Lifetime Has Elapsed 当粒子的生命周期结束时,销毁这些粒子。 Lifetime &…...
状态模式的C++实现示例
核心思想 状态模式(State Pattern) 是一种行为设计模式,允许对象在其内部状态改变时改变其行为。它将状态相关的逻辑分散到不同的状态类中,避免了使用大量的条件语句来处理不同状态下的行为。 状态抽象化:将对象的状…...
ThinkPHP8.0+MySQL8.0搭建简单实用电子证书查询系统
客户花了100元买了一个系统,开始不能导入,到处找人帮忙解决。给解决能导入了,不能修改,满足不了用户的需求。用户一狠心,花200块钱,叫我给他定制了一个电子证书查询系统。还免费给部署到服务器。惭愧惭愧……...
STM32全系大阅兵(2)
接前一篇文章:STM32全系大阅兵(1) 本文内容参考: STM32家族系列的区别_stm32各个系列区别-CSDN博客 STM32--STM32 微控制器详解-CSDN博客...
upload-labs通关攻略 【Pass-01~Pass-19】
注意:GitHub中upload-labs有多个版本:19关、21关、23关。版本不同,关卡的顺序也很可能不同。此次例子是21关。 项目地址:https://github.com/c0ny1/upload-labs 一、Pass-01 【js前端检测的绕过】 1. 打开Pass-01 访问:ip/uploa…...
HCIP复习拓扑练习(修改版)
拓扑: 实际: 需求: 需求分析 1.这意味着学校内部网络能够正常解析域名并进行互联网访问。 2. PC1和PC2处于同一个内网192.168.1.0/24,其中PC1有权限访问外部网段3.3.3.0/24,而PC2没有。这涉及ACL(访问控制…...
Zabbix 7.2 + Grafana 中文全自动安装ISO镜像
简介 基于Zabbix 官方的Alma Linux 8 作为基础镜像。 镜像源都改为国内大学镜像站,自动联网安装ZabbixGrafana。 安装中文字体、Zabbix和Grafana也配置默认中文。 Zabbix 也指定中文字体,绘图无乱码。 配置时区为东八区,Zabbix配置We…...
使用 Python 将 PDF 转换为文本:打造一个简单高效的提取工具
在数字化时代,PDF 文件是我们日常生活中常见的文档格式。无论是学术论文、工作报告还是电子书,PDF 的广泛使用让提取其中文字内容成为一个常见需求。手动复制粘贴显然效率低下,而借助 Python,我们可以轻松实现自动化提取。本文将介…...
scoop退回软件版本的方法
title: scoop退回软件版本的方法 date: 2025-3-11 23:53:00 tags: 其他 前言 在软件更新后,如果出现了很影响使用体验的问题,那么可以把软件先退回以前的版本进行使用, 但是scoop本身并没有提供直接让软件回退版本的功能,因此…...
网络爬虫-2:正则化
1.正则化 一.正则化 1.转义字符 转义字符含义\s空白字符(空格、制表符等)\d数字字符(0-9)\w字母、数字或下划线.除换行符外的任意字符\n换行符\t制表符 import re result re.findall(r\s, Hello World\nPython) print(result)…...
emacs使用mongosh的方便工具发布
github项目地址: GitHub - csfreebird/emacs_mongosh: 在emacs中使用mongosh快速登录mongodb数据库 * 用途 在emacs中使用mongosh快速登录mongodb数据库, 操作方法: M-x mongosh, 输入数据库名称,然后就可以自动登录,前提是你已经配置好了…...
【Spring】详细剖析Spring程序
文章目录 一、Spring概述1. Spring简介1.1 OCP开闭原则1.2 依赖倒置原则DIP1.3 控制反转IoC 2. Spring8大模块 二、Spring的入门程序1. Spring官网2. 第一个Spring程序2.1 创建工程2.2 配置 pom.xml:2.3 定义bean:User . java2.4 配置文件 spring.xml2.5…...
《MySQL数据库从零搭建到高效管理|库的基本操作》
目录 一、数据库的操作 1.1 展示数据库 1.2 创建数据库 1.3 使用数据库 1.4 查看当前数据库 1.5 删除数据库 1.6 小结 二、常用数据类型 2.1 数值类型 2.2 字符串类型 2.3 日期类型 一、数据库的操作 打开MySQL命令行客户端,安装完MySQL后会有两个客户端…...
docker部署jenkins,安装使用一条龙教程
Jenkins k8s 实现CI/CD 一、简介 1. JenKins是什么? Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成。 2. 什么是CI / CD…...
图像识别技术与应用-YOLO
1 YOLO-V1 YOLO-V1它是经典的one-stage方法,You Only Look Once,名字就已经说明了一切!把检测问题转化成回归问题,一个CNN就搞定了!也可以对视频进行实时检测,应用领域非常广! YOLO-V1诞生与2…...
【网络通信安全】子专栏链接及简介
目录 操作系统安全:筑牢网络安全根基 网络协议安全:守护数据传输通道 Web 站点安全开发:打造安全的网络交互平台 在数字化浪潮席卷的当下,网络通信已深度融入生活与工作的方方面面,从日常的线上购物、社交互动…...
Oracle比较好的几本书籍
1.《Oracle专家高级编程》 2.《Oracle高效设计》 3.《Oracle9i&10g&11g编程艺术深入数据库体系结构》 4.《让Oracle跑的更快》(1/2) ....... n.《Oracle官方文档的阅读》下面包括这几个部分,可以跟进研读一下: (1)《…...
忘记dedecms后台超级管理员账号和密码的解决方案
解决方案: 方案一、数据库修改: 1、前提是您能登录到数据库后台,登录MySQL数据库管理工具(如phpMyAdmin) 2、打开数据库中的 dede_admin 表,找到管理员记录,将 pwd 字段的值改成 f297a57a5a7…...
处理动态分页:自动翻页与增量数据抓取策略-数据议事厅
一、案例场景 Lily(挥舞着数据报表):“用户反馈我们的股票舆情分析总是缺失最新跟帖!这些动态分页像狡猾的狐狸,每次抓取都漏掉关键数据!” 小王(调试着爬虫代码):“传…...
微服务新手入门
一、微服务概念 微服务是一种软件架构风格,ta是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。 微服务 - 服务拆分 - 远程调用 - 服务治理 - 请求路由 - 身份认证 - 配置管理 - 服务保护 - 分布式事务 - 异步通信 - 消息可靠性 - 延迟消…...
antd浏览器引入的问题
1,在使用ant design vue的4.1.2版本通过浏览器引入的方式遇到的问题,遇到的问题(不确定其他版本有没有问题),通过在页面使用下面的代码 <a-modal v-model:open"apiOpen" title"修改秘钥" ok&q…...
STM32-Unix时间戳
一:什么是时间戳 Unix时间戳(Unix Timestamp)是一个计数器数值,这个数值表示的是一个从1970年1月1日0时0分0秒开始到现在所经过的秒数,不考虑闰秒。 时间戳存储在一个秒计数器里,秒计数器为32位/64位的整…...
【性能测试】Jmeter如何做一份测试报告(3)
本篇文章主要介绍Jmeter中下载插件(Jmeter Plugins) 如何使用监听器插件,线程组插件,梯度压测线程组 测试报告需要去关注的数据,怎么看测试报告图表 目录 一:插件下载 1:下载地址 2ÿ…...
游戏引擎学习第153天
仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾 目前正在进行的是一个比较大的系统调整,原本预计今天会继续深入这个改动,但实际上在昨天的开发中,我们已经完成了大部分的代码编写,并且运行之后几乎一切都能正常工作&#x…...
CentOS7下安装MongoDB
步骤 1:创建 MongoDB Yum 仓库文件 你需要创建一个 MongoDB 的 Yum 仓库配置文件,以便从官方源下载 MongoDB。打开终端并使用以下命令创建并编辑该文件: sudo vi /etc/yum.repos.d/mongodb-org-7.0.repo 在打开的文件中,输入以下…...
Elasticsearch-07-Elasticsearch Java API Client-Elasticsearch 8.0 的高阶api
文章目录 es8 API基础配置和bean注入高阶使用1:引入elasticsearchClient2:查询所有索引3:查询某个索引4:创建索引5:删除指定索引6:查询索引的映射7:创建索引指定映射8:创建文档使用HashMap作为数据存储容器使用自定义类作为数据存储容器使用外…...
【性能优化】MySQL 生产环境 SQL 性能优化实战案例
🚀 MySQL 生产环境 SQL 性能优化实战案例 🏗️ 背景介绍 最近在处理一个项目时,发现在生产环境的工作流相关接口中,某些查询的执行时间异常缓慢,尽管数据量仅为 2 万条。经过分析,发现以下 SQL 语句执行非…...
Docker容器安装软件(完整版)
文章目录 一、安装Docker1.1 docker 相关的命令1.2 配置镜像加速 二. 安装es2.1 创建网络2.2 拉取镜像2.3 创建挂载点目录2.4 部署单点es,创建es容器2.5 编写elasticsearch.yml2.6 重启es容器2.7 测试Elasticsearch是否安装成功 三. 基于Docker安装Kibana3.1 拉取镜…...
DeepSeek-进阶版部署(Linux+GPU)
前面几个小节讲解的Win和Linux部署DeepSeek的比较简单的方法,而且采用的模型也是最小的,作为测试体验使用是没问题的。如果要在生产环境使用还是需要用到GPU来实现,下面我将以有一台带上GPU显卡的Linux机器来部署DeepSeek。这里还只是先体验单…...
11. Pandas :操作Excel文件(Excel报表的案例研究)
从一个装有各种 Excel 文件的文件夹开始,这些文件需要被整合到 Excel 报表中。 它们包含了虚构的电信运营商在全美各营业厅的套餐(金、银、铜)销售情况。每个月有两个文件,子文件夹 new 中的是新用户,子文件夹 existin…...
Qt开源控件库(qt-material-widgets)的编译及使用
项目简介 qt-material-widgets是一个基于 Qt 小部件的 Material Design 规范实现。 项目地址 项目地址:qt-material-widgets 本地构建环境 Win11 家庭中文版 VS2019 Qt5.15.2 (MSVC2019) 本地构建流程 克隆后的目录结构如图: 直接使用Qt Crea…...
freeswitch(多台服务器级联)
亲测版本centos 7.9系统–》 freeswitch1.10.9本人freeswitch安装路径(根据自己的路径进入)/usr/local/freeswitch/etc/freeswitch使用场景: 使用服务器级联需要双方网络可以ping通,也就是类似局域网内,比如A服务器IP 192.168.1.100 B服务器 192.168.1.101,通过C设备注册…...
【大模型统一集成项目】让 AI 聊天更丝滑:WebSocket 实现流式对话!
🌟 在这系列文章中,我们将一起探索如何搭建一个支持大模型集成项目 NexLM 的开发过程,从 架构设计 到 代码实战,逐步搭建一个支持 多种大模型(GPT-4、DeepSeek 等) 的 一站式大模型集成与管理平台ÿ…...