博客 / 詳情

返回

絕望博弈!一眾大模型加持的猜拳遊戲,人類勝率竟不足10%?

基於 LLM + Next.js 的博弈實戰猜拳遊戲

摘要:當你以為自己在和隨機數生成器玩遊戲時,對面的 AI 正在閲讀你所有的歷史出拳記錄,並寫了一篇關於你心理狀態的小作文。本文帶你拆解這個基於 Next.js 16 + Tailwind v4 + LLM 的“過度設計”+“沒啥技術含量”+”有那麼點意思“項目。

👉 先給老闆們體驗:(具體規則有手就能玩!)

優先地址:https://rps.anhejin.cn

有條件的:https://rps-eta-ten.vercel.app

image


最近閒着沒事,突然想這用AI寫點代碼。作為一名要把“簡單需求複雜化”刻在 DNA 裏的老前端,我決定拿最簡單的“剪刀石頭布”開刀。

在這個 AI 滿天飛的時代,還在用 Math.random() 寫對手邏輯未免太沒追求了。於是,我基於最新的技術棧(Next.js 16 + React 19),接入了 OpenAI等一眾大模型,搞出了一個會“讀心”、會嘲諷,甚至懂博弈論的猜拳遊戲。

為什麼是剪刀石頭布?

別笑,剪刀石頭布其實是一個極佳的博弈論模型。

  • 新手:完全隨機(Chaos)。
  • 普通人:贏了保持,輸了變招(Win-Stay, Lose-Shift)。
  • 高手:預判你的預判。

我的目標是:構建一個能看穿你心理的 AI,並且用目前最前沿的前端技術棧把它跑起來。

技術選型:這就叫“殺雞用牛刀”

為了配得上這個“高智商”AI,我在技術棧上直接拉滿,全部採用了目前(2025-2026)的最新穩定版:

  1. Next.js 16.1 (App Router):服務端組件(RSC)處理核心邏輯,隱藏 AI 的 Prompt,保證你沒法通過 F12 偷看答案。
  2. React 19:享受最新的 Hooks 和併發特性。
  3. Tailwind CSS v4:對,就是那個不用配置構建工具、性能起飛的 v4 版本。關鍵是AI喜歡用這個
  4. SQLite + LibSQL:輕量級數據庫,用來記仇——啊不,記錄你的勝負數據。

核心玩法:AI 是怎麼“讀心”的?

這個項目的核心不在於 UI 有多炫(雖然 Tailwind 4 確實很潤),而在於 /lib/ai-service.ts 裏的那段邏輯。

傳統的遊戲 AI 往往是預設好的 if-else。但在我的設計裏,每一輪遊戲,我都會把你在這個 Session 裏的所有歷史記錄打包,像講故事一樣發給 LLM(大語言模型):


// lib/ai-service.ts

// 構建遊戲歷史描述
const historyDescription = history.length > 0
  ? history.map((h) =>
      `第${h.round}輪: 玩家出${translateChoice(h.player_choice)}, 
       AI出${translateChoice(h.ai_choice)}, 
       結果: ${translateResult(h.result)}`
    ).join("\n")
  : "這是第一輪,沒有歷史記錄。";

// ...發送給 LLM
const response = await client.chat.completions.create({
  messages: [
    { role: "system", content: systemPrompt },
    { role: "user", content: userPrompt }, // 這裏包含了 historyDescription
  ],
  // ...
});

System: 你是一個猜拳高手,你的對手是一個普通人類。
User: 前幾輪戰況如下:第1輪玩家出剪刀,你出布(輸);第2輪玩家出石頭,你出布(贏)。現在是第3輪,請分析玩家的心理,並給出你的出拳。

不僅如此,我給 AI 設定了兩種模式:

  1. 策略模式(Strategy):降低模型的 temperature(隨機性),讓它進行嚴密的邏輯推理。比如它會分析:“玩家上一把輸了,根據心理學,這把他大概率會出剋制我上一把的招數,所以我預判他……”
  2. 混沌模式(Chaos):拉高 temperature,讓 AI 徹底放飛自我,主打一個亂拳打死老師傅。

優雅降級:當 GPT 腦幹缺失時

作為老全棧,必須要考慮一種情況:如果 API 掛了,或者響應超時了怎麼辦?

難道讓用户乾等着轉圈圈?絕對不行。

我在後端實現了一套基於傳統統計學的本地算法作為“備胎”。如果 LLM 在規定時間內沒有響應,系統會無縫切換到本地邏輯。這個本地邏輯一點也不弱,它內置了經典的策略庫(代碼在 lib/game.ts):


