マガジン

神経衰弱は記憶力だけのゲームか:運と記憶の割合

遊びを見つける

執筆にClaudeを使用しています。

森の小川の上で光る五枚の色とりどりの葉を、リスと小鳥が見つめる風景。
記事のテーマをもとに制作したAI生成イラスト。

8組16枚の神経衰弱で、まだ1枚もめくっていない場面を考えてみます。最初に1枚めくり、次に別の1枚をめくります。2枚目が1枚目の相方である確率は、残り15枚のうち相方が1枚なので15分の1、約6.7%です。どれほど記憶力が良くても、この1ターン目には覚えている札がありません。運に任せるしかない局面です。 反対に終盤を考えてみます。裏向きの札が2枚だけ残り、ほかはすべて取られているなら、1枚めくった時点で残りの1枚が相方だと確定します。ここで働いているのは記憶ではなく消去法です。序盤は運、中盤は記憶、終盤はまた確率というように、ゲームの中で運と記憶の比重は動いています。 そのため「運と記憶の割合は何対何か」という問いに、1つの数字で答えることはできません。「どの局面で、何が成立の原因になっていたか」を数える必要があります。この記事は、手元のカードで1ゲームずつ記録し、成立したペアを運と記憶に分けて集計し、短いコードで作る基準線と比べる手順を示します。結果の数値は書きません。数えるのは読者自身です。

この記事の目次
  1. 「運」と「記憶」を言葉で切り分ける
  2. 局面が進むと確率はどう変わるか
  3. 記録の取り方:1ターンずつ書く
  4. 集計の単位と、コードで作る基準線
  5. 結果の読み方と起こりやすい誤り
  6. 次の行動

「運」と「記憶」を言葉で切り分ける

数える前に、言葉の決まりを固定します。ここが曖昧だと集計が意味を持たなくなります。

  • 1ターン:札を2枚めくって、成立か不成立かが決まるまでです。成立しても1ターンと数えます。続けてめくるルールで遊ぶ場合も、2枚で区切って数えます。
  • 未知の札:このゲームでまだ一度もめくられていない札です。
  • 見た札:すでに一度以上めくられていて、取られていない札です。履歴に残っているかどうかで客観的に決められます。
  • 記憶成立(A):成立した2枚のうち、少なくとも1枚がそのターンより前にめくられていたペアです。
  • 運成立(B):2枚とも、そのターンで初めてめくられて揃ったペアです。
  • 不成立(X):揃わなかったターンです。
  • 取りこぼし:1枚目の相方がすでに履歴に出ているのに、取れなかったターンです。見た札のペアが両方そろっているのに取らなかったターンも含めます。

「記憶力」を直接測るのではなく、履歴から後で判定できる事実に置き換えている点が大事です。頭の中で覚えていたかどうかは外から見えませんが、履歴を見れば「覚えていれば取れた局面」を特定できます。

局面が進むと確率はどう変わるか

記録に入る前に、計算だけで分かる範囲を確認します。

1枚目を未知の札にして、その相方が見た札の中にないと分かったとします。相方は残りの未知の札のどこかに1枚あります。2枚目を未知の札から無作為に選ぶなら、当たる確率は、1枚目をめくる前の未知札の枚数をUとして「1/(U-1)」です。16枚の盤で、未知札の枚数ごとに並べます。

  • 16、運成立の確率 1/(U-1):1/15(約6.7%)
  • 12、運成立の確率 1/(U-1):1/11(約9.1%)
  • 8、運成立の確率 1/(U-1):1/7(約14.3%)
  • 4、運成立の確率 1/(U-1):1/3(約33.3%)
  • 2、運成立の確率 1/(U-1):1/1(100%)

序盤は6〜9%台と低く、終盤に近づくほど急に高くなります。終盤で揃うペアには、記憶力とは関係のない「確率の自然な上昇」が含まれます。

