数字华容道Java实战:棋盘建模、可解性检测到求解器一次搞定
简介Java项目实战数字华容道/石头迷阵游戏面向Java初学者、课程设计学生及游戏开发爱好者。该项目基于Swing构建经典滑块拼图玩法完整实现棋盘初始化、随机打乱且保证局面可解、上下左右移动判定、步数统计、胜利弹窗与重置功能并配有数字方块、背景及胜利界面等图片素材帮助读者把面向对象、二维数组、事件监听、界面布局知识应用到真实项目中。压缩包共22个文件以3个Java源文件为核心覆盖游戏入口、逻辑控制与界面绘制另含18张PNG图片素材和1个iml工程模块文件整体仅372KB轻量易学。源码目录结构清晰按com.itheima包组织业务类src/image统一存放图片可直接导入主流集成开发环境运行并二次开发。已有1018人学习下载适合作为课程设计、项目实训、蓝桥杯备赛或自学练手的优质参考便于深入理解Java游戏开发完整流程。1. 数字华容道/石头迷阵游戏为什么是Java项目实战的绝佳练手题一个4x4的滑块游戏表面看只是把15个数字按顺序排列但对Java工程师来说它是一道把数组操作、随机算法、事件监听、搜索剪枝串起来的综合题。很多人在简历上写“数字华容道游戏”面试官第一句就是你的打乱算法怎么保证有解这个问题能筛掉一半没做过深度思考的人。石头迷阵则是同一个游戏的换皮版本把数字换成石头图标规则完全一致。这个项目适合刚学完Java基础准备找项目实战的初学者也适合想在面试前用一个小而完整的代码重新梳理逻辑的工程师。下面我按自己带项目时的顺序从棋盘建模讲到求解器验证每段代码都能放进你的项目里跑通。2. 先把游戏逻辑写对棋盘建模、移动判定与可解性检测2.1 用二维数组还是一维数组两种建模方式与选择理由先决定数据模型。常见做法是用一个长度为size*size的一维数组来表示棋盘0作为空白格。为什么不用int[][]因为一维数组的下标可以直接对应UI层的组件索引做交换时只需要记录blankIndex而二维数组虽然直观却要在每一层做row/col换算多写不少代码还容易把x和y搞反。我一般会把棋盘逻辑放在一个独立类里不让任何UI代码直接操作这个数组。这个类对外提供canMove、move、isSolved、getTile几个方法内部怎么存都不影响外部调用。这样做的直接好处是控制台版、Swing版、甚至后来接Spring Boot接口都可以复用同一个模型类也方便写单元测试。如果你偏爱二维数组也可以但要写一个to1D(row, col)方法统一换算并且保证所有调用都走这个方法。我在代码审查时见过好几次行列转换错误根源都是这里不是算法本身。与其用二维数组增加心智负担不如一开始就用一维数组。2.2 把移动封装成 move(int index)边界判断与交换移动的本质是把被点击的块与空白格交换。用一个方法完成这个操作后续所有游戏模式都调用它。public class NumberPuzzle { private final int size; private final int[] tiles; private int blankIndex; public NumberPuzzle(int size) { this.size size; this.tiles new int[size * size]; for (int i 0; i tiles.length - 1; i) { tiles[i] i 1; } tiles[tiles.length - 1] 0; blankIndex tiles.length - 1; } public int getSize() { return size; } public int getTileCount() { return tiles.length; } public int getTile(int index) { return tiles[index]; } public int getBlankIndex() { return blankIndex; } public int[] getTiles() { return tiles.clone(); } public void setTiles(int[] source, int blankIndex) { System.arraycopy(source, 0, tiles, 0, tiles.length); this.blankIndex blankIndex; } public boolean canMove(int index) { if (index 0 || index tiles.length) return false; int row index / size; int col index % size; int blankRow blankIndex / size; int blankCol blankIndex % size; return Math.abs(row - blankRow) Math.abs(col - blankCol) 1; } public void move(int index) { if (!canMove(index)) { throw new IllegalArgumentException(无法移动该块不在空白格旁边); } tiles[blankIndex] tiles[index]; tiles[index] 0; blankIndex index; } public boolean isSolved() { for (int i 0; i tiles.length - 1; i) { if (tiles[i] ! i 1) return false; } return tiles[tiles.length - 1] 0; } }逻辑说明canMove用曼哈顿距离判断两个格子是否相邻而不是逐个写四个方向这样当size变化时不需要改动。move里先把空白位填入被移动的块再将被移动位置置0最后更新空白下标。setTiles用于从外部加载一个初始局面后面打乱和求解器都要用到。我们给size做成构造参数而不是写死4方便扩展3x3、5x5。参数说明setTiles里我用System.arraycopy而不是直接this.tiles tiles这样外部后续修改传入的数组不会污染棋盘内部状态。这个细节在写求解器时会避免一类很难查的bug。getTiles返回clone也是同样的防御性拷贝思路很多玄学bug都来自外部直接拿到底层数组后乱改。2.3 可解性检测为什么3x3和4x4的判定不一样如果只是把数字洗牌就开始游戏你会得到大约一半根本解不出来的死局。规则是这样的把除0外的方块按从左到右、从上到下展开成一列统计每个数右边比自己小的数个数之和称为逆序数。对奇数阶3x3可解条件是逆序数为偶数对偶数阶4x4可解条件是“逆序数 空白格所在行从底部起的行号”为偶数。public static boolean isSolvable(int[] tiles, int size) { int[] flat new int[tiles.length - 1]; int idx 0; for (int value : tiles) { if (value ! 0) flat[idx] value; } int inversions 0; for (int i 0; i flat.length; i) { for (int j i 1; j flat.length; j) { if (flat[i] flat[j]) inversions; } } if (size % 2 1) { return inversions % 2 0; } else { int blankRow findBlankRow(tiles, size); int blankRowFromBottom size - 1 - blankRow; return (inversions blankRowFromBottom) % 2 0; } } private static int findBlankRow(int[] tiles, int size) { for (int i 0; i tiles.length; i) { if (tiles[i] 0) return i / size; } return -1; }逻辑说明双重循环求逆序数在15个数时性能可以忽略。这个双重循环和冒泡排序的写法很像面试时如果被问到排序也能顺带聊两句。为什么偶数阶要额外看空白行号因为每次水平移动会改变逆序数奇偶性垂直移动会影响空白行位置两类移动对奇偶性的影响需要合并计算。这里不展开证明但你要知道结论否则面试答不上来。写完这个类后建议你顺手写几个测试用例从已解决状态反向推导出来的一步状态、两步状态分别断言可解再把两个非零块交换后断言不可解。这样后面的shuffle才不会偷偷引入死局。3. 把源代码跑起来从控制台版到Swing图形界面的改造路线3.1 拿到源代码后先看什么项目结构、入口类与构建方式无论是从源码包解压还是自己建项目第一个动作都是先看入口。常见的Java项目源码会按“模型、视图、控制”分层即使是一个小游戏也建议这样组织number-puzzle/ ├── README.md ├── src/ │ └── main/java/com/example/puzzle/ │ ├── NumberPuzzle.java # 棋盘逻辑 │ ├── PuzzleSolver.java # 求解器 │ ├── GamePanel.java # Swing画布 │ └── Main.java # 入口 └── test/ └── java/com/example/puzzle/ └── NumberPuzzleTest.java # 单元测试拿到别人的源码不要上来就找界面文件。先读NumberPuzzle.java确认规则和数据结构再去找main方法。如果是一个还没有重构的单文件版本那正好由你来拆分。用Git做源代码管理每拆出一个类提交一次出问题可以随时回退这是我在项目实战里最看重的习惯。构建方式方面最简单的就是纯JDK在src/main/java里直接javac Main.java跑。如果项目里带了pom.xml就用Maven的mvn clean package带build.gradle就用Gradle。不要一上来就依赖IDE的绿色三角形先弄清构建命令后面接数据库或者前后端分离项目才不会翻车。3.2 控制台版最小实现输入块编号循环与错误处理控制台版最大的作用是验证模型层没有逻辑错误。你可以在不启动图形界面的情况下把移动、胜利、非法输入都测一遍。import java.util.Scanner; public class ConsoleMain { public static void main(String[] args) { NumberPuzzle game new NumberPuzzle(4); Scanner scanner new Scanner(System.in); while (!game.isSolved()) { System.out.println(当前棋盘); printBoard(game); System.out.print(输入要移动的块编号1- (game.getTileCount() - 1) 0退出); String line scanner.nextLine(); int num; try { num Integer.parseInt(line.trim()); } catch (NumberFormatException e) { System.out.println(输入的不是数字请重试。); continue; } if (num 0) break; int index num - 1; if (game.canMove(index)) { game.move(index); } else { System.out.println(这个块当前不能移动。); } } printBoard(game); System.out.println(game.isSolved() ? 恭喜复原 : 手动退出。); scanner.close(); } private static void printBoard(NumberPuzzle game) { int size game.getSize(); for (int r 0; r size; r) { for (int c 0; c size; c) { int v game.getTile(r * size c); System.out.printf(%2d , v 0 ? 0 : v); } System.out.println(); } } }逻辑说明这里我用nextLine()而不是nextInt()是因为用户如果输入“3 空格回车”nextInt()会把残留换行留给下一次输入造成跳过。先用trim()去掉首尾空白再解析遇到非数字就continue这样整个外部输入通道是干净的。打印棋盘用printf(%2d)对齐改成石头迷阵时只需要把数字替换成图标名称。参数说明printBoard里通过game.getSize()拿边长不再写死4。这个“小暴露”是重构的第一步后续Swing版也会用到避免在多个地方重复定义。3.3 Swing界面JButton网格、事件绑定与刷新策略图形界面这一步我推荐用Swing而不是JavaFX原因只有一个Swing是JDK自带的零依赖直接javac Main.java就能跑适合项目实战和面试演示。JavaFX在较新的JDK里已经被拆分出去配置成本更高。import javax.swing.*; import java.awt.*; public class GamePanel extends JPanel { private final NumberPuzzle game; private final JButton[] buttons; public GamePanel(NumberPuzzle game) { this.game game; int size game.getSize(); setLayout(new GridLayout(size, size)); buttons new JButton[size * size]; for (int i 0; i buttons.length; i) { JButton button new JButton(); button.setFont(new Font(SansSerif, Font.BOLD, 24)); int index i; button.addActionListener(e - { if (game.canMove(index)) { game.move(index); refresh(); } }); buttons[i] button; add(button); } refresh(); } private void refresh() { int size game.getSize(); for (int i 0; i buttons.length; i) { int value game.getTile(i); buttons[i].setText(value 0 ? : String.valueOf(value)); buttons[i].setEnabled(value ! 0); } } }逻辑说明按钮下标直接用一维棋盘下标点击事件里先判断canMove再move然后统一调refresh()。refresh()全量更新文字和可用状态虽然简单但16个按钮完全不会卡顿。setEnabled(false)让空白格不可点击避免用户在空白块上点出“无法移动”的提示体验更好。这里有一个关键点GamePanel不持有Scanner只持有game对象所有输入都来自事件回调。这样模型和视图彻底分离后面如果改成REST接口或增加AI自动求解都不需要动视图代码。Main类只要创建一个JFrame把GamePanel加进去即可import javax.swing.*; public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(() - { JFrame frame new JFrame(数字华容道); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new GamePanel(new NumberPuzzle(4))); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); }); } }这里要注意用SwingUtilities.invokeLater启动Swing线程而不是直接在main线程创建组件。这是Java面试题里常问的单线程模型也算项目实战里的正规写法。如果你想往前后端分离项目实战方向扩展也可以把NumberPuzzle抽成纯Java模型再用Spring Boot暴露REST接口前端用Vue调接口不过那是另一个话题了。4. 石头迷阵变体图标代替数字、自定义尺寸与随机打乱算法4.1 石头迷阵和数字华容道的关系换皮不换核“石头迷阵”听起来像另一个游戏其实它只是数字华容道的换皮版本把16个格子里115的数字替换成不同颜色或纹理的石头块目标变成把石头按顺序排列。规则、移动逻辑、可解性检测完全复用。很多游戏项目实战的题目里写“数字华容道/石头迷阵”目的就是让你把通用逻辑拆出来UI只是主题。我一般会把主题资源抽出来单独管理。数字版用一个int就行石头版则需要维护MapInteger, Icon把每个数字映射到一张图片。这样针对“石头迷阵”的改动只会落在UI层模型层一个字节都没变。这也是面试时能讲清楚“面向对象设计”的地方。4.2 随机打乱为什么不能只靠shuffle50%的错误局面过滤初学者最容易犯的错误是直接对数组做Collections.shuffle然后交给玩家。前面说过随机洗牌只有一半情况可解。这也是很多“数字华容道项目”被投诉的根本原因。正确做法是洗完牌后用isSolvable检查如果无解就交换前两个非零块。import java.util.*; public class PuzzleShuffler { public static void shuffle(NumberPuzzle game) { int size game.getSize(); int[] tiles new int[size * size]; for (int i 0; i tiles.length - 1; i) tiles[i] i 1; tiles[tiles.length - 1] 0; ListInteger list new ArrayList(); for (int v : tiles) list.add(v); Collections.shuffle(list); int[] shuffled list.stream().mapToInt(Integer::intValue).toArray(); if (!NumberPuzzle.isSolvable(shuffled, size)) { // 交换前两个非零块翻转奇偶性 int first -1, second -1; for (int i 0; i shuffled.length; i) { if (shuffled[i] 0) continue; if (first -1) first i; else if (second -1) { second i; break; } } int tmp shuffled[first]; shuffled[first] shuffled[second]; shuffled[second] tmp; } game.setTiles(shuffled, findBlank(shuffled)); } private static int findBlank(int[] tiles) { for (int i 0; i tiles.length; i) { if (tiles[i] 0) return i; } return -1; } }逻辑说明交换两个非零块会把逆序数奇偶性翻转因此无解变成有解。为什么交换两个而不是三个因为一次相邻交换最少影响一次逆序数两次交换又会翻回来作为修正手段单个对换是最小的改动。这里没有使用固定种子如果想让测试可复现可以让shuffle接收一个long seed参数传给Collections.shuffle。参数说明list.stream().mapToInt(...)是一种快速把ListInteger转int[]的写法熟悉Lambda的人会觉得很顺手。如果你还在用老版本Java可以手动for循环填充。这个类独立成PuzzleShuffler是因为它同时要被游戏初始化、关卡生成和测试代码调用。4.3 自定义尺寸与难度参数化从3x3到5x5把size变成构造参数后3x3八数码、4x4十五数码、5x5二十四数码都能跑。不同尺寸的判定差异已经在2.3里处理UI的GridLayout也自动跟着变主题映射则只需准备相应数量的图标。尺寸数字个数适合场景3x38单元测试、算法教学4x415经典游戏、项目实战展示5x524进阶挑战、求解器压力测试难度参数除了尺寸还可以控制打乱次数。但注意打乱次数多不代表更难因为移动路径可能重复反而可能产生简单局面。更可靠的难度参数是“从目标状态反向随机走N步”每步只做合法的反向移动。这样保证初始局面一定可解而且步数有上限。这个思路本身就是一个递归回溯过程和后面说的求解器形成闭环。主题替换的代码可以像这样写在GamePanel里增加一个applyTheme(MapInteger, Icon iconMap)方法遍历按钮把非空格按钮设置为对应图标。public void applyTheme(MapInteger, Icon icons) { for (int i 0; i buttons.length; i) { int value game.getTile(i); if (value 0) { buttons[i].setIcon(null); } else { buttons[i].setIcon(icons.get(value)); } } refresh(); }逻辑说明icons.get(value)直接按数字取资源不需要知道具体是哪块石头。图片首次加载应该放在Main里统一做一次存进Map再传入避免每次刷新都读磁盘。石头迷阵界面还可以把数字改成石头1、石头2的标题但核心逻辑完全一致。这个参数化过程也适合参加蓝桥杯数字拼图题你只需要把size换成题目给的n。5. 避坑数字华容道Java项目实战的5个常见踩坑点5.1 打乱后永远无法复原shuffle撞上不可解排列现象玩家玩到只剩两个数字对调无论怎么移都差一步或者你自己测试时从初始状态开始就找不到解。 原因打乱只用了Collections.shuffle没有做可解性检测。无序排列中有一半不可达开局就是死局。 解决打乱后调用2.3里的isSolvable无解则交换前两个非零块。更稳妥的做法是采用4.3提到的“反向移动N步”生成局面天然可解。我在项目里默认用后者随机洗牌只留作彩蛋模式。5.2 点击按钮后界面没反应但调试信息显示move执行了现象控制台打印了移动成功的日志但屏幕上的数字纹丝不动。 原因移动后没有调用刷新方法或者刷新时更新了模型数组但没更新按钮文字。 解决在按钮事件里走统一的refresh()这个函数负责把每个按钮的setText、setEnabled和图标都重新设置一遍。我写过一个反面案例在move方法里刷新结果控制台版也被牵连出现了空指针。正确的做法是刷新只存在于UI层模型层不做任何与界面有关的操作。5.3 按钮文字和期望位置错位一维下标与行列转换弄反现象你点击第3行第2列的块结果第2行第3列在动。 原因在UI代码里自己写了行列换算比如index row col * size而正确的是一维数组按行优先存储index row * size col。二维数组如果直接用[col][row]也会发生同样错位。 解决模型层直接暴露一维下标UI层不做二次转换。如果项目已经有二维数组写一个to1D(int row, int col)工具方法并加单元测试验证坐标映射。这个坑也常出现在拼图、扫雷、连连看之类的二维网格项目里先统一好映射后面就不会翻车。5.4 5x5以上刷图卡顿每次移动都重读图片资源现象3x3流畅5x5或石头迷阵使用大量图片后每次点击有明显卡顿。 原因setIcon每次都从硬盘读ImageIcon图片缩放也在刷新代码里重复执行。在Java里磁盘I/O是最大的性能黑匣子不能放到高频路径。 解决在启动时把ImageIcon加载到MapInteger, Icon缓存刷新时只做setIcon(icons.get(value))。如果需要缩放用new ImageIcon(img.getScaledInstance(w, h, Image.SCALE_SMOOTH))也放到初始化阶段。这样指数级减少I/O界面自然流畅。5.5 源码包导入后中文乱码或编译失败编码与JDK版本不一致现象从网上拿来的源码在IDE里中文注释全乱或者javac报“非法字符: \uff1b”这类错误。 原因源码是GBK编码而IDE默认UTF-8或者用了var等新语法但编译器还在JDK 8。 解决用IDE的File Encodings把项目编码切到UTF-8再统一转码如果命令行编译加-encoding UTF-8。对于JDK版本在pom.xml里设置maven.compiler.source/target为一组自己验证过的版本不要盲目用最新。源代码管理上我习惯在项目根目录放一个.editorconfig强制UTF-8和LF换行这是被乱码坑过之后养成的习惯。这些坑如果写成自动化测试用例也能变成很好的软件测试项目实战素材。6. 进阶给游戏加一个回溯求解器用最少步数验证你的打乱算法数字华容道项目做完后我建议你再加一个自动求解功能。常见做法是BFS但4x4的状态空间非常大全量BFS会吃光内存。所以我改用迭代加深搜索IDS从深度0开始逐层加深每次做DFS并且跳过空白格本身来减少无效分支。这个策略对4x4随机打乱通常几十步内能出解虽然不保证最少步数但能作为打乱算法的反向验证。import java.util.*; public class PuzzleSolver { public ListInteger solve(NumberPuzzle game) { int maxDepth 80; for (int depth 0; depth maxDepth; depth) { ListInteger path new ArrayList(); if (dfs(game, depth, path)) { return path; } } return null; } private boolean dfs(NumberPuzzle game, int depth, ListInteger path) { if (game.isSolved()) return true; if (depth 0) return false; int[] savedTiles game.getTiles().clone(); int savedBlank game.getBlankIndex(); for (int i 0; i game.getTileCount(); i) { if (i savedBlank) continue; if (!game.canMove(i)) continue; game.move(i); path.add(i); if (dfs(game, depth - 1, path)) return true; path.remove(path.size() - 1); game.setTiles(savedTiles, savedBlank); } return false; } }逻辑说明depth是递归层数每层只额外做一步。savedTiles和savedBlank在递归前保存回溯时恢复保证状态不污染。i savedBlank是跳过空白格本身因为点击空白格没有意义canMove(i)保证相邻。这个版本没有做严格的路径剪枝如果你追求性能可以再加一个prevIndex参数避免把上一步刚移过来的块立刻移回去。实际使用时我在游戏初始化完成后调一次solve如果返回的路径长度大于0才把局面开放给玩家如果返回null说明打乱算法又出了问题。有一次我改了shuffle的种子逻辑忘了重新验证结果测试妹子玩三局就有两局死局最后就是用这个求解器定位出来的。现在我的习惯是每个打乱器都配一个求解器做回归测试测出平均求解步数和最大深度作为难度指标写进项目说明里。这个小习惯帮我少了很多玄学调参的夜晚希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Unity深度图优化:零翻倍Draw Call的4种实战方案