// lib/game.ts 裏的心理學博弈邏輯

// 1. 如果玩家上輪輸了,傾向於出能剋制AI上一招的選項 (Win-Stay, Lose-Shift的變種)
if (lastResult === 'ai_win') {
  const lastAIChoice = lastRound.ai_choice as Choice;
  // 預測玩家會出剋制我不上一把的牌
  const predictedPlayerChoice = whatBeatsAI[lastAIChoice];
  // 那我就預判你的預判
  return counterMoves[predictedPlayerChoice];
}

// 2. 如果玩家上輪贏了,可能繼續用同一招
if (lastResult === 'player_win') {
  // 玩家可能繼續用同一招,直接剋制它
  return counterMoves[lastPlayerChoice];
}

這些策略包括:

  • 頻率分析:如果你一直出石頭,它就會瘋狂出布。
  • 反制連勝:如果你贏了,它會假設你會繼續出一樣的,直接剋制你。

在代碼實現上,這只是一個簡單的 try-catch 降級,但對用户體驗來説是質的飛躍。用户根本感覺不到 AI 掉線了,只會感覺“這傢伙怎麼變風格了?”

全棧體驗:Next.js App Router 的絲滑

在 Next.js 16 中,前後端的邊界變得非常模糊(褒義)。本項目使用了 App Router 的 Route Handlers 來處理遊戲邏輯。

前端組件調用後端接口就像調用本地函數一樣自然:


// src/app/game/[id]/page.tsx
const playRound = useCallback(async (choice: Choice | null, timeout: boolean = false) => {
    // ...
    const res = await fetch('/api/game/play', {
        method: 'POST',
        body: JSON.stringify({ /*...*/ }),
    });
    // ...
}, []);

而在服務端 (src/app/api/game/play/route.ts),我們完成了完整的業務閉環:


// src/app/api/game/play/route.ts
export async function POST(request: NextRequest) {
    // 1. 身份校驗與數據庫讀取
    const { sessionId, playerChoice } = await request.json();
    const baseSession = await db.execute(/*...*/);

    // 2. 調用 AI (帶超時降級)
    // 如果 API 響應太慢,這裏會自動切換到本地邏輯
    const aiChoiceResult = await Promise.race([
        getAIChoiceFromAPI(aiConfig, history, difficulty),
        timeoutPromise // 設定的超時時間
    ]);

    // 3. 判定勝負 & 寫入數據庫
    const result = determineWinner(playerChoice, aiChoiceResult.choice);
    // ...
    
    return NextResponse.json({ /*...*/ });
}

這一套流程行雲流水,類型安全雖然不如 Server Actions 極致,但通過共享類型定義(Shared Types),依然能保證前後端的一致性。不用寫繁瑣的 Swagger,不用搞複雜的 Redux,一把梭。

實際上手:由於太會嘲諷導致不想玩了

為了增加趣味性,我讓 AI 不僅輸出“石頭/剪刀/布”,還要輸出一段 Reasoning(推理過程)Comment(賽後嘲諷)

當你輸掉比賽時,你可能會看到這樣的結算語:
“我看你第一把猶豫了很久出了剪刀,我就知道你是個保守的人。下一把別這麼明顯了,人類。”

説實話,代碼寫完後我自己測試了幾把,勝率居然只有 40% 左右。看着屏幕上 AI 的嘲諷,我即使作為開發者也不禁懷疑:這玩意兒是不是真有意識?

體驗地址

雖説代碼沒什麼核心科技,但帶來的博弈體驗確實很有趣。我已經把項目部署上去了,歡迎來挑戰(或者被虐):

👉 在線體驗

優先地址:https://rps.anhejin.cn

有條件的:https://rps-eta-ten.vercel.app

總結

這個項目證明了一件事:技術是冰冷的,但通過簡單的創意組合,可以創造出有温度(甚至有點燙手)的交互體驗。 Next.js 16 和 React 19 的組合讓全棧開發的門檻進一步降低,讓我們有更多精力去關注“玩法”本身,而不是被構建配置折磨。

如果你對源碼感興趣,或者想改改 Prompt 把 AI 調教成“討好型人格”,歡迎去 GitHub 扒代碼。


注:

  1. 本文僅供技術交流,玩遊戲輸給 AI 請勿用拳頭擊打顯示器,開發者概不負責。
  2. 這只是一個娛樂小遊戲,結果具有隨機性,不代表任何AI大模型的真實能力。
  3. 遊戲結果僅供娛樂,不應用於評估或比較AI模型的實際性能。
  4. 網站不收集、存儲或分享任何個人信息或用户數據。
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.