もう1つの量は、見た札のうち相方がまだ見えていない札の枚数Kです。1枚目に未知の札をめくったとき、それが見た札の相方である確率は「K/U」です。16枚の盤の局面例を3つ挙げます。

  • 1ターン目が不成立だった直後(K=2、U=14):2/14、約14.3%です。
  • 1組取られ、見た札が4枚(K=4、U=10):4/10、40%です。
  • 2組取られ、見た札が6枚(K=6、U=6):6/6、100%です。この局面では、どの未知札をめくっても相方が見えています。

K/Uの値が高い局面では、1枚目で相方を思い出せるかどうかが成立を決めます。つまり、序盤は成立の材料を集める段階で、記憶の出番は中盤から増え、終盤は再び確率の影響が強まります。「最初の数手は運、後半は記憶」という見立ては、この計算から出てくる仮説です。実際のプレーでどうなるかは、次の記録で確かめます。

記録の取り方:1ターンずつ書く

準備するものは、同じ絵柄が2枚ずつある8組16枚のカード(トランプなら同じ数字の2枚を8組選びます)、マスに1〜16の番号を振った4×4の配置、記録用紙、鉛筆です。記録係が1人いると正確ですが、1人でも「めくるたびに書く」ことで続けられます。

書くのは次の4列だけです。分類やUやKは、あとで履歴から計算します。

  1. ターン番号
  2. 1枚目のマス番号と絵柄
  3. 2枚目のマス番号と絵柄
  4. 成立したかどうか

1ゲームの記録を終えたら、履歴を上から順にたどり、各ターンについて次の3つを机の上で書き足します。

  • U:そのターンの1枚目をめくる前の未知札の枚数です。
  • K:見た札のうち相方がまだ見えていない札の枚数です。
  • 分類:A、B、X、取りこぼしのどれかです。

回数の目安は10ゲーム以上です。1ゲームでは、最初の数手で偶然ペアが出ただけで結果が大きく動きます。10ゲーム分を足して初めて、序盤・中盤・終盤それぞれに十分な件数が集まります。

局面の区切りはターン数ではなく、Uで行うと比較しやすくなります。16枚の盤なら、Uが11以上を序盤、6〜10を中盤、5以下を終盤とします。ゲームごとにターン数が違っても、同じUの帯どうしで比べられます。

集計の単位と、コードで作る基準線

集計は、局面の帯(序盤・中盤・終盤)ごとに、10ゲーム分を合計して行います。

  • 成立数:AとBの件数
  • 記憶成立の比率:A ÷ (A + B)
  • 探索ターン(1枚目の相方が見た札になく、2枚目を未知札から選んだターン)の数と、そのUから求めた運成立の見込み E_B:各探索ターンの 1/(U-1) の合計
  • 取りこぼしの件数

E_Bは「運だけで揃うなら、これくらいになるはず」という見込みです。実際のBと比べると、2枚目の選び方に偏りがなかったかが見えます。

次に、忘却の度合いを変えた仮想プレーヤーの基準線を作ります。下のコードは、ターンの終わりに見た札を確率 forget で忘れる仮想プレーヤーの1ゲームを動かします。forget が 0 なら完全記憶、1 なら記憶なしです。ブラウザの開発者ツールのコンソールか Node.js に貼って実行できます。

js
function play(n, forget) {
  const cards = [];
  for (let i = 0; i < n; i++) cards.push(i, i);
  for (let i = cards.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [cards[i], cards[j]] = [cards[j], cards[i]];
  }
  const alive = new Set(cards.keys());
  const seen = new Set();
  const pick = list => list[Math.floor(Math.random() * list.length)];
  const mateIn = x => [...seen].find(j => j !== x && cards[j] === cards[x]);
  const take = (x, y) => [x, y].forEach(k => { alive.delete(k); seen.delete(k); });
  let turns = 0, luck = 0, memo = 0;
  while (alive.size > 0) {
    turns++;
    const known = [...seen].find(i => mateIn(i) !== undefined);
    if (known !== undefined) {
      take(known, mateIn(known));
      memo++;
    } else {
      const a = pick([...alive].filter(x => !seen.has(x)));
      const m = mateIn(a);
      if (m !== undefined) {
        take(a, m);
        memo++;
      } else {
        const b = pick([...alive].filter(x => x !== a && !seen.has(x)));
        if (cards[a] === cards[b]) { take(a, b); luck++; }
        else { seen.add(a); seen.add(b); }
      }
    }
    seen.forEach(k => { if (Math.random() < forget) seen.delete(k); });
  }
  return { turns, luck, memo };
}