Unity深度图优化:零翻倍Draw Call的4种实战方案

1. 项目概述:为什么深度图优化总在“画蛇添足”?Unity里做深度图(Depth Texture),绝大多数人第一反应就是勾上Camera的Depth Texture Mode → Depth,然后在Shader里用_CameraDepthTexture采样——看起来很顺…

2026/10/18 0:39:25 阅读更多 →
Vue3框架搭建3:配置说明-prettier配置与TaoToken协作实践

Vue3框架搭建3:配置说明-prettier配置与TaoToken协作实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:39:25 阅读更多 →
微信小程序连接PHP后端获取数据库数据实战指南

微信小程序连接PHP后端获取数据库数据实战指南

1. 项目概述:为什么小程序要连PHP后端拿数据库数据?“微信小程序网络请求服务器php接口获取数据库数据信息”——这短短二十个字,其实是绝大多数中小型业务型小程序落地时绕不开的“第一道坎”。它不是炫技,而是刚需:小…

2026/10/18 0:38:23 阅读更多 →

最新新闻

Java计算两个日期之间的工作日天数:排除周末、节假日与调休的完整方案

Java计算两个日期之间的工作日天数:排除周末、节假日与调休的完整方案

简介:这是一份面向Java开发者的日期计算实战资料,聚焦「计算两个日期之间的天数并排除节假日与周末」这一常见业务需求,适合需要实现请假天数、工作日统计等功能的初中级开发者参考。资源以PDF形式呈现,压缩包内共1个文件&#xf…

