<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://sukima-ml.club/blog</id>
    <title>隙间月影 | Sukima Moonlight Blog</title>
    <updated>2025-12-16T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://sukima-ml.club/blog"/>
    <subtitle>隙间月影 | Sukima Moonlight Blog</subtitle>
    <icon>https://sukima-ml.club/img/favicon.svg</icon>
    <entry>
        <title type="html"><![CDATA[揭秘“东方Project角色人格测试”背后的算法原理]]></title>
        <id>https://sukima-ml.club/blog/touhou-personality-test-analysis</id>
        <link href="https://sukima-ml.club/blog/touhou-personality-test-analysis"/>
        <updated>2025-12-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[今天，“测测你是哪个东方人物”的小测试在Q群刷屏。作为一位光荣的计算机系学生/东方同人社团主催，我不禁好奇：这个测试到底是如何运作的？它是真的通过基础的机器学习算法来匹配角色，还是仅仅通过简单的条件判断？我直觉上的“六维向量”匹配是否确有其事？]]></summary>
        <content type="html"><![CDATA[<p>今天，“测测你是哪个东方人物”的小测试在Q群刷屏。作为一位光荣的计算机系学生/东方同人社团主催，我不禁好奇：这个测试到底是如何运作的？它是真的通过基础的机器学习算法来匹配角色，还是仅仅通过简单的条件判断？我直觉上的“六维向量”匹配是否确有其事？</p>
<p>为了解开这个谜题，我分析了该网页的源代码。在这篇文章中，我将带大家深入代码底层，看看你的“本命角色”究竟是如何被算出来的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="核心发现六维并不只是向量">核心发现：六维并不只是向量<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#%E6%A0%B8%E5%BF%83%E5%8F%91%E7%8E%B0%E5%85%AD%E7%BB%B4%E5%B9%B6%E4%B8%8D%E5%8F%AA%E6%98%AF%E5%90%91%E9%87%8F" class="hash-link" aria-label="核心发现：六维并不只是向量的直接链接" title="核心发现：六维并不只是向量的直接链接" translate="no">​</a></h2>
<p>经过对网页源码（主要是 <code>index-*.js</code> 文件）的逆向分析，我发现该测试确实基于一个<strong>六维人格模型</strong>。与我们熟知的 MBTI（四维）类似，这个测试引入了额外的两个维度，构建了一个更复杂的分类系统。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-十二个子维度与六大轴线">1. 十二个子维度与六大轴线<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#1-%E5%8D%81%E4%BA%8C%E4%B8%AA%E5%AD%90%E7%BB%B4%E5%BA%A6%E4%B8%8E%E5%85%AD%E5%A4%A7%E8%BD%B4%E7%BA%BF" class="hash-link" aria-label="1. 十二个子维度与六大轴线的直接链接" title="1. 十二个子维度与六大轴线的直接链接" translate="no">​</a></h3>
<p>代码中定义了 12 个基础维度，它们两两相对，构成了 6 个核心人格轴线。代码片段如下：</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 代码中的维度定义映射</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> dimensions </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">code</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"外向"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">opposite</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"i"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">oppositeName</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"内向"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">code</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"n"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"理想"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">opposite</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">oppositeName</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"实用"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">code</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"t"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"逻辑"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">opposite</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">oppositeName</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"感性"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">code</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"p"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"应变"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">opposite</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"j"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">oppositeName</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"规划"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">code</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"a"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"怀疑"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">opposite</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"o"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">oppositeName</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"包容"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// A vs O</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">code</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"h"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"进取"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">opposite</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">oppositeName</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"守旧"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// H vs C</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>这六对对抗特质分别是：</p>
<ol>
<li class=""><strong>E (外向) vs I (内向)</strong>：经典的外倾/内倾维度。</li>
<li class=""><strong>N (理想) vs S (实用)</strong>：类似 MBTI 的直觉/实感。</li>
<li class=""><strong>T (逻辑) vs F (感性)</strong>：思考/情感。</li>
<li class=""><strong>P (应变) vs J (规划)</strong>：感知/判断。</li>
<li class=""><strong>A (怀疑) vs O (包容)</strong>：这是一个独特的维度，可能对应大五人格中的宜人性或神经质的变体。</li>
<li class=""><strong>H (进取) vs C (守旧)</strong>：衡量对新事物的态度，可能对应开放性。</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-积分算法">2. 积分算法<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#2-%E7%A7%AF%E5%88%86%E7%AE%97%E6%B3%95" class="hash-link" aria-label="2. 积分算法的直接链接" title="2. 积分算法的直接链接" translate="no">​</a></h3>
<p>测试题目包含若干道问题，每道问题都对应上述 12 个子维度中的某一个。当你选择 A/B/C/D 选项时，会分别为该维度增加 1 到 4 分。</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 伪代码还原的积分逻辑</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> scores </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">e</span><span class="token operator" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">i</span><span class="token operator" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">n</span><span class="token operator" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">s</span><span class="token operator" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 初始化全为0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">userAnswers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">answer</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 每个问题都有一个固定的维度属性，比如 'e'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> dimension </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> answer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">dimension</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// answer.score 是 1-4 分</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">dimension</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> answer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">score</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>并不是每道题都在 E 和 I 之间拉锯，而是有些题目专门测 E，有些专门测 I。最终，系统会分别统计 E 和 I 的总得分。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-决斗与生成人格代码">3. “决斗”与生成人格代码<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#3-%E5%86%B3%E6%96%97%E4%B8%8E%E7%94%9F%E6%88%90%E4%BA%BA%E6%A0%BC%E4%BB%A3%E7%A0%81" class="hash-link" aria-label="3. “决斗”与生成人格代码的直接链接" title="3. “决斗”与生成人格代码的直接链接" translate="no">​</a></h3>
<p>关键的一步来了。系统并不会直接使用这 12 个具体的分数进行相似度计算（如余弦相似度），而是采用了一种**二值化（Binarization）**的策略，类似于 MBTI 的类型划分。</p>
<p>对于每一对轴线，它会比较两个子维度的总分，得分高者胜出：</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> resultCode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">e</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">i</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"e"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"i"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">n</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">s</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"n"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">t</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">f</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"t"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">p</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">j</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"p"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"j"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">a</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">o</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"a"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"o"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">h</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> scores</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">c</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"h"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"c"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>这就生成了一个由 6 个字母组成的字符串（人格代码），例如 <code>"entpah"</code> 或 <code>"isfjoc"</code>。</p>
<p>如果是 6 个维度，每个维度 2 种可能，那么总共有 $2^6 = 64$ 种可能的人格组合。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-角色匹配机制">4. 角色匹配机制<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#4-%E8%A7%92%E8%89%B2%E5%8C%B9%E9%85%8D%E6%9C%BA%E5%88%B6" class="hash-link" aria-label="4. 角色匹配机制的直接链接" title="4. 角色匹配机制的直接链接" translate="no">​</a></h3>
<p>你可能会以为系统会计算你的分数向量与各个角色向量的欧氏距离，找出“最近”的角色。但实际上，代码的逻辑非常简单粗暴：<strong>精确查表</strong>。</p>
<p>系统直接拿着生成的 6 字母代码去数据库查询：</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 伪代码</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> characters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> database</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"characters"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">where</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dimension_code"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"=="</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> resultCode</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>即中</strong>：如果数据库里有角色的设定刚好是这个代码（比如灵梦被设定为 <code>entpah</code>），那么你就匹配到了灵梦。</li>
<li class=""><strong>碰撞</strong>：如果同一个代码对应了多个角色，系统会从中<strong>随机</strong>抽取一个。</li>
<li class=""><strong>未命中（Fallback）</strong>：这是最有趣的部分。如果数据库里<strong>没有</strong>角色的代码和你完全一致，会发生什么？代码显示，它会<strong>随机返回一个角色</strong>！</li>
</ul>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">matchedCharacters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> allCharacters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAllCharacters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 随机抽取一个幸运角色</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    finalCharacter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> allCharacters</span><span class="token punctuation" style="color:#393A34">[</span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">floor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">random</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> allCharacters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>这意味着，如果你的人格组合非常独特（或者非常奇葩），导致在预设的东方角色库中找不到对应的人，你得到的其实是一个完全随机的结果。这解释了为什么有时候结果会让人觉得“不太准”。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="技术总结">技术总结<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93" class="hash-link" aria-label="技术总结的直接链接" title="技术总结的直接链接" translate="no">​</a></h2>
<p>从技术角度看，这个 H5 应用使用了以下栈：</p>
<ul>
<li class=""><strong>前端</strong>：React + Vite 打包。</li>
<li class=""><strong>后端服务</strong>：使用了 Supabase (BaaS) 提供的数据库服务，前端直接通过 API 读取题目和角色数据。</li>
<li class=""><strong>构建平台</strong>：看起来像是使用了名为 "Miaoda" (秒搭) 的低代码/无代码平台生成的。</li>
</ul>
<p>所谓的“六维向量”其实是 <strong>6 组二元对抗特质</strong>。匹配算法本质上是<strong>分类（Classification）<strong>而非</strong>回归（Regression）<strong>或是</strong>聚类（Clustering）</strong>。它将丰富的人格光谱简化为了 64 个离散的格子。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="结语">结语<a href="https://sukima-ml.club/blog/touhou-personality-test-analysis#%E7%BB%93%E8%AF%AD" class="hash-link" aria-label="结语的直接链接" title="结语的直接链接" translate="no">​</a></h2>
<p>虽然算法逻辑比预想的要简单直白，但这并不妨碍它的趣味性。这种将复杂人格降维打击成几个标签的做法，正是各种网络心理测试流行的秘诀——它简单、易于传播，并且给出了一个看似确定的“身份”。</p>
<p>下次当你测出自己是博丽灵梦或是雾雨魔理沙时，不妨想一想：你是在那 1/64 的格子里与她相遇，还是被随机函数“命运”地指派到了她身边呢？</p>
<hr>
<p><em>本文基于对公开页面源码的分析，仅供学习交流。</em></p>
<p>Sincerely,</p>
<p><strong>苏心贤 (he/him)</strong><br>
<!-- -->Undergraduate Student / Incoming Ph.D. Student (2026)<br>
<!-- -->Beijing Jiaotong University</p>]]></content>
        <author>
            <name>苏心贤</name>
            <email>kanade271828@gmail.com</email>
            <uri>https://fcsu.dev</uri>
        </author>
        <category label="东方Project" term="东方Project"/>
        <category label="技术" term="技术"/>
        <category label="算法" term="算法"/>
        <category label="逆向工程" term="逆向工程"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[北大例会记，展示品不小心变成奖品了（]]></title>
        <id>https://sukima-ml.club/blog/pku_Hxzn</id>
        <link href="https://sukima-ml.club/blog/pku_Hxzn"/>
        <updated>2025-11-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[2025年11月23日的北大例会，是我们社团制品的第一次线下首秀。]]></summary>
        <content type="html"><![CDATA[<p>2025年11月23日的北大例会，是我们社团制品的第一次线下首秀。
为此我们特意准备了两幅紫妈。按照原定剧本，16寸用于抽奖，20寸仅作镇场展示。结果因为忘记和Staff确认细节，出现了意料之外的一幕——本该跟我回家的20寸大画，被台上的蕾米捧在胸前，作为大奖送给了一位幸运的“村民”。
木已成舟，为了不让大家失望，我干脆“将错就错”，把剩下的那幅16寸也送给了现场辛勤工作的Staff们。
这次宣发费用是彻底花超了，但能参与氛围这么好的大学例会，也是值了。更何况我自己也是欧气爆发，反手抽中了一份二等奖——炎上书屋的《人间之里，闲庭信步》。</p>
<hr>
<p>Sincerely,</p>
<p><strong>苏心贤 (he/him)</strong><br>
<!-- -->Undergraduate Student / Incoming Ph.D. Student (2026)<br>
<!-- -->Beijing Jiaotong University</p>]]></content>
        <author>
            <name>苏心贤</name>
            <email>kanade271828@gmail.com</email>
            <uri>https://fcsu.dev</uri>
        </author>
        <category label="社团" term="社团"/>
        <category label="发展" term="发展"/>
        <category label="东方Project" term="东方Project"/>
        <category label="名画同人" term="名画同人"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[一切的开始]]></title>
        <id>https://sukima-ml.club/blog/beginning</id>
        <link href="https://sukima-ml.club/blog/beginning"/>
        <updated>2025-11-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[2025年11月8日的北京THO上，我看到了三幅惊艳的名画同人，买下两幅后依然惊叹于这一创意，意犹未尽。]]></summary>
        <content type="html"><![CDATA[<p>2025年11月8日的北京THO上，我看到了三幅惊艳的名画同人，买下两幅后依然惊叹于这一创意，意犹未尽。</p>
<p>说干就干，当晚我联系到了摊主，征得同意后拿到了原图制作了两幅艺术微喷。我认为这么优秀的美术资源理应在更好的载体上呈现，比如摄影纯棉纸和爱普生十色打印机所输出的艺术微喷。</p>
<p>依然意犹未尽，于是第二天我确立了社团名字，第三天我买下了域名，开始搭建社团网站。</p>
<p>然后是寻找合适的画师并且联系约稿。</p>
<p>如今是11.11的0:22，从我产生了创建社团的念头到付诸行动，大概用了48小时吧。</p>
<p>许多美术资源的筹备计划已经出现在我心中，看来这个双十一，我要大出血了。</p>
<p>最后祝贺我们隙间月影的成立，希望我，和我未来的伙伴们，能保持行动力，科学规划，长远发展，无限进步。</p>
<hr>
<p>Sincerely,</p>
<p><strong>苏心贤 (he/him)</strong><br>
<!-- -->Undergraduate Student / Incoming Ph.D. Student (2026)<br>
<!-- -->Beijing Jiaotong University</p>]]></content>
        <author>
            <name>苏心贤</name>
            <email>kanade271828@gmail.com</email>
            <uri>https://fcsu.dev</uri>
        </author>
        <category label="社团" term="社团"/>
        <category label="创立" term="创立"/>
        <category label="东方Project" term="东方Project"/>
        <category label="名画同人" term="名画同人"/>
    </entry>
</feed>