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

Go Ebiten小游戏开发:井字棋

image-20250113024452832

今天我将分享如何使用 Go 语言和 Ebiten 游戏库开发一个简单的井字棋游戏。Ebiten 是一个轻量级的 2D 游戏库,非常适合用来开发小型游戏。通过这个项目,我们可以学习到如何使用 Ebiten 处理输入、渲染图形以及管理游戏状态。

项目概述

井字棋是一个经典的两人对战游戏,玩家轮流在 3x3 的棋盘上放置自己的标记(通常是“圈”和“叉”),先连成一条线的玩家获胜。我们的目标是实现一个简单的井字棋游戏,支持以下功能:

  • 玩家轮流下棋
  • 检测游戏是否结束(胜利或平局)
  • 游戏结束后的重新开始功能
  • 简单的动画效果

代码结构

我们的代码主要分为以下几个部分:

  1. 游戏状态管理:包括棋盘状态、当前玩家回合、游戏是否结束等。
  2. 输入处理:处理鼠标点击和键盘输入。
  3. 渲染逻辑:绘制棋盘、棋子和游戏结束动画。
  4. 游戏逻辑:检查胜利条件、平局条件等。

1. 游戏状态管理

我们使用一个 Game 结构体来管理游戏的状态:

type Game struct {Turn       bool      // 当前玩家回合(true: 玩家1,false: 玩家2)Board      [3][3]int // 3x3 的棋盘,0: 空,1: 玩家1,2: 玩家2IsGameOver bool      // 游戏是否结束
}

2. 输入处理

我们通过 HandleInput 函数来处理玩家的输入。玩家可以通过鼠标点击来下棋,按下 R 键重新开始游戏,按下 ESC 键退出游戏。