2026/10/18 1:19:42 阅读更多 →
163MusicLyrics:从网易云和 QQ 音乐批量导出 LRC/SRT 歌词的免费开源工具

163MusicLyrics:从网易云和 QQ 音乐批量导出 LRC/SRT 歌词的免费开源工具

163MusicLyrics:从网易云和 QQ 音乐批量导出 LRC/SRT 歌词的免费开源工具 【免费下载链接】163MusicLyrics 云音乐歌词获取处理工具【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 整理本地曲库时,一个常见…

2026/10/18 1:19:42 阅读更多 →
KBEngine 内嵌 Python 的 shelve 模块:持久化字典的用法、陷阱与源码剖析

KBEngine 内嵌 Python 的 shelve 模块:持久化字典的用法、陷阱与源码剖析

游戏开发后端 【免费下载链接】kbengine A MMOG engine of server. 项目地址: https://gitcode.com/gh_mirrors/kb/kbengine 点击查看 免费下载 导读 shelve 是 Python 标准库中一个将对象序列化后持久化到磁盘的模块,它提供一种"持久化的字典&qu…

2026/10/18 1:19:42 阅读更多 →
BIND主从DNS服务器与分离解析实战:高可用架构配置指南

BIND主从DNS服务器与分离解析实战:高可用架构配置指南

1. 项目缘起与整体设计思路1.1 为什么单台DNS服务器扛不住真实场景很多人在实验环境里搭DNS,习惯性地只配一台服务器,解析记录一写,systemctl restart named,能ping通域名就算完事。这种玩法在自家局域网里确实够用,但…

2026/10/18 1:19:42 阅读更多 →
FSoE黑通道原理:工业安全通信的不可信链路设计

FSoE黑通道原理:工业安全通信的不可信链路设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 1:19:42 阅读更多 →
Step-3.7-Flash-oQ3e基准测试深度解析:思考开0.77 vs 关0.57,量化损失究竟多少?

Step-3.7-Flash-oQ3e基准测试深度解析:思考开0.77 vs 关0.57,量化损失究竟多少?

【免费下载链接】Step-3.7-Flash-oQ3e 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/Step-3.7-Flash-oQ3e 点击查看 免费下载 Step-3.7-Flash-oQ3e 是 stepfun-ai/Step-3.Flash 系列面向 Apple Silicon 的 MLX 量化模型(oQ3e&#xff0c…

2026/10/18 1:18:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →