<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>如若不燃</title><description>酷爱蹦跶，穿梭堂狱</description><link>https://from-env.com</link><item><title>Undertale 传说之下</title><link>https://from-env.com/posts/undertale</link><guid isPermaLink="true">https://from-env.com/posts/undertale</guid><pubDate>Wed, 18 Jan 2017 15:16:22 GMT</pubDate><content:encoded>&lt;p&gt;第一次了解 Undertale，是在网易云音乐听到其 OST「Stronger Than You」。这是一款打破常规的另类 RPG，且乐评率在 Steam 排名第一，是 2015 Steam 最佳游戏之一。好奇心促使我对它一探究竟。&lt;/p&gt;
&lt;p&gt;「Stronger Than You」&lt;/p&gt;
&lt;p&gt;第一遍没看攻略，走了中立路线。一路上杀了所有主要人物，除了羊爸。我饶恕了他，最后等到的却是 Flowey 大魔王的奸笑。Flowey 吸收了羊爸先前占有的 6 个人类灵魂，变身绿巨怪发射全屏弹幕，这里我被折磨 n 遍才通关，想屎的心都有了。&lt;/p&gt;
&lt;p&gt;第二遍开始走善良路线，幻想着自己可以绝对完美地走完一切，然后迎来 happy ending。然而路途上，npc 居然记得你曾经杀过它，纳闷为什么你看它的眼神像在看一个灵魂。它会戳穿你没有穿 Old Tutu 的谎言。总之，你的言行不一，都会被敏锐的 npc 察觉到，可谓本游戏细思恐极之处。一般而言，玩家觉得自己是游戏的主宰，而在这里，你的人性仿佛被游戏看穿。&lt;/p&gt;
&lt;p&gt;另外，尽管最后没有变态绿巨怪 Flowey 出现，但是前面小 Boss 们的脱战方式的难度也不小。因为你不能杀死他们，每个 Boss 的脱战方式需要自己摸索好久……也只有唯有 stay determined（无限复活），不断提升自己的躲避技巧，才能战胜他们。&lt;/p&gt;
&lt;p&gt;除了中立路线与和平路线，还存在第三种屠杀路线：你必须杀光所有随机遇到的小怪，神挡杀神，佛挡杀佛。若如此作，所有普民包括商店老板会逃跑，你能毫不费力获得回复道具及强力武器。最后，你终于走进「Stronger Than You」的情节：Sans 了解你厌倦了一次次地走和平路线，企图杀戮所有人的决心，决定誓死也要阻止你。虽然屠杀能使你获得大量 LOVE，能毫不费力的升满 19 级并获得最强武器，但面对攻击力和防御力均为 1 的 Sans，你只能感受到绝望。相比之前，你失去了受伤后的无敌时间，若稍显失误，你就挂在他的连续攻击之下，接着 stay determined，重新开始战斗。而他每次都能 Miss 你的攻击，令人抓狂。个人觉得这样过于残忍，着实不敢走这条路。&lt;/p&gt;
&lt;p&gt;开全屏玩这款游戏，听 BGM ，场景代入感十分强烈。每个小怪都有自己的性格、故事和其对应风格的曲子，讨人欢喜。尤其是和羊妈重逢的时候再次响起和羊妈在一起时的 BGM，有种游子归家的感动。若是重玩这款游戏，有趣的 BGM 依然值得回味。&lt;/p&gt;
&lt;p&gt;羊妈家 BGM&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>Edge 浏览器复制粘贴 URL 显示网站标题</title><link>https://from-env.com/posts/edge-url-paste</link><guid isPermaLink="true">https://from-env.com/posts/edge-url-paste</guid><pubDate>Wed, 27 Apr 2022 15:04:41 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;meting-js id=&quot;1922188998&quot; type=&quot;song&quot; server=&quot;netease&quot; fixed=&quot;false&quot; mini=&quot;false&quot; autoplay=&quot;false&quot; theme=&quot;#255579&quot;&amp;gt;&amp;lt;/meting-js&amp;gt;&lt;/p&gt;
&lt;h2&gt;问题描述&lt;/h2&gt;
&lt;p&gt;与预料的不同，当把 Edge 浏览器地址栏中的 https://collection.armyja.cn/v/front-end/ 粘贴到 Notion
时，显示的是超链接 【前端笔记 - Collection (armyja.cn)】。这是为什么呢？&lt;/p&gt;
&lt;p&gt;把 https://collection.armyja.cn/v/front-end/ 粘贴到记事本，再粘贴回
Notion，发现只显示超链接 https://collection.armyja.cn/v/front-end/ ，符合预期。&lt;/p&gt;
&lt;h2&gt;分析过程&lt;/h2&gt;
&lt;p&gt;打开 Chrome Debugger，添加事件侦听器断点，勾选 paste，如下图所示。粘贴网址，进断点。由于 js
文件是混淆过的，挤在一行不好分析，于是点击下图左下角的【{}】按钮，展示为 format
后的代码内容。
&lt;img alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;首先进入到 injectGlobalHook.js，如下图所示。因为 _intercept 变量值为 false，所以函数没有做任何操作。所以这里不需要分析。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;接着跳到下一个断点监听，如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;到这里就比较难推进了，因为每在函数内部调用一次函数就要手动定位函数位置并打断点。有没有更快的办法呢？注意到
clipboardData 有 3 个 type。参考 https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData 、
https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData ，提到 clipboardData 的类型为 DataTransfer，有方法 getData(format)。
format 为 data types。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Example data types are &lt;code&gt;text/plain&lt;/code&gt; and &lt;code&gt;text/uri-list&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;于是在控制台尝试拿到粘贴内容。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; i[0].clipboardData.getData(&apos;text/html&apos;)
&amp;lt; &apos;&amp;lt;html&amp;gt;\r\n&amp;lt;body&amp;gt;\r\n\x3C!--StartFragment--&amp;gt;&amp;lt;a href=&quot;https://collection.armyja.cn/v/front-end/&quot;&amp;gt;前端笔记 - Collection (armyja.cn)&amp;lt;/a&amp;gt;\x3C!--EndFragment--&amp;gt;\r\n&amp;lt;/body&amp;gt;\r\n&amp;lt;/html&amp;gt;&apos;

&amp;gt; i[0].clipboardData.getData(&apos;text/link-preview&apos;)
&amp;lt; &apos;&apos;

&amp;gt; i[0].clipboardData.getData(&apos;text/plain&apos;)
&amp;lt; &apos;&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;顺藤摸瓜，既然粘贴的内容类型是 &lt;code&gt;text/html&lt;/code&gt;，那么 js 一定有针对这一类型做特殊处理。在这个文件搜索
&lt;code&gt;text/html&lt;/code&gt;，打上断点，果然程序停在这里，距离上个分析点直接越过 10 余个堆栈元素，如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;回溯到中间的堆栈可以看到返回有语义的 json 结构，如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;当把 Edge 浏览器地址栏中的网址粘贴到 Notion 时，js 存储的粘贴内容由浏览器决定， data type 为 &lt;code&gt;text/html&lt;/code&gt;。&lt;br /&gt;
从记事本拷贝链接，js 存储的粘贴内容 data type 为 &lt;code&gt;text/plain&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;在 Edge 浏览器的 &lt;strong&gt;设置 - 共享、复制和粘贴&lt;/strong&gt; 里说明了，默认 Ctrl-V 是粘贴链接，
Ctrl-Shift-V 为粘贴纯文本，详细说明参见 https://go.microsoft.com/fwlink/?linkid=2136809 。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; /&gt;&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>GAMES104 笔记</title><link>https://from-env.com/posts/games104-note</link><guid isPermaLink="true">https://from-env.com/posts/games104-note</guid><pubDate>Mon, 30 May 2022 07:23:59 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;meting-js id=&quot;33367012&quot; type=&quot;song&quot; server=&quot;netease&quot; fixed=&quot;false&quot; mini=&quot;false&quot; autoplay=&quot;false&quot; theme=&quot;#255579&quot;&amp;gt;&amp;lt;/meting-js&amp;gt;&lt;/p&gt;
&lt;h2&gt;GAMES104 课程简介&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Pilot Engine&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本课程将介绍现代游戏引擎所涉及的系统架构，技术点，引擎系统相关的知识。 通过该课程，你能够对游戏引擎建立起一个全面且完整的了解。 如果你动手能力足够强，你将能够跟随课程，从 0 到 1 搭建起一个完整的迷你游戏引擎。如本课程适合相关专业领域的学生、研究者，以及所有对游戏引擎设计和开发感兴趣的人。&lt;/p&gt;
&lt;p&gt;课程网址：&lt;a href=&quot;https://games104.boomingtech.com/&quot;&gt;https://games104.boomingtech.com/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;作业&lt;/h2&gt;
&lt;h3&gt;PA01:Build and Run Pilot Engine&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://cdn.boomingtech.com/games104_static/upload/GAMES104_PA01.pdf&quot;&gt;作业说明 PDF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作业说明：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build and run Pilot ✔️&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;笔者安装 Visual Studio 2022，安装选项附带了 CMake，所以为了在命令行使用 CMake，添加用户环境变量：&lt;code&gt;X:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Execute the &lt;strong&gt;build_windows.bat&lt;/strong&gt;, and then open &lt;strong&gt;Pilot.sln&lt;/strong&gt; with Visual Studio&lt;/p&gt;
&lt;p&gt;错误提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fatal: unsafe repository (&apos;D:/project/Pilot&apos; is owned by someone else)
To add an exception for this directory, call:

    git config --global --add safe.directory D:/project/Pilot
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个问题似乎与 &lt;a href=&quot;https://github.blog/2022-04-12-git-security-vulnerability-announced/&quot;&gt;https://github.blog/2022-04-12-git-security-vulnerability-announced/&lt;/a&gt; 相关。暂时不理会。&lt;/p&gt;
&lt;h3&gt;PA02:Rendering&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://cdn.boomingtech.com/games104_static/upload/PA02%EF%BC%9ARendering%20.pdf&quot;&gt;作业说明 PDF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作业说明：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在 Pilot 小引擎代码中找到
&lt;code&gt;pilot/engine/shader/glsl/color_grading.frag&lt;/code&gt;，补充此 &lt;code&gt;shader&lt;/code&gt; 代码中的
&lt;code&gt;main&lt;/code&gt; 函数，以实现 &lt;code&gt;ColorGrading&lt;/code&gt; 功能。若代码编译成功且实现方法正确，则可
以看到进行 &lt;code&gt;ColorGrading&lt;/code&gt; 渲染之后的结果。 ✔️&lt;/li&gt;
&lt;li&gt;使用自定义的 &lt;code&gt;LUT&lt;/code&gt; 图，并修改相应代码，实现具有个性的 &lt;code&gt;ColorGrading&lt;/code&gt; 的
效果。 ✔️&lt;/li&gt;
&lt;li&gt;（提高项，可选）添加一个新的 &lt;code&gt;Pass&lt;/code&gt; 实现某个自己感兴趣的后处理效果 ❌
&lt;ul&gt;
&lt;li&gt;调整 PMainCameraPass::setupRenderPass 添加一个新的 Vulkan Subpass。&lt;/li&gt;
&lt;li&gt;调整 PVulkanManager::initializeDescriptorPool 增加相关 Descriptor 的数量。&lt;em&gt;【这里用了 Magic Number，不清楚如何统计，可能和 Vulkan 相关】&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;LUT 贴图路径：&lt;code&gt;engine\asset\texture\lut&lt;/code&gt;，默认配置为&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;color_grading_map&quot;: &quot;asset/texture/lut/color_grading_lut_01.png&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置文件在 &lt;code&gt;engine\asset\global\rendering.global.json&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mortenblaa/lut-generator/&quot;&gt;LUT Table Texture Generator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Python script for generating neutral LUT tables of different sizes. It supports both Unreal Engine style LUT (top down) and the Unity style LUT (bottom up).&lt;/p&gt;
&lt;p&gt;Based on a GitHub gist by Koki Ibukuro.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Samples&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Unreal Engine&lt;/th&gt;
&lt;th&gt;Unity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;256x16&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://github.com/mortenblaa/lut-generator/raw/master/samples/unreal/lut_strip_16_256x16.png&quot; alt=&quot;strip 256x16&quot; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://github.com/mortenblaa/lut-generator/raw/master/samples/unity/lut_strip_16_256x16.png&quot; alt=&quot;lut_strip_16_256x16&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024x32&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://github.com/mortenblaa/lut-generator/raw/master/samples/unreal/lut_strip_32_1024x32.png&quot; alt=&quot;strip 1024x32&quot; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://github.com/mortenblaa/lut-generator/raw/master/samples/unity/lut_strip_32_1024x32.png&quot; alt=&quot;strip 1024x32&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pilot 使用 Unreal Engine 的格式。&lt;/p&gt;
&lt;p&gt;修改 &lt;code&gt;engine\shader\glsl\color_grading.frag&lt;/code&gt;，参考 &lt;a href=&quot;https://www.zhihu.com/people/wang-jun-yang-5-82&quot;&gt;V1tozzZ&lt;/a&gt; 的实现：&lt;a href=&quot;https://zhuanlan.zhihu.com/p/508156645&quot;&gt;GAMES104 作业 2 基础部分&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#version 310 es