function summary(n, forget, trials) {
  const L = [];
  let t = 0, m = 0;
  for (let k = 0; k < trials; k++) {
    const r = play(n, forget);
    L.push(r.luck); t += r.turns; m += r.memo;
  }
  L.sort((a, b) => a - b);
  const mean = L.reduce((s, v) => s + v, 0) / trials;
  return { 平均ターン: t / trials, 平均記憶成立: m / trials, 平均運成立: mean,
    運成立10_90: [L[Math.floor(trials * 0.1)], L[Math.floor(trials * 0.9)]] };
}
for (const f of [1, 0.5, 0.2, 0]) console.log("忘却率", f, summary(8, f, 2000));

出力の「運成立10_90」は、2,000ゲームのうち下位10%と上位90%の位置にある運成立の件数です。運だけで起こる件数が、1ゲームごとにどの程度ぶれるかを示します。手元の記録と比べるときの物差しになります。

結果の読み方と起こりやすい誤り

集計が終わったら、次の順に読みます。

  1. 最初のターンのA:1ターン目に記憶成立は起こり得ません。履歴に何もないからです。もしAが付いていたら、分類を間違えています。
  2. 序盤・中盤・終盤のA ÷ (A + B):中盤で比率が高ければ、成立の主な原因が記憶だったことを示します。比率が低ければ、見た札を取りこぼしている可能性があります。取りこぼしの件数と合わせて確認します。
  3. 終盤のB:終盤のBが多くても、すぐに運だと結論しないでください。表のとおり、Uが小さい局面では確率そのものが高いからです。E_Bと並べて、見込みの範囲に収まっているかを見ます。
  4. 仮想プレーヤーとの照合:自分のターン数と取りこぼしの件数を、forget を変えた各行と見比べます。どの行に近いかが、自分の記憶の「効き方」の目安になります。

起こりやすい誤りもまとめます。

  • 1ゲームだけで判断する:運のぶれが大きく、序盤の偶然が全体を左右します。10ゲーム以上を合計してください。
  • 「見た」と「覚えた」を混同する:この分析の「見た札」は履歴上の事実です。覚えていたかどうかは、取りこぼしの有無から間接的に見ます。
  • ルールが混ざる:成立後に続けてめくるルールの回と、手番が交代する回を混ぜると、ターンの数え方が揃いません。ルールは固定してください。
  • 配置の偏りを無視する:隅や端の札は覚えやすいといわれます。札の並びを毎回変えて、特定の配置の影響を薄めます。
  • 学習効果を忘れる:同じ並びを繰り返すと、2回目以降は記憶ではなく並びの暗記になります。毎回シャッフルしてください。
  • ふたり対戦で相手のめくりを数えない:相手がめくった札も「見た札」です。履歴は両者の分を合わせて書きます。

次の行動

まず1ゲームだけ、4列の記録を取ってみてください。終わったら履歴をたどって、探索ターンのUから 1/(U-1) を足し合わせ、E_Bを出します。その数字と実際のBを並べるだけで、「運の取り分」の輪郭が見えてきます。

順番を覚えるタイプの記憶ゲームと比べたいときは、アソバースの「こだまの森」を開いてみてください。光る葉の順番を覚えて音色で返すゲームで、神経衰弱の「位置を覚えて確率を読む」記憶とは使い方が違います。この記事の記録法を応用して、自作の神経衰弱をHTMLにまとめ、アソバースに投稿することもできます。