func (game *Game) HandleInput() {if ebiten.IsKeyPressed(ebiten.KeyEscape) {game.Exit() // 按下 ESC 键退出游戏}if !game.IsGameOver && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {game.HandleMouseClick() // 如果游戏未结束且按下鼠标左键,处理点击}if game.IsGameOver && ebiten.IsKeyPressed(ebiten.KeyR) {game.Restart() // 如果游戏结束且按下 R 键,重新开始游戏}
}

3. 渲染逻辑

我们使用 DrawBoard 函数来绘制棋盘和棋子。棋盘由两条垂直线和两条水平线组成,棋子则根据棋盘状态绘制“圈”或“叉”。

func DrawBoard(screen *ebiten.Image, game *Game) {// 绘制棋盘线条for i := 1; i <= 2; i++ {vector.DrawFilledRect(screen, float32(i)*BlockSize, 0, LineWidth, 3*BlockSize+LineWidth, WHITE, true)vector.DrawFilledRect(screen, 0, float32(i)*BlockSize, 3*BlockSize+LineWidth, LineWidth, WHITE, true)}// 绘制棋子的圈和叉for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if game.Board[i][j] == 1 {DrawCircle(screen, i, j) // 画圈} else if game.Board[i][j] == 2 {DrawCross(screen, i, j) // 画叉}}}
}

4. 游戏逻辑

我们通过 CheckGameOver 函数来检查游戏是否结束。如果棋盘已满且没有玩家获胜,则为平局;否则,检查是否有玩家连成一条线。

func (game *Game) CheckGameOver() {if IsBoardFull(game.Board) { // 检查是否平局game.IsGameOver = trueGameOverText = "It's a Draw!"} else if CheckWin(game.Board) { // 检查是否有玩家获胜game.IsGameOver = trueif game.Turn { // 当前回合是 O,说明 X 赢了GameOverText = "Player X Wins!"} else { // 当前回合是 X,说明 O 赢了GameOverText = "Player O Wins!"}}
}

完整代码

package mainimport ("image""image/color""log""math""os""github.com/hajimehoshi/ebiten/v2""github.com/hajimehoshi/ebiten/v2/vector""golang.org/x/image/font""golang.org/x/image/font/basicfont""golang.org/x/image/math/fixed"
)const (BlockSize       float32 = 200                               // 每个格子的大小WindowWidth     int     = 3*int(BlockSize) + int(LineWidth) // 窗口宽度WindowHeight    int     = 3*int(BlockSize) + int(LineWidth) // 窗口高度LineWidth       float32 = 20                                // 线条宽度LineOffsetRatio float32 = LineWidth / BlockSize / 2         // 线条偏移比例
)var (BLUE          color.Color = color.NRGBA{0, 0, 255, 255}     // 蓝色,用于画圈RED           color.Color = color.NRGBA{255, 0, 0, 255}     // 红色,用于画叉WHITE         color.Color = color.NRGBA{255, 255, 255, 255} // 白色,用于画线条GameOverText  string                                        // 游戏结束时的提示文本RestartButton bool                                          // 是否显示重新开始按钮(未使用)GameOverTimer int                                           // 游戏结束动画计时器
)type Game struct {Turn       bool      // 当前玩家回合(true: 玩家1,false: 玩家2)Board      [3][3]int // 3x3 的棋盘,0: 空,1: 玩家1,2: 玩家2IsGameOver bool      // 游戏是否结束
}// Update 是 Ebiten 的主循环函数,每一帧调用一次
func (game *Game) Update() error {game.HandleInput() // 处理输入if game.IsGameOver {GameOverTimer++ // 游戏结束时,计时器增加}return nil
}// Draw 是 Ebiten 的渲染函数,每一帧调用一次
func (game *Game) Draw(screen *ebiten.Image) {DrawBoard(screen, game) // 绘制棋盘if game.IsGameOver {DrawGameOver(screen) // 如果游戏结束,绘制结束动画}
}// Layout 设置窗口的布局
func (game *Game) Layout(outsideWidth, outsideHeight int) (int, int) {return outsideWidth, outsideHeight
}// HandleInput 处理用户输入
func (game *Game) HandleInput() {if ebiten.IsKeyPressed(ebiten.KeyEscape) {game.Exit() // 按下 ESC 键退出游戏}if !game.IsGameOver && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {game.HandleMouseClick() // 如果游戏未结束且按下鼠标左键,处理点击}if game.IsGameOver && ebiten.IsKeyPressed(ebiten.KeyR) {game.Restart() // 如果游戏结束且按下 R 键,重新开始游戏}
}// HandleMouseClick 处理鼠标点击事件
func (game *Game) HandleMouseClick() {mouseX, mouseY := ebiten.CursorPosition()                        // 获取鼠标位置x, y := mouseX/int(BlockSize), mouseY/int(BlockSize)             // 计算点击的格子坐标if x >= 0 && x < 3 && y >= 0 && y < 3 && game.Board[x][y] == 0 { // 如果点击的格子为空if game.Turn {game.Board[x][y] = 1 // 玩家1下棋} else {game.Board[x][y] = 2 // 玩家2下棋}game.Turn = !game.Turn // 切换玩家回合game.CheckGameOver()   // 检查游戏是否结束}
}// CheckGameOver 检查游戏是否结束
func (game *Game) CheckGameOver() {if IsBoardFull(game.Board) { // 检查是否平局game.IsGameOver = trueGameOverText = "It's a Draw!"} else if CheckWin(game.Board) { // 检查是否有玩家获胜game.IsGameOver = trueif game.Turn { // 当前回合是 O,说明 X 赢了GameOverText = "Player X Wins!"} else { // 当前回合是 X,说明 O 赢了GameOverText = "Player O Wins!"}}
}// Restart 重新开始游戏
func (game *Game) Restart() {game.Board = [3][3]int{} // 重置棋盘game.Turn = false        // 重置回合game.IsGameOver = false  // 重置游戏状态GameOverText = ""        // 清空结束文本GameOverTimer = 0        // 重置计时器
}// Exit 退出游戏
func (game *Game) Exit() {os.Exit(0)
}// DrawBoard 绘制棋盘
func DrawBoard(screen *ebiten.Image, game *Game) {// 绘制棋盘线条for i := 1; i <= 2; i++ {vector.DrawFilledRect(screen, float32(i)*BlockSize, 0, LineWidth, 3*BlockSize+LineWidth, WHITE, true)vector.DrawFilledRect(screen, 0, float32(i)*BlockSize, 3*BlockSize+LineWidth, LineWidth, WHITE, true)}// 绘制棋子的圈和叉for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if game.Board[i][j] == 1 {DrawCircle(screen, i, j) // 画圈} else if game.Board[i][j] == 2 {DrawCross(screen, i, j) // 画叉}}}
}// DrawCircle 绘制圈
func DrawCircle(screen *ebiten.Image, x, y int) {x0, y0 := ((1+LineOffsetRatio)*float32(x)+0.5)*BlockSize, ((1+LineOffsetRatio)*float32(y)+0.5)*BlockSizevector.StrokeCircle(screen, x0, y0, BlockSize/3, LineWidth, BLUE, true)
}// DrawCross 绘制叉
func DrawCross(screen *ebiten.Image, x, y int) {L := BlockSize / 4x1, y1 := ((1+LineOffsetRatio)*float32(x)+0.5)*BlockSize-L, ((1+LineOffsetRatio)*float32(y)+0.5)*BlockSize-Lx2, y2 := ((1+LineOffsetRatio)*float32(x)+0.5)*BlockSize+L, ((1+LineOffsetRatio)*float32(y)+0.5)*BlockSize+Lvector.StrokeLine(screen, x1, y1, x2, y2, LineWidth, RED, true)x3, y3 := ((1+LineOffsetRatio)*float32(x)+0.5)*BlockSize+L, ((1+LineOffsetRatio)*float32(y)+0.5)*BlockSize-Lx4, y4 := ((1+LineOffsetRatio)*float32(x)+0.5)*BlockSize-L, ((1+LineOffsetRatio)*float32(y)+0.5)*BlockSize+Lvector.StrokeLine(screen, x3, y3, x4, y4, LineWidth, RED, true)
}// DrawGameOver 绘制游戏结束动画
func DrawGameOver(screen *ebiten.Image) {// 背景渐变动画alpha := uint8(math.Min(float64(GameOverTimer)*2, 255))bgColor := color.NRGBA{0, 0, 0, alpha}vector.DrawFilledRect(screen, 0, 0, float32(WindowWidth), float32(WindowHeight), bgColor, true)// 绘制游戏结束文本if GameOverText != "" {textColor := color.NRGBA{255, 255, 255, 255}text := GameOverText + " Press R to Restart"DrawText(screen, text, WindowWidth/4, WindowHeight/2, textColor)}
}// DrawText 绘制文本
func DrawText(screen *ebiten.Image, text string, x, y int, clr color.Color) {f := basicfont.Face7x13textWidth := font.MeasureString(f, text).Ceil()textHeight := f.Metrics().Height.Ceil() + 100textX := x - textWidth/2textY := y - textHeight/2textImage := ebiten.NewImage(textWidth, textHeight)textImage.Fill(color.Transparent)d := &font.Drawer{Dst:  textImage,Src:  image.NewUniform(clr),Face: f,Dot:  fixed.Point26_6{X: fixed.I(20), Y: fixed.I(20)},}d.DrawString(text)op := &ebiten.DrawImageOptions{}op.GeoM.Scale(2, 2)                               // 缩放文本op.GeoM.Translate(float64(textX), float64(textY)) // 定位文本op.ColorScale.ScaleWithColor(clr)                 // 设置文本颜色screen.DrawImage(textImage, op)
}// CheckWin 检查是否有玩家获胜
func CheckWin(board [3][3]int) bool {// 检查行for i := 0; i < 3; i++ {if board[i][0] != 0 && board[i][0] == board[i][1] && board[i][0] == board[i][2] {return true}}// 检查列for i := 0; i < 3; i++ {if board[0][i] != 0 && board[0][i] == board[1][i] && board[0][i] == board[2][i] {return true}}// 检查对角线if board[0][0] != 0 && board[0][0] == board[1][1] && board[0][0] == board[2][2] {return true}if board[2][0] != 0 && board[2][0] == board[1][1] && board[2][0] == board[0][2] {return true}return false
}// IsBoardFull 检查棋盘是否已满
func IsBoardFull(board [3][3]int) bool {for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if board[i][j] == 0 {return false}}}return true
}// main 是程序入口
func main() {ebiten.SetWindowTitle("Tic-Tac-Toe")            // 设置窗口标题ebiten.SetWindowSize(WindowWidth, WindowHeight) // 设置窗口大小game := &Game{}if err := ebiten.RunGame(game); err != nil {log.Fatal(err)}
}

相关文章:

Go Ebiten小游戏开发:井字棋

今天我将分享如何使用 Go 语言和 Ebiten 游戏库开发一个简单的井字棋游戏。Ebiten 是一个轻量级的 2D 游戏库&#xff0c;非常适合用来开发小型游戏。通过这个项目&#xff0c;我们可以学习到如何使用 Ebiten 处理输入、渲染图形以及管理游戏状态。 项目概述 井字棋是一个经典…...

嵌入式系统中的 OpenCV 与 OpenGLES 协同应用

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 一、OpenCV 在嵌入式中的基石地位二、OpenGLES 为嵌入式图形渲染赋能三、二者协同的精妙之处四、面临的挑战与应对策略 在嵌入式开…...

秒懂虚拟化(二):服务器虚拟化、操作系统虚拟化、服务虚拟化全解析,通俗解读版

秒懂虚拟化&#xff08;一&#xff09;&#xff1a;从概念到网络、存储虚拟化全解析&#xff0c;通俗解读版-CSDN博客这篇文章学习了虚拟化的概念、网络虚拟化和存储虚拟化&#xff0c;本节将继续学习服务器虚拟化、操作系统虚拟化、服务虚拟化。 1、服务器虚拟化 服务器虚拟…...

Java定时任务

在 Java 中&#xff0c;定时任务通常用于在特定时间或间隔执行某个操作。Java 提供了多种方式来实现定时任务&#xff0c;包括使用 Timer 类、ScheduledExecutorService 和 Spring 框架中的定时任务功能。下面将介绍这些常见的方法。 1. 使用 Timer 类 Timer 类可以用来安排任…...

springCloud特色知识记录(基于黑马教程2024年)

目录 Nacos 简介 Nacos 的特点 Nacos 的使用步骤可以查看黑马教程文档&#xff1a;‍‌​‌​&#xfeff;⁠​⁠​​​​​&#xfeff;‬​​​​‍‌&#xfeff;‬⁠​&#xfeff;​‬​​​​‍​&#xfeff;⁠​&#xfeff;​​⁠​​‬​⁠&#xfeff;​​day03-微…...

Linux---shell脚本练习

要求&#xff1a; 1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 3、编写个shel 脚本将/usr/local 日录下…...

ClickHouse-CPU、内存参数设置

常见配置 1. CPU资源 1、clickhouse服务端的配置在config.xml文件中 config.xml文件是服务端的配置&#xff0c;在config.xml文件中指向users.xml文件&#xff0c;相关的配置信息实际是在users.xml文件中的。大部分的配置信息在users.xml文件中&#xff0c;如果在users.xml文…...

浅谈云计算02 | 云计算模式的演进

云计算计算模式的演进 一、云计算计算模式的起源追溯1.2 个人计算机与桌面计算 二、云计算计算模式的发展阶段2.1 效用计算的出现2.2 客户机/服务器模式2.3 集群计算2.4 服务计算2.5 分布式计算2.6 网格计算 三、云计算计算模式的成熟与多元化3.1 主流云计算服务模式的确立3.1.…...

设置模块一级菜单添加遥控器功能

文章目录 问题点问题分析资源和源码分析解决方案源码分析找到对应的Activitymenifest 分析SettingsHomepageActivity 分析 问题点 MTK Android12/13 系统设置一级界面&#xff0c;蓝牙遥控器无法上下滑动页面。 备注&#xff1a;自己对设置整个模块系统其实并不熟悉&#xff…...

Blazor中Syncfusion Word组件使用方法

Blazor中Syncfusion Word组件用于在Blazor应用程序中创建、编辑、查看和打印 Word&#xff08;DOC、DOCX 和 RTF&#xff09;文档。 主要功能&#xff1a; 从头开始创建文档。打开和编辑 Word&#xff08;DOC、DOCX&#xff09;、RTF 和 SFDT&#xff08;Syncfusion 文档文本…...

HTB:Driver[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用smbclient尝…...

微信小程序-Docker+Nginx环境配置业务域名验证文件

在实际开发或运维工作中&#xff0c;我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件&#xff0c;用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx&#xff0c;就需要将该验证文件正确地映射&#xff08;挂载&#xff09;到容器中&#xff0c;并…...

55_OpenResty开发入门

Nginx编程需要用到Lua语言,因此我们必须先学习Lua的基本语法。Nginx本身也是C语言开发,因此也允许基于Lua做拓展。多级缓存的实现离不开Nginx编程,而Nginx编程又离不开OpenResty。 1.OpenResty概述 OpenResty是一款基于NGINX和LuaJIT的Web平台。通过Lua扩展NGINX实现的可伸…...

Windows安装Jenkins——及修改主目录、配置简体中文、修改插件源

一、简介 Jenkinshttps://www.jenkins.io/zh/ Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。 二、Windows安装配置Jenkins2.479 2.1、J...

大数据环境搭建进度

1.使用虚拟机的系统&#xff1a;centos7.xLinux 2.资源不足&#xff0c;使用云服务器&#xff1a; 1. 3.使用远程登录进行操作 用xshell 4.任务 1.虚拟机装好 2.设置IP地址 3.可以联网 4.设置远程登录访问 5.创建module和software目录&#xff0c;修改两…...

第27章 汇编语言--- 设备驱动开发基础

汇编语言是低级编程语言的一种&#xff0c;它与特定的计算机架构紧密相关。在设备驱动开发中&#xff0c;汇编语言有时用于编写性能关键的部分或直接操作硬件&#xff0c;因为它是接近机器语言的代码&#xff0c;可以提供对硬件寄存器和指令集的直接访问。 要展开源代码详细叙…...

Apache Hop从入门到精通 第二课 Apache Hop 核心概念/术语

1、apache hop核心概念思维导图 虽然apache hop是kettle的一个分支&#xff0c;但是它的概念和kettle还是有一些区别的&#xff0c;下图是我根据官方文档梳理的appache hop的核心概念思维导图。 2、Tools&#xff08;工具&#xff09; 1&#xff09;Hop Conf Hop Conf 是一个…...

Vue2+OpenLayers使用Overlay实现点击获取当前经纬度信息(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 关键参数&#xff1a; 实现思路&#xff1a; 核心代码&#xff1a; 完整代码&#xff1a; 四、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、代码实现 覆盖物&#xff08;Overlay&#xf…...

英语互助小程序springboot+论文源码调试讲解

第2章 开发环境与技术 英语互助小程序的编码实现需要搭建一定的环境和使用相应的技术&#xff0c;接下来的内容就是对英语互助小程序用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&#xff0c;是经常变动的&#xff0c;没有…...

中等难度——python实现电子宠物和截图工具

import io # 文件处理 import nt # windows nt 库直接获取对应的磁盘空间 import time # 时间 import zlib # 加解密 import ctypes # 调用 import struct # 处理字节二进制 import base64 # 编解码 import threading # 线程 import tkinter as tk # tk from datetime…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...