#extension GL_GOOGLE_include_directive : enable

#include &quot;constants.h&quot;

layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInput in_color;

layout(set = 0, binding = 1) uniform sampler2D color_grading_lut_texture_sampler;

layout(location = 0) out highp vec4 out_color;

void main()
{
    // 这里的 LUT 贴图为单行排列
    highp ivec2 lut_tex_size = textureSize(color_grading_lut_texture_sampler, 0);
    // 纵向值，同时表示格子的数量，一般取值 16，32，64
    highp float _COLORS      = float(lut_tex_size.y);
    // 横向值，为纵向值的平方
    highp float xsize        = float(lut_tex_size.x);

    // rgba 的取值范围: 0 ~ 1.0
    highp vec4 color       = subpassLoad(in_color).rgba;

    // 先得到 rgb 在 lut 颜色数量上的映射（可以理解为在单个格子里的偏移量）
    highp float bluemapped          = (_COLORS-1.0)*color.b;
    highp float redmapped           = (_COLORS-1.0)*color.r;
    highp float greenmapped         = (_COLORS-1.0)*color.g;

    // 用蓝色确定从左至右第几个颜色格子，加上红色确定格子上x坐标 取得u坐标
    // 映射后的蓝色可能是小数 那么就取小数前后两个格子
    highp float rbmapped1 = redmapped + floor(bluemapped)*_COLORS;
    highp float rbmapped2 = redmapped + ceil(bluemapped)*_COLORS;
    highp float u1 = rbmapped1/xsize;
    highp float u2 = rbmapped2/xsize;

    // 用绿色取v坐标
    highp float v = greenmapped/_COLORS;
    highp vec2 uv1 = vec2(u1,v);
    highp vec2 uv2 = vec2(u2,v);
    highp vec3 mappedcolor1  =   texture(color_grading_lut_texture_sampler, uv1).xyz;
    highp vec3 mappedcolor2  =   texture(color_grading_lut_texture_sampler, uv2).xyz;

    //混合两个格子的颜色 fract(bluemapped)表示用小数部分决定两个格子占比权重
    highp vec3 mixedcolor   =   mix(mappedcolor1,mappedcolor2,fract(bluemapped));

    out_color = vec4(mixedcolor,color.a);

}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Pilot 引擎技术点&lt;/h2&gt;
&lt;h3&gt;反射&lt;/h3&gt;
&lt;p&gt;Pilot 引擎使用静态反射框架，用户通过 &lt;strong&gt;定义数据结构&lt;/strong&gt; 与提供对应的 &lt;strong&gt;配置文件&lt;/strong&gt;，框架利用元编程技术生成读取接口。&lt;/p&gt;
&lt;p&gt;可以在 &lt;code&gt;engine\source\_generated\serializer\all_serializer.ipp&lt;/code&gt; 看到序列化/反序列化代码，由 &lt;code&gt;engine\source\precompile\precompile.cmake&lt;/code&gt; 定义的预编译流程生成。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &quot;D:/project/Pilot/engine/source/_generated/serializer/global_rendering.serializer.gen.h&quot;
namespace Pilot{
    // ...
    template&amp;lt;&amp;gt;
    PJson PSerializer::write(const GlobalRenderingRes&amp;amp; instance){
        PJson::object  ret_context;
        ret_context.insert_or_assign(&quot;skybox_irradiance_map&quot;, PSerializer::write(instance.m_skybox_irradiance_map));
        ret_context.insert_or_assign(&quot;skybox_specular_map&quot;, PSerializer::write(instance.m_skybox_specular_map));
        ret_context.insert_or_assign(&quot;brdf_map&quot;, PSerializer::write(instance.m_brdf_map));
        ret_context.insert_or_assign(&quot;color_grading_map&quot;, PSerializer::write(instance.m_color_grading_map));
        ret_context.insert_or_assign(&quot;sky_color&quot;, PSerializer::write(instance.m_sky_color));
        ret_context.insert_or_assign(&quot;ambient_light&quot;, PSerializer::write(instance.m_ambient_light));
        ret_context.insert_or_assign(&quot;camera_config&quot;, PSerializer::write(instance.m_camera_config));
        ret_context.insert_or_assign(&quot;directional_light&quot;, PSerializer::write(instance.m_directional_light));
        return  PJson(ret_context);
    }
    template&amp;lt;&amp;gt;
    GlobalRenderingRes&amp;amp; PSerializer::read(const PJson&amp;amp; json_context, GlobalRenderingRes&amp;amp; instance){
        assert(json_context.is_object());
        if(!json_context[&quot;skybox_irradiance_map&quot;].is_null()){
        PSerializer::read(json_context[&quot;skybox_irradiance_map&quot;], instance.m_skybox_irradiance_map);
        }
        if(!json_context[&quot;skybox_specular_map&quot;].is_null()){
        PSerializer::read(json_context[&quot;skybox_specular_map&quot;], instance.m_skybox_specular_map);
        }
        if(!json_context[&quot;brdf_map&quot;].is_null()){
        PSerializer::read(json_context[&quot;brdf_map&quot;], instance.m_brdf_map);
        }
        if(!json_context[&quot;color_grading_map&quot;].is_null()){
        PSerializer::read(json_context[&quot;color_grading_map&quot;], instance.m_color_grading_map);
        }
        if(!json_context[&quot;sky_color&quot;].is_null()){
        PSerializer::read(json_context[&quot;sky_color&quot;], instance.m_sky_color);
        }
        if(!json_context[&quot;ambient_light&quot;].is_null()){
        PSerializer::read(json_context[&quot;ambient_light&quot;], instance.m_ambient_light);
        }
        if(!json_context[&quot;camera_config&quot;].is_null()){
        PSerializer::read(json_context[&quot;camera_config&quot;], instance.m_camera_config);
        }
        if(!json_context[&quot;directional_light&quot;].is_null()){
        PSerializer::read(json_context[&quot;directional_light&quot;], instance.m_directional_light);
        }
        return instance;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;相关分析：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zhihu.com/people/ban-tang-96-14&quot;&gt;鹏 wp&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/502729373&quot;&gt;C++反射-Pilot 引擎的反射实现&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zhihu.com/people/netcan&quot;&gt;netcan&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/165993590&quot;&gt;如何优雅的实现 C++编译期静态反射
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/388454455&quot;&gt;C++静态反射框架：ConfigLoader&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><author>Armyja</author></item><item><title>2024 第一篇博客</title><link>https://from-env.com/posts/2024-first-blog</link><guid isPermaLink="true">https://from-env.com/posts/2024-first-blog</guid><pubDate>Sun, 31 Mar 2024 15:17:00 GMT</pubDate><content:encoded>&lt;h2&gt;加油&lt;/h2&gt;
&lt;p&gt;你好棒&lt;/p&gt;
&lt;p&gt;来听音乐吧
&amp;lt;meting-js id=&quot;2118754864&quot; type=&quot;song&quot; server=&quot;netease&quot; fixed=&quot;false&quot; mini=&quot;false&quot; autoplay=&quot;false&quot; theme=&quot;#255579&quot;&amp;gt;&amp;lt;/meting-js&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://bucket.armyja-online.uk/blog/1711948205956.jpg&quot; alt=&quot;GMA全球音乐奖获奖&quot; /&gt;&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>Cody介绍</title><link>https://from-env.com/posts/cody-introduction</link><guid isPermaLink="true">https://from-env.com/posts/cody-introduction</guid><description>Cody 是一个 AI 编码助手，负责编写、修复和维护您的代码。它使用 AI 和对代码库的深刻理解来收集上下文，帮助您更快地编写和理解代码。</description><pubDate>Thu, 04 Apr 2024 13:12:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://sourcegraph.com/docs/cody&quot;&gt;Cody&lt;/a&gt; 是一个 AI 编码助手，负责编写、修复和维护您的代码。它使用 AI 和对代码库的深刻理解来收集上下文，帮助您更快地编写和理解代码。&lt;/p&gt;
&lt;p&gt;它是 Sourcegraph 旗下的产品。&lt;a href=&quot;https://sourcegraph.com&quot;&gt;Sourcegraph&lt;/a&gt; 是一个代码智能平台，可以深入理解您的代码，无论代码有多大或托管在何处，都能为现代开发人员体验提供支持。&lt;br /&gt;
1、AI 代码助手：使用 Cody 更快地读取、写入和理解整个代码库&lt;br /&gt;
2、代码搜索：搜索所有分支和所有代码主机的所有存储库&lt;br /&gt;
3、代码智能：导航代码、查找引用、查看代码所有者、跟踪历史记录等&lt;br /&gt;
4、修复和重构：跨存储库同时推出和跟踪大规模更改和迁移&lt;/p&gt;
&lt;p&gt;我使用 Cody 的原因，是以前习惯在 Sourcegraph 看 Github 网站的源码，浏览比较方便。并且每月会员 Cody 比 Copilot 便宜一点。&lt;br /&gt;
在 &lt;code&gt;VSCode&lt;/code&gt; 安装 &lt;code&gt;Cody AI&lt;/code&gt; 后，推荐两个配置：&lt;br /&gt;
1、自定义输出的语言&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
    &quot;cody.chat.preInstruction&quot;: &quot;Answer all my questions in Chinese.&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2、配置用户级别的自定义指令。在 &lt;code&gt;~/.vscode/cody.json&lt;/code&gt; 设置&lt;a href=&quot;https://sourcegraph.com/docs/cody/capabilities/commands#custom-commands&quot;&gt;自定义指令&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;commit-message&quot;: {
    &quot;description&quot;: &quot;Commit message for current changes&quot;,
    &quot;prompt&quot;: &quot;Suggest an informative commit message by summarizing code changes from the shared command output. The commit message should follow the conventional commit format and provide meaningful context for future readers.&quot;,
    &quot;context&quot;: {
      &quot;selection&quot;: false,
      &quot;command&quot;: &quot;git diff --cached&quot;
    }
  },
  &quot;current-dir&quot;: {
    &quot;description&quot;: &quot;Explain current directory&quot;,
    &quot;prompt&quot;: &quot;At a high level, explain what this directory is used for.&quot;,
    &quot;context&quot;: {
      &quot;currentDir&quot;: true,
      &quot;selection&quot;: false
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;做了如上配置后，可以在 &lt;code&gt;VSCode&lt;/code&gt; 使用预置命令用中文解释代码、用自定义命令解释当前文件夹的代码、生成提交说明，体验非常好。&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>QueryDSL源码阅读</title><link>https://from-env.com/posts/querydsl-code-reading</link><guid isPermaLink="true">https://from-env.com/posts/querydsl-code-reading</guid><description>QueryDSL是一个强大的框架,它使Java开发人员能够以类型安全的方式构建SQL查询。</description><pubDate>Thu, 04 Apr 2024 14:32:00 GMT</pubDate><content:encoded>&lt;h2&gt;导语&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/querydsl/querydsl&quot;&gt;QueryDSL&lt;/a&gt;是一个强大的框架,它使Java开发人员能够以类型安全的方式构建SQL查询。以下是我喜欢QueryDSL的一些原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;QueryDSL让我们摆脱了编写原始SQL字符串的麻烦,这种做法容易出错且难以维护。相反,QueryDSL提供了一个优雅的API,让我们可以像在Java代码中一样构建查询。这不仅提高了代码的可读性,还消除了SQL注入的风险。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;QueryDSL支持多种持久层框架,如JPA、SQL、MongoDB和Lucene等。无论使用何种持久层技术,QueryDSL都能提供统一的查询API,这极大地简化了跨框架的代码移植。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;QueryDSL查询是完全类型安全的,编译器会检查错误,避免了许多运行时错误。这使得重构变得更加容易和安全。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;QueryDSL查询也更易于维护。相比晦涩的SQL字符串,QueryDSL查询的代码结构更清晰,注释也更易于编写和理解。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;总之,QueryDSL让我们能够以一种现代、类型安全和面向对象的方式来构建查询,极大地提高了生产力和代码质量。它是Java持久层编程中非常有价值的工具。&lt;/p&gt;
&lt;p&gt;关于QueryDSL的使用示例，可以参考 Jay Kim 的&lt;a href=&quot;https://jskim1991.medium.com/spring-boot-exploring-spring-boot-3-with-querydsl-part-2-7b563c382192&quot;&gt;文章&lt;/a&gt; 和&lt;a href=&quot;https://github.com/jskim1991/spring-boot-querydsl-sample&quot;&gt;代码仓库&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;模块分析&lt;/h2&gt;
&lt;p&gt;从 &lt;code&gt;querydsl-core&lt;/code&gt; 开始看起，关注 &lt;code&gt;DSL expression types&lt;/code&gt;。&lt;code&gt;com.querydsl.core.types.dsl&lt;/code&gt; 包含了Querydsl核心类型的定义和实现。Querydsl是一个用于构建类型安全的SQL查询的框架,这些类型定义了Querydsl查询中使用的各种表达式和操作的接口和实现。&lt;/p&gt;
&lt;p&gt;一些主要的类型包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Expression: 定义了通用的类型化表达式接口。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Constant: 表示常量表达式。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Operation: 表示常见的操作和函数调用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Path: 表示变量、属性和集合成员访问。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FactoryExpression: 用于基于行的结果处理。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些接口和类为Querydsl提供了构建查询的基础抽象和实现。通过这些类型,Querydsl能够以类型安全的方式构造复杂的查询,并将其翻译为不同的查询语言(如SQL、MongoDB查询等)。&lt;/p&gt;
&lt;p&gt;总的来说,这个目录定义了Querydsl查询构造的核心模型,是整个Querydsl框架的基础。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;ToStringVisitor.java&lt;/code&gt; 代码片段&lt;/h3&gt;
&lt;p&gt;对于 &lt;code&gt;FactoryExpression&lt;/code&gt; 类型,构造一个新对象的字符串表示,包括类名和参数列表。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Override
public String visit(FactoryExpression&amp;lt;?&amp;gt; e， Templates templates) {
  final StringBuilder builder = new StringBuilder();
  builder.append(&quot;new &quot;).append(e.getType().getSimpleName()).append(&quot;(&quot;);
  boolean first = true;
  for (Expression&amp;lt;?&amp;gt; arg : e.getArgs()) {
    if (!first) {
      builder.append(&quot;, &quot;);
    }
    builder.append(arg.accept(this, templates));
    first = false;
  }
  builder.append(&quot;)&quot;);
  return builder.toString();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对于 &lt;code&gt;Operation&lt;/code&gt; 类型,根据操作符查找对应的模板,并按模板的元素顺序拼接字符串,处理操作数的优先级。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Override
public String visit(Operation&amp;lt;?&amp;gt; o, Templates templates) {
  final Template template = templates.getTemplate(o.getOperator());
  if (template != null) {
    final int precedence = templates.getPrecedence(o.getOperator());
    final StringBuilder builder = new StringBuilder();
    for (Template.Element element : template.getElements()) {
      final Object rv = element.convert(o.getArgs());
      if (rv instanceof Expression) {
        if (precedence &amp;gt; -1 &amp;amp;&amp;amp; rv instanceof Operation) {
          if (precedence &amp;lt; templates.getPrecedence(((Operation&amp;lt;?&amp;gt;) rv).getOperator())) {
            builder.append(&quot;(&quot;);
            builder.append(((Expression&amp;lt;?&amp;gt;) rv).accept(this, templates));
            builder.append(&quot;)&quot;);
            continue;
          }
        }
        builder.append(((Expression&amp;lt;?&amp;gt;) rv).accept(this, templates));
      } else {
        builder.append(rv.toString());
      }
    }
    return builder.toString();
  } else {
    return &quot;unknown operation with operator &quot; + o.getOperator().name() + &quot; and args &quot; + o.getArgs();
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Constant&lt;/h3&gt;
&lt;p&gt;Constant接口代表一个通用的常量表达式。它继承自 Expression 接口,并定义了一个 getConstant() 方法来获取包装的常量值。&lt;/p&gt;
&lt;p&gt;与之相关的主要类有:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ConstantImpl&lt;/code&gt;&lt;br /&gt;
这是 Constant 接口的实现类,它包装了实际的常量值。在 ConstantImpl 中,有一个泛型字段 constant 用于存储常量值。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Expressions&lt;/code&gt;&lt;br /&gt;
这是一个工具类,提供了创建常量表达式的静态方法 constant(T value)。它内部调用了 ConstantImpl.create(value) 来构造常量表达式。&lt;/p&gt;
&lt;p&gt;一些测试用的常量类&lt;br /&gt;
在测试代码中,有一些继承自 &lt;code&gt;ConstantImpl&lt;/code&gt; 的常量类,如 &lt;code&gt;TimeConstant&lt;/code&gt;、&lt;code&gt;DateConstant&lt;/code&gt;、&lt;code&gt;StringConstant&lt;/code&gt;、&lt;code&gt;NumberConstant&lt;/code&gt; 等,用于测试不同类型的常量表达式。&lt;/p&gt;
&lt;p&gt;总的来说,&lt;code&gt;Constant&lt;/code&gt; 接口定义了常量表达式的契约,&lt;code&gt;ConstantImpl&lt;/code&gt; 是其实现,而 &lt;code&gt;Expressions&lt;/code&gt; 工具类提供了创建常量表达式的便捷方法。在查询DSL中,常量表达式可以用于构建查询条件、投影等。&lt;/p&gt;
&lt;h3&gt;Path&lt;/h3&gt;
&lt;p&gt;Path接口代表一个路径表达式。路径表达式指的是对变量、属性和集合成员的访问。它继承自 Expression 接口。&lt;/p&gt;
&lt;p&gt;Path 接口定义了以下几个主要方法:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;getMetadata()：获取该路径的元数据。&lt;/li&gt;
&lt;li&gt;getRoot()：获取该路径的根路径。&lt;/li&gt;
&lt;li&gt;getAnnotatedElement()：获取与该路径相关的注解元素。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;与 Path 接口相关的主要类有:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PathMetadata：封装了路径的元数据信息,如路径类型、父路径等。&lt;/li&gt;
&lt;li&gt;PathImpl：Path 接口的默认实现类。&lt;/li&gt;
&lt;li&gt;一些具体的路径类,如 SimplePath、BeanPath、CollectionPath、MapPath 等,分别代表不同类型的路径。&lt;br /&gt;
这些具体的路径类通常作为查询的起点,例如:&lt;pre&gt;&lt;code&gt;QEmployee employee = QEmployee.employee;
employee.firstName // 代表 employee 对象的 firstName 属性路径
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在查询DSL中,路径表达式用于构建查询条件、投影等。通过路径表达式,可以方便地访问对象的属性、集合元素等。Path 接口定义了路径表达式的基本契约,而具体的路径类型由不同的实现类来表示。&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>洞洞谱制作器</title><link>https://from-env.com/posts/tin-whistle-tabs-creator</link><guid isPermaLink="true">https://from-env.com/posts/tin-whistle-tabs-creator</guid><pubDate>Thu, 09 May 2024 16:04:41 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;洞洞谱制作器&amp;lt;/title&amp;gt;
&amp;lt;meta name=viewport content=&quot;width = device-width, initial-scale = 1&quot;&amp;gt;
&amp;lt;style&amp;gt;
.l {
writing-mode: vertical-rl;
letter-spacing: 0.2ch;
}
#p_title {
font-size: 1.2em;
font-weight: bold;
}
#box&amp;gt;input,#box&amp;gt;button,#box&amp;gt;textarea {
border: 1px solid #ccc;
}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;body&amp;gt;
&amp;lt;div id=box&amp;gt;
&amp;lt;select id=&quot;type&quot;&amp;gt;
&amp;lt;option value=&quot;5&quot;&amp;gt;全按作5&amp;lt;/option&amp;gt;
&amp;lt;option value=&quot;1&quot;&amp;gt;全按作1&amp;lt;/option&amp;gt;
&amp;lt;/select&amp;gt;
标题：&amp;lt;input type=&quot;text&quot; id=&quot;title&quot;&amp;gt;
&amp;lt;br /&amp;gt;
简谱（1、(5)、[3]、[[1]]...）
&amp;lt;br /&amp;gt;
&amp;lt;textarea id=content&amp;gt;&amp;lt;/textarea&amp;gt;
&amp;lt;button id=&apos;btn&apos;&amp;gt;生成&amp;lt;/button&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;div id=p&amp;gt;
&amp;lt;div id=&quot;p_title&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;p_type&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;div id=&quot;preview&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
normal = {
&apos; &apos;: &apos;&amp;lt;span class=&quot;l&quot;&amp;gt; &amp;lt;/span&amp;gt;&apos;,
&apos;\n&apos;: &apos;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&apos;
}
one = {
&apos;1&apos;: &apos;bbbbbb&apos;,
&apos;2&apos;: &apos;bbbbbw&apos;,
&apos;3&apos;: &apos;bbbbww&apos;,
&apos;4&apos;: &apos;bbbwww&apos;,
&apos;5&apos;: &apos;bbwwww&apos;,
&apos;6&apos;: &apos;bwwwww&apos;,
&apos;7&apos;: &apos;wwwwww&apos;,
&apos;[1]&apos;: &apos;wbbbbb+&apos;,
&apos;[2]&apos;: &apos;bbbbbw+&apos;,
&apos;[3]&apos;: &apos;bbbbww+&apos;,
&apos;[4]&apos;: &apos;bbbwww+&apos;,
&apos;[5]&apos;: &apos;bbwwww+&apos;,
&apos;[6]&apos;: &apos;bwwwww+&apos;,
&apos;[7]&apos;: &apos;wwwwww+&apos;,
&apos;[[1]]&apos;: &apos;wbbbbb+&apos;,
}
five = {
&apos;(5)&apos;: &apos;bbbbbb&apos;,
&apos;(6)&apos;: &apos;bbbbbw&apos;,
&apos;(7)&apos;: &apos;bbbbww&apos;,
&apos;1&apos;: &apos;bbbwww&apos;,
&apos;2&apos;: &apos;bbwwww&apos;,
&apos;3&apos;: &apos;bwwwww&apos;,
&apos;4&apos;: &apos;wbbwww&apos;,
&apos;5&apos;: &apos;wbbbbb+&apos;,
&apos;6&apos;: &apos;bbbbbw+&apos;,
&apos;7&apos;: &apos;bbbbww+&apos;,
&apos;[1]&apos;: &apos;bbbwww+&apos;,
&apos;[2]&apos;: &apos;bbwwww+&apos;,
&apos;[3]&apos;: &apos;bwwwww+&apos;,
&apos;[4]&apos;: &apos;hwwwww+&apos;,
&apos;[5]&apos;: &apos;wbbbbb+&apos;,
}
const c_h = &apos;◐&apos;
const c_b = &apos;●&apos;
const c_w = &apos;○&apos;
for (let k in one) {
one[k] = one[k].replaceAll(&apos;b&apos;, c_b).replaceAll(&apos;w&apos;, c_w)
if (one[k].length &amp;lt; 7) {
one[k] += &apos;  &apos;
}
}
for (let k in five) {
five[k] = five[k].replaceAll(&apos;b&apos;, c_b).replaceAll(&apos;w&apos;, c_w).replaceAll(&apos;h&apos;, c_h)
if (five[k].length &amp;lt; 7) {
five[k] += &apos;  &apos;
}
}
btn.onclick = function () {
updateContent()
updateTitle()
updateType()
}
function updateTitle() {
p_title.textContent = title.value
}
title.onchange = updateTitle
function updateType() {
p_type.textContent = type.options[type.selectedIndex].text
}
type.onchange = updateType;
function updateContent() {
let str = content.value.trim()
let arr = parse(str)
let html = gen(arr)
}
content.onchange = updateContent
function gen(arr) {
let ret = &apos;&apos;
for (let s of arr) {
if (s in normal) {
ret += normal[s]
continue
}
let current = type.value === &apos;1&apos; ? one : five;
if (s in current) {
ret += &lt;code&gt;&amp;lt;span class=&quot;l&quot;&amp;gt;${current[s]}&amp;lt;/span&amp;gt;&lt;/code&gt;
}
}
preview.innerHTML = ret;
}
function parse(str) {
let arr = [];
for (i = 0; i &amp;lt; str.length; i++) {
if (str[i] === &apos;[&apos;) {
if (str[i + 1] === &apos;[&apos;) {
arr.push(str.substr(i, 5));
i += 4;
continue;
}
arr.push(str.substr(i, 3));
i += 2;
continue;
}
if (str[i] === &apos;(&apos;) {
arr.push(str.substr(i, 3));
i += 2;
continue;
}
arr.push(str[i])
}
return arr;
}
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>网易云音乐工具[安卓]</title><link>https://from-env.com/posts/netease-tool</link><guid isPermaLink="true">https://from-env.com/posts/netease-tool</guid><description>网易云音乐工具</description><pubDate>Sat, 26 Oct 2024 02:10:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;meting-js id=&quot;2610226440&quot; type=&quot;song&quot; server=&quot;netease&quot; fixed=&quot;false&quot; mini=&quot;false&quot; autoplay=&quot;false&quot; theme=&quot;#255579&quot;&amp;gt;&amp;lt;/meting-js&amp;gt;&lt;/p&gt;
&lt;h2&gt;软件说明&lt;/h2&gt;
&lt;p&gt;开发这个软件的初衷，是因为笔者习惯在手机下载音乐，遇到了几个痛点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;网页版的NCM转换工具，不支持给音乐加上封面；&lt;/li&gt;
&lt;li&gt;从一些第三方音源下载下来的音乐文件没有标签，手动添加标签太麻烦。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;软件特性&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;把ncm里面的图片url下载内嵌到音乐标签，最后再导出音乐文件。只要选择一个文件夹 就将该目录下的所有ncm文件做处理，原地保存新文件。&lt;/li&gt;
&lt;li&gt;修改标签功能支持手动和半自动。半自动的意思是：先在APP打开歌曲的修改tag弹框，接着点击网易云音乐的分享歌曲链接按钮，然后回到APP，APP会自动监听剪贴板里的网址并自动解析（或者手动点击读取剪贴板按钮），一键填写标签和封面。&lt;/li&gt;
&lt;li&gt;在APP点开修改弹窗后会自动播放歌曲，这样在播放过程中就可以切到网易云音乐APP听歌识曲，通过识曲的结果定位音乐，从而得到分享链接。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;软件BUG&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;如果既通过剪贴板导入封面，又马上修改图片，可能出现图片不符合预期的情况。返回主界面，重新扫描 重新导入本地图片即可。&lt;/li&gt;
&lt;li&gt;ncm转换后的文件名，可能和原文件的文件名不一致。如果不一致，会重复生成如同(1) (2)的音乐文件。建议只生成一次 然后手动迁移或删除已处理的ncm文件。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;应用截图&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://bucket.armyja-online.uk/armyja/1729910567283.png&quot; alt=&quot;1729910567283.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://bucket.armyja-online.uk/armyja/1729910567334.jpg&quot; alt=&quot;1729910567334.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://bucket.armyja-online.uk/armyja/1729910567314.jpg&quot; alt=&quot;1729910567314.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://bucket.armyja-online.uk/armyja/1729910567297.jpg&quot; alt=&quot;1729910567297.jpg&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;下载方式&lt;/h2&gt;
&lt;p&gt;https://www.ilanzou.com/s/qdgys29f&lt;br /&gt;
提取码：orck&lt;br /&gt;
解压密码：52pojie&lt;/p&gt;
</content:encoded><author>Armyja</author></item><item><title>Windows WSL2 部署 OpenClaw 全攻略</title><link>https://from-env.com/posts/openclaw-wsl2-deployment</link><guid isPermaLink="true">https://from-env.com/posts/openclaw-wsl2-deployment</guid><description>详细介绍如何在 Windows WSL2 环境下部署和配置 OpenClaw AI 助手，并集成 Telegram 频道。</description><pubDate>Sun, 08 Feb 2026 13:40:00 GMT</pubDate><content:encoded>&lt;h2&gt;引言&lt;/h2&gt;
&lt;p&gt;在 Windows 环境下想要运行一个强大的 AI 助手，又不想放弃 Linux 的命令行体验？WSL2（Windows Subsystem for Linux 2）是最佳选择。本文将详细介绍如何在 WSL2 中部署 OpenClaw，并配置 Telegram 频道进行交互。&lt;/p&gt;
&lt;h2&gt;WSL2 环境准备&lt;/h2&gt;
&lt;h3&gt;1. 启用 WSL2 功能&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 以管理员身份运行 PowerShell
wsl --install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这会自动安装 Ubuntu（默认发行版）和 WSL2。安装完成后需要重启系统。&lt;/p&gt;
&lt;h3&gt;2. 解决 WSL 启动错误（踩坑 💥）&lt;/h3&gt;
&lt;p&gt;如果启动 WSL 时出现错误代码 &lt;code&gt;0xc03a0014&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Installing, this may take a few minutes...
WslRegisterDistribution failed with error: 0xc03a0014
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;解决方案：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;打开 Windows &lt;strong&gt;设备管理器&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;找到 &lt;strong&gt;Microsoft 虚拟驱动器枚举器&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;右键 → 启用设备&lt;/li&gt;
&lt;li&gt;重新进入 WSL，输入用户名和密码即表示成功&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;3. 更新系统&lt;/h3&gt;
&lt;p&gt;⚠️ &lt;strong&gt;重要：&lt;/strong&gt; WSL 里的基础软件默认装不了，必须先更新软件源！&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. 安装必要工具&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 安装 curl、git、nodejs 等
sudo apt install -y curl git wget build-essential
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. WSL 网络模式配置（踩坑 💥）&lt;/h3&gt;
&lt;p&gt;如果主机使用了 V2RayN 等代理软件，&lt;strong&gt;NAT 模式下 WSL 无法直接访问主机的代理&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决方案：启用镜像模式 + 自动代理&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;编辑 Windows 用户目录下的 &lt;code&gt;.wslconfig&lt;/code&gt; 文件（如果没有就创建）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# C:\Users\你的用户名\.wslconfig
[wsl2]
networkingMode=mirrored
autoProxy=true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后重启 WSL：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
# 重新打开 WSL 终端
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;效果：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WSL 可以直接使用主机 IP &lt;code&gt;127.0.0.1&lt;/code&gt; 访问代理&lt;/li&gt;
&lt;li&gt;Telegram 等需要代理的 channel 收发消息正常&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;安装 OpenClaw&lt;/h2&gt;
&lt;h3&gt;1. 使用 npm 全局安装&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo npm install -g openclaw
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 启动引导程序&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;openclaw onboard
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;引导程序会引导你完成以下配置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;工作区目录&lt;/strong&gt;：选择存放配置和文件的目录&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;模型配置&lt;/strong&gt;：配置 AI 模型提供商（如 MiniMax、OpenAI 等）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Telegram 集成&lt;/strong&gt;：配置 Telegram Bot Token&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 配置 Telegram Bot&lt;/h3&gt;
&lt;h4&gt;3.1 创建 Bot&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;在 Telegram 中搜索 &lt;code&gt;@BotFather&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;发送 &lt;code&gt;/newbot&lt;/code&gt; 创建新 Bot&lt;/li&gt;
&lt;li&gt;按照提示设置 Bot 名称和用户名&lt;/li&gt;
&lt;li&gt;获取 Bot Token&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;3.2 配置 OpenClaw&lt;/h4&gt;
&lt;p&gt;编辑配置文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nano ~/.openclaw/openclaw.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键配置项：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;channels&quot;: {
    &quot;telegram&quot;: {
      &quot;botToken&quot;: &quot;你的Bot Token&quot;,
      &quot;dmPolicy&quot;: &quot;pairing&quot;,
      &quot;groupPolicy&quot;: &quot;allowlist&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;3.3 配对用户&lt;/h4&gt;
&lt;p&gt;用户需要在 Telegram 中与 Bot 对话，然后管理员批准配对请求：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openclaw telegram pair
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;配置详解&lt;/h2&gt;
&lt;h3&gt;基础配置示例&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;agents&quot;: {
    &quot;defaults&quot;: {
      &quot;model&quot;: {
        &quot;primary&quot;: &quot;minimax-portal/MiniMax-M2.1&quot;
      },
      &quot;verboseDefault&quot;: &quot;on&quot;,
      &quot;workspace&quot;: &quot;/home/用户名/.openclaw/workspace&quot;
    }
  },
  &quot;commands&quot;: {
    &quot;bash&quot;: true
  },
  &quot;channels&quot;: {
    &quot;telegram&quot;: {
      &quot;dmPolicy&quot;: &quot;pairing&quot;,
      &quot;groupPolicy&quot;: &quot;allowlist&quot;,
      &quot;streamMode&quot;: &quot;partial&quot;,
      &quot;groups&quot;: {
        &quot;群ID&quot;: {
          &quot;requireMention&quot;: false,
          &quot;groupPolicy&quot;: &quot;open&quot;
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;命令配置&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;commands&quot;: {
    &quot;native&quot;: &quot;auto&quot;,
    &quot;nativeSkills&quot;: &quot;auto&quot;,
    &quot;bash&quot;: true
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;开启 &lt;code&gt;bash&lt;/code&gt; 命令后，可以在对话中直接执行 Shell 命令。&lt;/p&gt;
&lt;h2&gt;常用工具配置&lt;/h2&gt;
&lt;h3&gt;1. VS Code 连接 WSL（推荐）&lt;/h3&gt;
&lt;h4&gt;1.1 安装步骤&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;在 Windows 上安装 VS Code&lt;/strong&gt;（不是 WSL 里！）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下载地址：https://code.visualstudio.com/download&lt;/li&gt;
&lt;li&gt;安装时勾选 &lt;strong&gt;&quot;添加到 PATH&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安装远程开发扩展包&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;打开 VS Code&lt;/li&gt;
&lt;li&gt;按 &lt;code&gt;Ctrl+Shift+X&lt;/code&gt; 打开扩展面板&lt;/li&gt;
&lt;li&gt;搜索并安装 &lt;strong&gt;&quot;Remote - WSL&quot;&lt;/strong&gt;（属于 ms-vscode-remote 扩展包）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WSL 里先更新软件源&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;1.2 打开 WSL 项目&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;方式一：命令行（推荐）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /你的项目目录
code .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;方式二：VS Code 里连接&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; 打开命令面板&lt;/li&gt;
&lt;li&gt;输入 &lt;code&gt;WSL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;选择 &quot;WSL: Reopen Folder in WSL&quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;1.3 扩展安装注意事项&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;只需装一次&lt;/strong&gt;（主题、UI 扩展）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;需要单独装&lt;/strong&gt;（Python、调试器、linting 等）- 在 WSL 里装&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;⚠️ 如果 WSL 里没装扩展，VS Code 会显示 ⚠️ 图标，点击 &quot;在 WSL 中安装&quot; 即可。&lt;/p&gt;
&lt;h3&gt;安装 GitHub CLI&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install gh -y
gh auth login --web
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;OpenClaw 高级配置&lt;/h2&gt;
&lt;h3&gt;1. 配置系统代理（踩坑 💥）&lt;/h3&gt;
&lt;p&gt;如果使用了 V2RayN 等代理软件，需要让 OpenClaw Gateway 服务使用代理，否则 Telegram 无法收发消息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方案一：编辑 systemd 服务文件&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl edit openclaw-gateway.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加以下内容：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Service]
Environment=&quot;HTTP_PROXY=http://127.0.0.1:代理端口&quot;
Environment=&quot;HTTPS_PROXY=http://127.0.0.1:代理端口&quot;
Environment=&quot;ALL_PROXY=http://127.0.0.1:代理端口&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;方案二：直接编辑服务文件&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/systemd/system/openclaw-gateway.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 &lt;code&gt;[Service]&lt;/code&gt; 段落下添加：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Environment=&quot;HTTP_PROXY=http://127.0.0.1:端口&quot;
Environment=&quot;HTTPS_PROXY=http://127.0.0.1:端口&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;重启服务使配置生效：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl restart openclaw-gateway.service
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 验证代理是否生效&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 查看服务环境变量
sudo systemctl show openclaw-gateway.service | grep Environment=
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Telegram 群聊配置&lt;/h3&gt;
&lt;p&gt;在群聊中无需 @ 提及即可自动回复：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;channels&quot;: {
    &quot;telegram&quot;: {
      &quot;groupAllowFrom&quot;: [&quot;*&quot;],
      &quot;groups&quot;: {
        &quot;-100123456789&quot;: {
          &quot;requireMention&quot;: false,
          &quot;groupPolicy&quot;: &quot;open&quot;
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;内存搜索&lt;/h3&gt;
&lt;p&gt;启用长期记忆功能：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;agents&quot;: {
    &quot;defaults&quot;: {
      &quot;memorySearch&quot;: {
        &quot;enabled&quot;: true,
        &quot;sources&quot;: [&quot;memory&quot;, &quot;sessions&quot;]
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;测试与使用&lt;/h2&gt;
&lt;h3&gt;1. 启动 OpenClaw&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;openclaw
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Telegram 交互&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;私聊&lt;/strong&gt;：直接发送消息&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;群聊&lt;/strong&gt;：无需 @ 提及（配置后）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;命令&lt;/strong&gt;：使用 &lt;code&gt;/help&lt;/code&gt; 获取帮助&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 常用命令&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 查看状态
openclaw status

# 重启服务
openclaw restart

# 查看日志
openclaw logs
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常见问题&lt;/h2&gt;
&lt;h3&gt;Q1: WSL2 与 Windows 文件互通&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 在 WSL 中访问 Windows 文件
cd /mnt/c/Users/你的用户名/

# 将 WSL 项目链接到 Windows 桌面
ln -s ~/.openclaw/workspace /mnt/c/Users/你的用户名/Desktop/openclaw
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Q2: 代理配置&lt;/h3&gt;
&lt;p&gt;如果需要代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export HTTP_PROXY=&quot;http://代理地址:端口&quot;
export HTTPS_PROXY=&quot;http://代理地址:端口&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Q3: Telegram 连接问题&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;检查 Bot Token 是否正确&lt;/li&gt;
&lt;li&gt;确认网络可以访问 Telegram API&lt;/li&gt;
&lt;li&gt;检查 &lt;code&gt;dmPolicy&lt;/code&gt; 和 &lt;code&gt;groupPolicy&lt;/code&gt; 配置&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;通过 WSL2，我们可以在 Windows 上享受完整的 Linux 开发和运维体验，同时通过 OpenClaw 获得强大的 AI 助手能力。配合 Telegram 频道，可以实现随时随地的智能交互。&lt;/p&gt;
&lt;h2&gt;参考资源&lt;/h2&gt;
&lt;h3&gt;OpenClaw 官方资源&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openclaw.ai&quot;&gt;OpenClaw 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openclaw/openclaw&quot;&gt;OpenClaw GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;WSL2 官方文档&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/windows/wsl&quot;&gt;WSL2 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.csdn.net/m0_52329284/article/details/147005298&quot;&gt;WSL 启动错误 0xc03a0014 解决方案&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/zh-cn/windows/wsl/networking&quot;&gt;WSL 网络配置（NAT/镜像模式）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/zh-cn/windows/wsl/tutorials/wsl-vscode&quot;&gt;VS Code 连接 WSL 教程&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><author>Armyja</author></item><item><title>拼图任务的价值：为什么AI无法完美拼图？</title><link>https://from-env.com/posts/ai-puzzle-np-complete</link><guid isPermaLink="true">https://from-env.com/posts/ai-puzzle-np-complete</guid><description>从拼图任务出发，探讨视觉大模型的空间推理能力，以及NP完全问题与AI能力的深层关系</description><pubDate>Tue, 17 Feb 2026 15:17:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;这是一篇与 Kimi AI 探讨拼图任务价值的对话记录整理。通过这个看似简单的问题，我们触及了视觉大模型的核心局限、计算复杂性理论的本质，乃至于AI能力的边界。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;问题的起点：视觉大模型能否完成拼图？&lt;/h2&gt;
&lt;p&gt;一切起源于这个看似简单的问题：现在的视觉大模型可以完成拼拼图的任务吗？为什么现在的顶尖测试都没有把拼拼图列进去呢？是太简单了还是太难了呢？&lt;/p&gt;
&lt;p&gt;这确实是一个非常敏锐的观察。当我们谈论视觉语言模型（VLM）的能力时，往往关注的是图像分类、目标检测、视觉问答（VQA）等任务，却很少听到有人提及&quot;拼图&quot;这个看似基础的能力。&lt;/p&gt;
&lt;h3&gt;空间推理是公认的短板&lt;/h3&gt;
&lt;p&gt;多项2024-2025年的研究一致表明，空间推理是VLMs的系统性弱点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;基础空间关系识别困难&lt;/strong&gt;：在What&apos;sUp基准测试中，18个主流VLM（包括BLIP、CLIP、LLaVA等）在区分&quot;左/右&quot;、&quot;上/下&quot;等基本空间关系时，准确率仅56%，而人类达到99%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;心理旋转能力薄弱&lt;/strong&gt;：SpatialEval基准显示，VLMs在物体旋转、折叠等任务上经常表现不如随机猜测&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺乏真正的空间理解&lt;/strong&gt;：模型往往依赖语言先验（如&quot;杯子通常在桌子上&quot;）而非视觉分析来做判断&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;拼图任务的特殊挑战&lt;/h3&gt;
&lt;p&gt;拼图任务对VLMs来说既不太简单，也不仅仅是难，而是涉及多重能力缺陷：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;拼图所需能力&lt;/th&gt;
&lt;th&gt;VLM现状&lt;/th&gt;
&lt;th&gt;具体困难&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;边缘匹配&lt;/td&gt;
&lt;td&gt;❌ 极弱&lt;/td&gt;
&lt;td&gt;无法精确比对形状轮廓的连续性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;纹理/图案衔接&lt;/td&gt;
&lt;td&gt;⚠️ 中等&lt;/td&gt;
&lt;td&gt;可以识别图案，但难以判断&quot;是否对齐&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;全局空间布局&lt;/td&gt;
&lt;td&gt;❌ 弱&lt;/td&gt;
&lt;td&gt;缺乏整体构图的3D理解&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;旋转对齐&lt;/td&gt;
&lt;td&gt;❌ 极弱&lt;/td&gt;
&lt;td&gt;心理旋转任务表现差&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;试错与回溯&lt;/td&gt;
&lt;td&gt;❌ 弱&lt;/td&gt;
&lt;td&gt;长程规划能力不足&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最新的研究（2025年3月）指出，VLMs存在&lt;strong&gt;语义-几何错位&lt;/strong&gt;（semantic-geometric misalignment）问题——模型能识别物体，但无法建立一致的3D空间表征。这正是拼图任务的核心要求。&lt;/p&gt;
&lt;h2&gt;为什么顶尖测试不包含拼图？&lt;/h2&gt;
&lt;p&gt;主流基准（如MMMU、MMBench、SEED-Bench等）没有将拼图列为评测项，不是因为太简单，而是因为：&lt;/p&gt;
&lt;h3&gt;1. 任务设计层面的&quot;不公平性&quot;&lt;/h3&gt;
&lt;p&gt;拼图是一种&lt;strong&gt;低语义、高几何&lt;/strong&gt;的任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主流VLM架构（CLIP-like）本质上是语义对齐的——将图像映射到语言概念空间&lt;/li&gt;
&lt;li&gt;拼图需要的纯几何匹配与当前训练目标（图像-文本对比学习）脱节&lt;/li&gt;
&lt;li&gt;测试拼图会被批评为&quot;架构偏见&quot;而非&quot;能力缺陷&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 评测的可操作性难题&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;答案格式不标准化&lt;/strong&gt;：拼图结果是一个空间排列，难以像VQA那样自动评分&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;难度梯度难以控制&lt;/strong&gt;：3片 vs 300片拼图是完全不同的复杂度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;与核心能力关联性争议&lt;/strong&gt;：拼图能力是否反映&quot;智能&quot;存在学术争议&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 更根本的原因：空间推理评测已被&quot;分解&quot;&lt;/h3&gt;
&lt;p&gt;学术界不是不关注拼图类能力，而是将其拆解为更基础的子任务分别测试：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SpatialEval&lt;/strong&gt;：测试关系推理、导航、心理旋转、物体计数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SRBench&lt;/strong&gt;：涵盖空间关系、方向导航、心理旋转、空间可视化&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What&apos;sUp&lt;/strong&gt;：严格控制的物体位置关系识别&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VSI-Bench&lt;/strong&gt;：视频空间推理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些基准比传统拼图更严格地测试空间认知，且避免了拼图任务的工程复杂性。&lt;/p&gt;
&lt;h2&gt;拼图的经济价值与战略意义&lt;/h2&gt;
&lt;p&gt;你的追问触及了AI研发中一个核心的战略选择问题。&lt;/p&gt;
&lt;h3&gt;拼图作为任务的&quot;死亡&quot;，拼图作为能力的&quot;重生&quot;&lt;/h3&gt;
&lt;p&gt;传统拼图（把碎片拼成完整图片）确实在消退，但拼图背后的空间推理能力正成为万亿级市场的核心：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;市场领域&lt;/th&gt;
&lt;th&gt;2025-2030年规模&lt;/th&gt;
&lt;th&gt;核心能力需求与拼图的关系&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;具身智能（Embodied AI）&lt;/td&gt;
&lt;td&gt;$230.6亿（CAGR 39%）&lt;/td&gt;
&lt;td&gt;实时空间导航、物体操作——拼图=静态版机器人操作&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;视觉语言模型（VLM）&lt;/td&gt;
&lt;td&gt;$417.5亿（CAGR 26.95%）&lt;/td&gt;
&lt;td&gt;视觉-语言-行动（VLA）对齐——拼图=空间理解的基础测试&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;工业质检&lt;/td&gt;
&lt;td&gt;缺陷减少30%，效率提升20%&lt;/td&gt;
&lt;td&gt;微观对齐、模式匹配——拼图=宏观版边缘匹配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空间计算/数字孪生&lt;/td&gt;
&lt;td&gt;高速增长&lt;/td&gt;
&lt;td&gt;3D环境理解——拼图=简化版场景重建&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;关键洞察：&lt;strong&gt;拼图任务本身没有商业价值，但拼图所要求的&quot;几何-语义对齐&quot;能力正在制造、物流、医疗等领域创造数百亿美元的增量价值。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;为什么基准测试&quot;回避&quot;拼图？——技术路线的分歧&lt;/h3&gt;
&lt;p&gt;主流基准不测试拼图，不是因为没价值，而是因为拼图暴露了当前架构的根本局限：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;当前VLM的&quot;作弊&quot;能力&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在VQA任务中，模型可以通过语言先验（&quot;天空在上方&quot;）回答空间问题&lt;/li&gt;
&lt;li&gt;在拼图任务中，这种作弊完全失效——必须真正理解几何关系&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;学术界的&quot;鸵鸟策略&quot;&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;测试拼图 = 承认当前架构（CLIP+LLM）存在不可修复的缺陷&lt;/li&gt;
&lt;li&gt;这会导致投资信心下降（VLM市场正在爆发期）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，不是拼图不重要，而是测试拼图会打断商业叙事。&lt;/p&gt;
&lt;h2&gt;视频生成与拼图的深层联系&lt;/h2&gt;
&lt;p&gt;你的观察非常敏锐——视频生成中的&quot;不合情理&quot;确实与拼图能力共享同一个底层缺陷。&lt;/p&gt;
&lt;h3&gt;视频生成的&quot;幻觉&quot;与拼图的同源性&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 共同的失败模式：几何-语义错位&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当前视频生成模型（Sora、Runway、Pika等）的&quot;不合情理&quot;现象，与VLM在拼图任务上的失败共享同一个根源：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;视频生成中的问题&lt;/th&gt;
&lt;th&gt;拼图任务中的对应&lt;/th&gt;
&lt;th&gt;共同根源&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;物体变形/闪烁（如手突然多手指）&lt;/td&gt;
&lt;td&gt;碎片边缘无法对齐&lt;/td&gt;
&lt;td&gt;缺乏精确的几何约束&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;物理违反（如穿墙、反重力）&lt;/td&gt;
&lt;td&gt;强迫不匹配的碎片拼接&lt;/td&gt;
&lt;td&gt;缺乏物理先验的显式建模&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;时序不一致（人物服装突然变色）&lt;/td&gt;
&lt;td&gt;图案纹理不连续&lt;/td&gt;
&lt;td&gt;跨帧/跨碎片对应关系学习不足&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;镜面反射错误&lt;/td&gt;
&lt;td&gt;无法处理对称/重复图案&lt;/td&gt;
&lt;td&gt;缺乏多视角一致性理解&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;2. 架构层面的同构性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;视频生成和拼图任务在技术上高度同源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;视频生成 = 时序维度上的&quot;拼图&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每一帧是一个&quot;碎片&quot;&lt;/li&gt;
&lt;li&gt;时序一致性 = 边缘匹配&lt;/li&gt;
&lt;li&gt;长程依赖 = 全局布局&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;拼图 = 空间维度上的&quot;视频生成&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个碎片是一帧&quot;关键帧&quot;&lt;/li&gt;
&lt;li&gt;边缘匹配 = 帧间一致性&lt;/li&gt;
&lt;li&gt;完整图像 = 视频序列&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;为什么视频生成&quot;看起来&quot;更成功？&lt;/h3&gt;
&lt;p&gt;关键区别：&lt;strong&gt;容错率与幻觉容忍度&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;拼图任务&lt;/th&gt;
&lt;th&gt;视频生成&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;错误可见性&lt;/td&gt;
&lt;td&gt;极高（错位一目了然）&lt;/td&gt;
&lt;td&gt;中等（人眼对时序不一致有容忍度）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;评估标准&lt;/td&gt;
&lt;td&gt;精确几何匹配（硬约束）&lt;/td&gt;
&lt;td&gt;感知合理性（软约束）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;幻觉空间&lt;/td&gt;
&lt;td&gt;极小（必须严丝合缝）&lt;/td&gt;
&lt;td&gt;较大（只要&quot;看起来像&quot;即可）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;商业应用&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;td&gt;极高&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这就是为什么视频生成可以&quot;作弊&quot;——它不需要真正的3D理解，只需要统计上的时序平滑，而拼图无法作弊——要么对齐，要么不对齐。&lt;/p&gt;
&lt;h2&gt;解决了视频生成，拼图更容易？&lt;/h2&gt;
&lt;p&gt;这是一个非常反直觉的问题。&lt;strong&gt;恰恰相反：视频生成更容易，拼图更难。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;核心悖论：维度与约束的权衡&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;视频生成&lt;/th&gt;
&lt;th&gt;拼图&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;信息丰富度&lt;/td&gt;
&lt;td&gt;高（时序连续性提供线索）&lt;/td&gt;
&lt;td&gt;低（静态碎片，无上下文）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;约束类型&lt;/td&gt;
&lt;td&gt;软约束（统计平滑即可）&lt;/td&gt;
&lt;td&gt;硬约束（必须精确匹配）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;容错空间&lt;/td&gt;
&lt;td&gt;大（微小错位人眼难察觉）&lt;/td&gt;
&lt;td&gt;零（错位即失败）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;评估标准&lt;/td&gt;
&lt;td&gt;主观（&quot;看起来对&quot;）&lt;/td&gt;
&lt;td&gt;客观（&quot;确实对齐&quot;）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;为什么视频生成&quot;解决&quot;了，拼图反而更难？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 视频生成的&quot;作弊&quot;本质&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当前视频模型依赖的是统计平滑，而非几何理解：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;视频生成的成功公式：
海量数据 + 扩散模型 + 时序注意力 = &quot;看起来像真的&quot;

拼图需要的公式：
几何约束求解 + 全局优化 + 精确边缘匹配 = &quot;确实是对的&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2. 拼图是&quot;纯几何&quot;任务，剥离了所有语义拐杖&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当前VLM的强项是语义-视觉对齐（&quot;这是猫&quot;），弱项是纯几何推理（&quot;这两块边缘曲率一致&quot;）。&lt;/p&gt;
&lt;p&gt;拼图恰好是去语义化的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你不能说&quot;这是天空碎片，应该放上面&quot;（语义捷径）&lt;/li&gt;
&lt;li&gt;你必须说&quot;这块边缘的曲率是y=0.3x²，与那块匹配&quot;（几何硬算）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这正是为什么VLM在What&apos;sUp基准（空间关系识别）只有56%准确率，而人类99%——&lt;strong&gt;几何推理与语言理解是不同的认知模块。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 视频生成的&quot;解决方案&quot;不迁移到拼图&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2024-2025年视频生成的突破确实引入了3D约束，但这些方法：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;视频生成方法&lt;/th&gt;
&lt;th&gt;拼图适用性&lt;/th&gt;
&lt;th&gt;原因&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;时序一致性损失&lt;/td&gt;
&lt;td&gt;❌ 不适用&lt;/td&gt;
&lt;td&gt;拼图无时间维度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多帧光流约束&lt;/td&gt;
&lt;td&gt;❌ 不适用&lt;/td&gt;
&lt;td&gt;单张静态图像&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3D高斯溅射&lt;/td&gt;
&lt;td&gt;⚠️ 部分适用&lt;/td&gt;
&lt;td&gt;需多视角，拼图只有单视角&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;物理引擎约束&lt;/td&gt;
&lt;td&gt;❌ 不适用&lt;/td&gt;
&lt;td&gt;拼图是2D几何，非物理模拟&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;视频生成解决的是&quot;时序连贯性&quot;，拼图需要的是&quot;空间精确性&quot;——两者正交。&lt;/p&gt;
&lt;h3&gt;更深层的认知科学视角&lt;/h3&gt;
&lt;p&gt;你的问题假设了一个线性进步模型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;解决视频生成（难） → 拼图（易）自然解决
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但实际情况是&lt;strong&gt;能力解耦&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;人类认知：
视觉理解 ─┬─→ 语义识别（这是什么）
         └─→ 几何推理（这在哪里、如何旋转）

当前AI：
视觉理解 ─┬─→ 语义识别 ✅（CLIP、DINO很强）
         └─→ 几何推理 ❌（仍是盲区）
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;计算机能否完美解决拼图问题？&lt;/h2&gt;
&lt;p&gt;这是一个触及计算本质的问题。&lt;/p&gt;
&lt;h3&gt;理论答案：不能（在一般情况下）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心结论：拼图是NP完全问题&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;根据MIT、斯坦福等机构的最新理论研究：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;定理（Demaine et al., 2025）：即使是最简单的拼图变体——1×n的边匹配拼图（edge-matching puzzle）——也是强NP完全的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这意味着：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;没有已知的多项式时间算法能在所有情况下完美求解&lt;/li&gt;
&lt;li&gt;如果P ≠ NP（计算机科学最核心的未解猜想），那么不存在高效精确算法&lt;/li&gt;
&lt;li&gt;即使允许近似解，近似到0.999999762以内也是NP难的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;为什么NP完全性如此致命？&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题规模&lt;/th&gt;
&lt;th&gt;穷举搜索时间&lt;/th&gt;
&lt;th&gt;实际意义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10片&lt;/td&gt;
&lt;td&gt;10! × 4^10 ≈ 1.2亿种&lt;/td&gt;
&lt;td&gt;计算机可处理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25片&lt;/td&gt;
&lt;td&gt;25! × 4^25 ≈ 10^40种&lt;/td&gt;
&lt;td&gt;超过宇宙原子数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100片&lt;/td&gt;
&lt;td&gt;100! × 4^100 ≈ 10^200种&lt;/td&gt;
&lt;td&gt;绝对不可解&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;实践答案：可以（在特定条件下）&lt;/h3&gt;
&lt;p&gt;虽然理论上是NP完全的，但实际算法在受限场景下表现良好：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方法&lt;/th&gt;
&lt;th&gt;适用场景&lt;/th&gt;
&lt;th&gt;成功率&lt;/th&gt;
&lt;th&gt;关键限制&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenCV传统算法&lt;/td&gt;
&lt;td&gt;方形、规则边缘、25片以下&lt;/td&gt;
&lt;td&gt;80-95%&lt;/td&gt;
&lt;td&gt;需要特定摄影条件、背景对比度高&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;深度学习+形状匹配&lt;/td&gt;
&lt;td&gt;标准拼图、已知模板&lt;/td&gt;
&lt;td&gt;90%+&lt;/td&gt;
&lt;td&gt;依赖参考图像（hint）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;纯几何求解&lt;/td&gt;
&lt;td&gt;无提示、仅边缘形状&lt;/td&gt;
&lt;td&gt;60-80%&lt;/td&gt;
&lt;td&gt;对噪声敏感、无法处理模糊匹配&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;三种&quot;完美&quot;的定义&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;完美级别&lt;/th&gt;
&lt;th&gt;定义&lt;/th&gt;
&lt;th&gt;可实现性&lt;/th&gt;
&lt;th&gt;技术路线&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;L0：理论完美&lt;/td&gt;
&lt;td&gt;对所有可能的拼图输入都正确&lt;/td&gt;
&lt;td&gt;❌ 不可实现（除非P=NP）&lt;/td&gt;
&lt;td&gt;需要指数时间算法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L1：工程完美&lt;/td&gt;
&lt;td&gt;对真实世界拼图（有唯一解、标准形状）100%正确&lt;/td&gt;
&lt;td&gt;⚠️ 接近可实现&lt;/td&gt;
&lt;td&gt;深度学习+约束求解+传感器融合&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2：感知完美&lt;/td&gt;
&lt;td&gt;人类无法察觉错误&lt;/td&gt;
&lt;td&gt;✅ 已实现&lt;/td&gt;
&lt;td&gt;当前商业软件可达到&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;NP完全问题到底是什么？&lt;/h2&gt;
&lt;h3&gt;通俗定义（用拼图解释）&lt;/h3&gt;
&lt;p&gt;想象你在解决一个1000片的拼图：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题类型&lt;/th&gt;
&lt;th&gt;定义&lt;/th&gt;
&lt;th&gt;拼图对应&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;P问题&lt;/td&gt;
&lt;td&gt;能快速解决的问题&lt;/td&gt;
&lt;td&gt;验证拼图是否完成（看一眼就知道）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NP问题&lt;/td&gt;
&lt;td&gt;能快速验证解的问题&lt;/td&gt;
&lt;td&gt;有人给你拼好的图，你能快速检查对错&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NP完全问题&lt;/td&gt;
&lt;td&gt;所有NP问题都能归约到它&lt;/td&gt;
&lt;td&gt;找到拼图的解法&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;核心悖论：&lt;strong&gt;验证容易，求解困难&lt;/strong&gt;。如果你有一个拼好的拼图，很容易验证它是否正确。但如果没有参考图，自己拼出来就极其困难。&lt;/p&gt;
&lt;h3&gt;形式化定义&lt;/h3&gt;
&lt;p&gt;一个问题是NP完全的，当且仅当：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;属于NP：解可在多项式时间内验证&lt;/li&gt;
&lt;li&gt;NP-hard：所有NP问题都能归约到它（多项式时间转换）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关键性质：&lt;strong&gt;如果任何一个NP完全问题有多项式时间算法，那么所有NP问题都有，即P=NP&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;围棋 vs 拼图：谁更难？&lt;/h2&gt;
&lt;h3&gt;复杂度层级对比&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;复杂度类&lt;/th&gt;
&lt;th&gt;难度定位&lt;/th&gt;
&lt;th&gt;关键特征&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;拼图（边匹配）&lt;/td&gt;
&lt;td&gt;NP完全&lt;/td&gt;
&lt;td&gt;极难，但可验证&lt;/td&gt;
&lt;td&gt;解存在时，验证快；搜索空间大&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;围棋（日式规则）&lt;/td&gt;
&lt;td&gt;EXPTIME完全&lt;/td&gt;
&lt;td&gt;更难&lt;/td&gt;
&lt;td&gt;需要指数时间，且需要指数空间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;围棋（中式规则）&lt;/td&gt;
&lt;td&gt;猜想：EXPSPACE完全&lt;/td&gt;
&lt;td&gt;极难&lt;/td&gt;
&lt;td&gt;可能需指数空间&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;为什么围棋比拼图&quot;更难&quot;？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 交互性 vs 静态性&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;拼图&lt;/th&gt;
&lt;th&gt;围棋&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;信息完全性&lt;/td&gt;
&lt;td&gt;完全信息（所有碎片可见）&lt;/td&gt;
&lt;td&gt;不完全信息（对手策略未知）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;动态性&lt;/td&gt;
&lt;td&gt;静态（一次性求解）&lt;/td&gt;
&lt;td&gt;动态（双方交替，路径爆炸）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;解的长度&lt;/td&gt;
&lt;td&gt;固定（拼好即可）&lt;/td&gt;
&lt;td&gt;不固定（可能无限对弈）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;验证方式&lt;/td&gt;
&lt;td&gt;几何匹配&lt;/td&gt;
&lt;td&gt;胜负判断需模拟至终局&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;2. 计算复杂度的本质差异&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;拼图 = 组合优化问题
     = &quot;找到满足所有约束的排列&quot;
     → NP完全（验证解容易）

围棋 = 博弈树搜索问题
     = &quot;在对手干扰下找到必胜策略&quot;
     → EXPTIME完全（验证策略本身需要指数时间）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键区别：拼图的解是一个静态配置，验证只需检查边缘匹配；围棋的解是一个策略（函数），验证需要模拟所有可能的对手应对，这可能需要指数时间。&lt;/p&gt;
&lt;h3&gt;为什么AlphaGo能击败人类，但拼图算法不完美？&lt;/h3&gt;
&lt;p&gt;这是一个深刻的反差：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;领域&lt;/th&gt;
&lt;th&gt;人类水平&lt;/th&gt;
&lt;th&gt;AI水平&lt;/th&gt;
&lt;th&gt;原因&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;围棋&lt;/td&gt;
&lt;td&gt;职业九段&lt;/td&gt;
&lt;td&gt;超越人类（AlphaGo）&lt;/td&gt;
&lt;td&gt;虽理论EXPTIME难，但启发式搜索+深度学习可有效逼近&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;拼图&lt;/td&gt;
&lt;td&gt;轻松完成&lt;/td&gt;
&lt;td&gt;不完美（尤其无提示时）&lt;/td&gt;
&lt;td&gt;NP完全问题的组合爆炸更难以启发式规避&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;悖论解释&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;围棋虽复杂度更高，但具有结构化启发式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;局部模式（定式）可学习&lt;/li&gt;
&lt;li&gt;价值函数可近似（神经网络评估局面）&lt;/li&gt;
&lt;li&gt;蒙特卡洛树搜索可剪枝&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;拼图虽&quot;仅&quot;NP完全，但缺乏有效启发式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;边缘匹配是硬约束（要么对，要么错，无中间状态）&lt;/li&gt;
&lt;li&gt;局部决策（两片是否匹配）无法独立评估（需全局一致性）&lt;/li&gt;
&lt;li&gt;深度学习学到的是统计相关性，而非几何精确性&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;核心洞察：复杂度 ≠ 实际难度&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;复杂度类&lt;/th&gt;
&lt;th&gt;典型问题&lt;/th&gt;
&lt;th&gt;实际求解难度&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;P&lt;/td&gt;
&lt;td&gt;排序、最短路径&lt;/td&gt;
&lt;td&gt;容易&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NP完全&lt;/td&gt;
&lt;td&gt;拼图、SAT、旅行商&lt;/td&gt;
&lt;td&gt;启发式可处理中等规模&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PSPACE完全&lt;/td&gt;
&lt;td&gt;广义象棋（n×n棋盘）&lt;/td&gt;
&lt;td&gt;更难，但有限内存可处理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPTIME完全&lt;/td&gt;
&lt;td&gt;围棋（标准19×19）&lt;/td&gt;
&lt;td&gt;理论极难，但特定规模可被AI攻克&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPSPACE完全&lt;/td&gt;
&lt;td&gt;围棋（中式规则，理论上）&lt;/td&gt;
&lt;td&gt;几乎不可解&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;关键结论：围棋的EXPTIME完全性是针对&quot;任意大棋盘&quot;的渐近结论。对于固定的19×19棋盘，实际复杂度被常数因子限制，使得深度学习+大规模计算可逼近最优解。拼图的NP完全性则意味着：即使对于固定规模（如100片），只要碎片形状足够复杂，就不存在通用高效算法。&lt;/p&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;复杂度&lt;/th&gt;
&lt;th&gt;核心难点&lt;/th&gt;
&lt;th&gt;AI现状&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;拼图&lt;/td&gt;
&lt;td&gt;NP完全&lt;/td&gt;
&lt;td&gt;组合爆炸、硬几何约束&lt;/td&gt;
&lt;td&gt;不完美（尤其无提示）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;围棋&lt;/td&gt;
&lt;td&gt;EXPTIME完全&lt;/td&gt;
&lt;td&gt;博弈树深度、对手不确定性&lt;/td&gt;
&lt;td&gt;超越人类（特定规模）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;你的直觉需要反转：&lt;strong&gt;围棋虽理论复杂度更高，但其结构化特性使深度学习有效；拼图虽&quot;仅&quot;NP完全，但其纯组合本质和硬约束使当前AI难以完美求解。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这也是为什么拼图仍是计算复杂性理论的经典案例，而围棋已成为AI工程的胜利——&lt;strong&gt;理论难度与实际可解性并不总是一致的。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;最终答案&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;在理论上&lt;/strong&gt;：不能（除非P=NP，这将颠覆整个计算机科学基础）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在工程上&lt;/strong&gt;：可以接近（对标准拼图达到99%+成功率，但无法保证100%）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在哲学上&lt;/strong&gt;：这揭示了计算复杂性与人类直觉的深刻差异——人类解决拼图依赖模式识别和物理直觉（&quot;这块感觉应该在这里&quot;），而计算机被限制在离散组合搜索的框架中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;拼图问题之所以重要，正是因为它是NP完全问题的物理化身&lt;/strong&gt;——谁能高效解决它，谁就能解决蛋白质折叠、密码破解、物流优化等无数实际问题。这也是为什么Eternity II拼图（256片边匹配）曾悬赏200万美元，至今未被完全解决。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;拼图只是表象，几何-语义对齐才是核心战场。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><author>Armyja</author></item></channel></rss>