<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>shisenshouのブログ</title>
<link>https://ameblo.jp/shisenshou/</link>
<atom:link href="https://rssblog.ameba.jp/shisenshou/rss20.xml" rel="self" type="application/rss+xml" />
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com" />
<description>ブログの説明を入力します。</description>
<language>ja</language>
<item>
<title>四川省ゲームのルールを忘れていたので、実際に遊びながら思い出してみた</title>
<description>
<![CDATA[ <h1>&nbsp;</h1><p>最近、久しぶりに四川省ゲームをやってみました。</p><p>昔は普通に遊んでいたはずなのに、いざ盤面を見ると、</p><p>「同じ牌なら全部消せるんだっけ？」</p><p>「線って何回まで曲がってよかった？」</p><p>と、意外とルールを忘れていました。</p><p>そこで今回は、説明を細かく読むより、実際に四川省を遊びながら思い出してみることにしました。</p><h2>四川省ゲームは、まず同じ絵柄の牌を2枚探す</h2><p>やってみると、最初のルールはすぐ思い出しました。</p><p>四川省は、盤面に並んだ麻雀牌の中から、同じ絵柄の牌を2枚探して消していくゲームです。</p><p>例えば「東」なら「東」。</p><p>同じ数字や同じ絵柄の牌をペアにします。</p><p>ただし、同じ牌を見つければ何でも消せるわけではありません。</p><p>ここが四川省ゲームらしいところでした。</p><h2>同じ牌なのに消せない理由も思い出した</h2><p>久しぶりに遊んでいて、</p><p>「同じ絵柄なのに、なんでこれは消えないんだろう」</p><p>となった場面がありました。</p><p>そこで思い出したのが、四川省の“線”のルールです。</p><p>2枚の牌の間を、ほかの牌に邪魔されずにつなげられる必要があります。</p><p>しかも、線は何度でも曲がれるわけではなく、基本は2回まで。</p><p>なので、</p><p>同じ牌を見つける<br>↓<br>2枚をつなげられるか見る<br>↓<br>つながれば消す</p><p>という流れになります。</p><p>この感覚が戻ると、一気に昔遊んでいた四川省らしくなりました。</p><h2>盤面の外側も使えるのを忘れていた</h2><p>もうひとつ忘れていたのが、外側の牌です。</p><p>最初は、</p><p>「この2枚、間に牌があるから無理だな」</p><p>と思っていたのですが、外側を回るとつながる場合があります。</p><p>なので四川省ゲームでは、盤面の中だけを見るより、</p><p>「外から回れないかな」</p><p>と見るのも大事でした。</p><p>久しぶりにやると、このあたりを忘れているんですよね。</p><p>でも何組か消しているうちに、だんだん感覚が戻ってきました。</p><h2>実際に遊ぶほうがルールを思い出しやすかった</h2><p>自分の場合、四川省のルールを文章だけで読み直すより、実際に牌を触ったほうが早かったです。</p><p>同じ牌を選ぶ。</p><p>消えない。</p><p>「なんでだろう」と盤面を見る。</p><p>別のペアを消す。</p><p>さっき取れなかった牌が取れるようになる。</p><p>この流れを何回かやると、</p><p>「ああ、こういうゲームだった」</p><p>と自然に思い出します。</p><h2>今回使った四川省ゲーム</h2><p>今回、<strong><a href="https://shisenshou.com/" rel="noopener noreferrer" target="_blank">四川省ゲーム</a>のルールを実際に確認したい、同じ麻雀牌がなぜ消せるのか試したい、二角取りの遊び方を思い出したい、無料でブラウザから四川省を遊びたい</strong>ときに使ったのが Shisenshou.com でした。</p><p>&nbsp;</p><p>PCやスマホのブラウザから盤面を開いて、同じ絵柄の牌を2枚選びながら、</p><p></p><p>「これは消せる」</p><p>「これはまだつながらない」</p><p>と実際に試せるので、久しぶりに四川省を遊ぶときには分かりやすかったです。</p><h2>四川省は、ルールを忘れていても意外とすぐ戻れる</h2><p>今回やってみて感じたのは、四川省ゲームは一度遊んだことがある人なら、かなり思い出しやすいゲームだということでした。</p><p>覚えておくことはそこまで多くありません。</p><p>同じ牌を探す。</p><p>2枚を線でつなげられるか見る。</p><p>取れる牌を少しずつ消していく。</p><p>最後まですべて消せたらクリア。</p><p>久しぶりでルールを忘れていても、一局遊んでいるうちにだんだん戻ってきます。</p><p>自分も最初は少し迷いましたが、数分後には普通に牌を探していました。</p><p>四川省ゲームを昔やっていて、また遊びたくなった人なら、ルールを完璧に思い出してから始めなくても大丈夫そうです。</p><p>まず盤面を開いて、同じ牌を一組探してみる。</p><p>自分にはそれが一番早かったです。</p>
]]>
</description>
<link>https://ameblo.jp/shisenshou/entry-12980159263.html</link>
<pubDate>Tue, 29 Sep 2026 22:39:20 +0900</pubDate>
</item>
<item>
<title>四川省ゲームを探していたら「二角取り」が出てきたので遊んでみた</title>
<description>
<![CDATA[ <h1>&nbsp;</h1><p>最近、久しぶりに四川省ゲームをやりたくなって探していたら、「二角取り」という名前もよく出てきました。</p><p>最初は、</p><p>「四川省と二角取りって別のゲーム？」</p><p>と思ったのですが、実際に遊んでみると、自分が昔やっていた四川省はまさにこのタイプでした。</p><p>麻雀牌のような同じ絵柄を2枚探して、線でつなげられる組み合わせを消していくゲームです。</p><p>名前を忘れていても、盤面を見るとすぐ思い出します。</p><h2>「これ、昔やっていた四川省だ」とすぐ分かった</h2><p>自分が覚えていたのは、</p><p>同じ絵柄の牌を探す。</p><p>2枚を選ぶ。</p><p>つながれば消える。</p><p>少しずつ盤面が空いていく。</p><p>という遊び方でした。</p><p>久しぶりだったので最初は少し迷いましたが、何組か消しているうちに、</p><p>「ああ、これだった」</p><p>という感じに。</p><p>四川省ゲームって、ルールを文章で全部覚え直すより、実際の盤面を見るほうが思い出すのが早い気がします。</p><h2>二角取りという名前でも探せると知って少し楽になった</h2><p>自分はずっと「四川省」という名前で覚えていました。</p><p>でも今回探してみて、「二角取り」という名前でも同じタイプの麻雀牌パズルが見つかることを知りました。</p><p>なので、</p><p>「昔遊んだ四川省ゲームをもう一度やりたい」</p><p>「麻雀牌を2枚ずつ消すゲームを探している」</p><p>というときは、四川省だけでなく二角取りという名前も覚えておくと探しやすいです。</p><p>見た目が似た麻雀牌ゲームはいくつかありますが、自分が探していたのはこの遊び方でした。</p><h2>実際に遊ぶと、意外と何局も続けてしまった</h2><p>最初は一局だけのつもりでした。</p><p>でも、同じ牌を見つけてもすぐ取れるとは限らないので、</p><p>「これはまだ無理かな」</p><p>「こっちを先に消したら取れそう」</p><p>と少し考えることになります。</p><p>これがちょうどよくて、気づいたらもう一局やっていました。</p><p>難しい操作を覚える必要はないけれど、完全に何も考えないゲームでもない。</p><p>四川省や二角取りが昔から好きだった理由を、久しぶりに思い出しました。</p><h2>今回遊んだ四川省ゲーム</h2><p>今回使ったのは、<strong>四川省ゲームを無料で遊びたい、二角取りをブラウザですぐ始めたい、同じ絵柄の麻雀牌を2枚ずつ消すパズルをPCやスマホで楽しみたい</strong>ときに使える Shisenshou.com です。</p><p><a href="https://shisenshou.com/">無料で四川省ゲーム・二角取りを遊ぶ</a></p><p>自分の場合は、四川省をやりたいと思ったときに、そのままブラウザから盤面を開けるのが楽でした。</p><p>昔遊んだ四川省を探している人や、「二角取りって四川省と同じなの？」と気になっている人なら、実際に一局やってみるとかなり分かりやすいと思います。</p><h2>名前より盤面を見ると早かった</h2><p>今回一番感じたのはこれでした。</p><p>四川省。</p><p>二角取り。</p><p>名前だけ見ていると、違うゲームなのかなと思います。</p><p>でも、自分の場合は実際の盤面を開いた瞬間に分かりました。</p><p>同じ麻雀牌を探して、つながる2枚を消していく。</p><p>自分が昔遊んでいたのは、これです。</p><p>久しぶりに四川省ゲームを探している人で、「二角取り」という名前が出てきて迷ったら、一度遊んでみるのが一番早いと思います。</p><p>自分もそれで、ようやく名前と記憶がつながりました。</p>
]]>
</description>
<link>https://ameblo.jp/shisenshou/entry-12980159087.html</link>
<pubDate>Tue, 29 Sep 2026 22:37:14 +0900</pubDate>
</item>
<item>
<title>最近、ちょっとした休憩時間に四川省ゲームをやっています。</title>
<description>
<![CDATA[ <p>最近、ちょっとした休憩時間に四川省ゲームをやっています。</p><p>昔遊んだことがある人なら分かると思うのですが、麻雀牌みたいな同じ絵柄を2枚見つけて、線でつなげられる組み合わせを消していくパズルです。</p><p>久しぶりにやると、最初は</p><p>「この2枚、消せるんだっけ？」</p><p>みたいに少し迷うのですが、何回か触っているとすぐ思い出します。</p><p>最近は、仕事の合間に5分だけ遊んだり、夜に少し気分転換したいときに一局だけやったりしています。</p><p>対戦ゲームみたいに相手を待たなくていいし、長く続けなくてもいいので、自分にはちょうどいいです。</p><p>四川省や二角取りって、ただ同じ牌を探すだけかと思いきや、</p><p>「こっちを先に消したほうがいいかな」</p><p>「この牌を取ると次が開きそう」</p><p>みたいに少し考えるのが面白いんですよね。</p><p>最近使っているのは Shisenshou.com です。</p><p><strong><a href="https://shisenshou.com/" rel="noopener noreferrer" target="_blank">四川省ゲーム</a>を無料で遊びたい、ブラウザですぐ始めたい、PCやスマホで一人用の麻雀牌パズルを遊びたい、二角取りを暇つぶしや短い休憩時間に楽しみたい</strong>というときに使いやすいです。</p><p>&nbsp;</p><p>アプリを入れなくても、そのまま四川省ゲームを始められるので、「ちょっとだけ遊びたい」という日に便利でした。</p><p>最近は動画を見るより、こういうシンプルなパズルを数分やるほうが気分転換になる日もあります。</p><p>四川省を昔遊んでいた人なら、一度盤面を見るとかなり懐かしく感じると思います。</p>
]]>
</description>
<link>https://ameblo.jp/shisenshou/entry-12980156303.html</link>
<pubDate>Tue, 29 Sep 2026 22:07:58 +0900</pubDate>
</item>
<item>
<title>最近、寝る前に何となくスマホを見続けてしまうことが多かったので、少しだけ別のことをしようと思って</title>
<description>
<![CDATA[ <p>最近、寝る前に何となくスマホを見続けてしまうことが多かったので、少しだけ別のことをしようと思って四川省ゲームをやってみました。</p><p>四川省は、同じ絵柄の麻雀牌を2枚探して、線でつなげられる組み合わせを消していくパズルゲームです。</p><p>「四川省ゲームをスマホで遊びたい」<br>「無料の二角取りを探している」<br>「アプリを入れずにブラウザで遊びたい」</p><p>という人には、かなり気軽なゲームだと思います。</p><p>自分も最初は本当に一局だけのつもりでした。</p><p>でも、同じ牌を見つけて、</p><p>「これは今消せるかな」<br>「先にこっちを取ったほうがいいかな」</p><p>と考えていると、意外と集中します。</p><p>SNSをぼんやり見続けるのとは違って、短い時間でも「ちゃんと何かをやった」という感じがありました。</p><p>最近遊んでいるのは Shisenshou.com です。</p><p><strong><a href="https://shisenshou.com/" rel="noopener noreferrer" target="_blank">四川省ゲーム</a>を無料で遊びたい、スマホやPCのブラウザですぐ始めたい、二角取りや麻雀牌パズルを一人で楽しみたい、寝る前や待ち時間の暇つぶしに短時間だけ遊びたい</strong>というときに使いやすいです。</p><p>&nbsp;</p><p>アプリのインストールなしで、そのまま四川省を始められるので、「今ちょっとだけ遊びたい」というときにちょうどよかったです。</p><p>四川省って派手なゲームではないけれど、同じ牌を探して少しずつ盤面が空いていく感じが気持ちいいんですよね。</p><p>最近は寝る前だけでなく、ちょっとした待ち時間にも一局だけ遊ぶことがあります。</p><p>長く遊ばなくても成立するので、自分にはこのくらいの軽さが合っていました。</p>
]]>
</description>
<link>https://ameblo.jp/shisenshou/entry-12980156186.html</link>
<pubDate>Tue, 29 Sep 2026 22:06:35 +0900</pubDate>
</item>
<item>
<title>四川省ゲームを実装する｜必ず解ける盤面を「逆順生成」で作る方法</title>
<description>
<![CDATA[ <h1>&nbsp;</h1><p>四川省ゲームをブラウザで実装するとき、接続判定が動いただけではゲームとしてまだ不十分でした。</p><p>次に問題になったのが、<strong>四川省の盤面をどう作るか</strong>です。</p><p>四川省（二角取り）は、同じ絵柄の麻雀牌を2枚選び、牌のない場所を通る線が二角以内でつながれば、その2枚を消せるパズルです。</p><p>そのため、牌をランダムに並べるだけだと、</p><ul><li><p>開始直後から取れる牌が少ない</p></li><li><p>途中で手詰まりになる</p></li><li><p>テストするたびに盤面品質が変わる</p></li><li><p>「最後まで解ける四川省ゲーム」を保証できない</p></li></ul><p>という問題が出ます。</p><p>自分が実装するときは、単純なランダム配置ではなく、</p><p><strong>先に「最後まで消せる順番」を作り、その順番を逆から使って麻雀牌を配置する</strong></p><p>方法にしました。</p><p>これなら、生成した四川省の盤面に<strong>少なくとも1本の完全な解法</strong>を持たせられます。</p><h2>四川省ゲームで単純シャッフルを使うと何が困るのか</h2><p>最初はかなり単純に作っていました。</p><p>同じ麻雀牌を偶数枚ずつ用意して、</p><pre><code>const tiles = [  "1m", "1m",  "2m", "2m",  "3m", "3m",  // ...];</code></pre><p>Fisher-Yatesでシャッフルします。</p><pre><code>function shuffle&lt;T&gt;(items: T[]): T[] {  const result = [...items];  for (let i = result.length - 1; i &gt; 0; i--) {    const j = Math.floor(Math.random() * (i + 1));    [result[i], result[j]] = [result[j], result[i]];  }  return result;}</code></pre><p>そして四川省の盤面へ順番に入れる。</p><pre><code>const shuffled = shuffle(tiles);</code></pre><p>これでも「同じ牌が必ず偶数枚ある」という条件は満たせます。</p><p>ただし、</p><p><strong>その配置を四川省のルールで最後まで消せるか</strong></p><p>は別問題です。</p><p>ペアが存在することと、そのペアを二角以内の線で取れることは同じではありません。</p><p>そこで、盤面を作ったあとに「解けることを祈る」のではなく、最初から解法を持つ盤面を生成することにしました。</p><h1>発想を逆にする：消す順番ではなく置く順番を作る</h1><p>考え方はシンプルです。</p><p>通常の四川省ゲームでは、</p><pre><code>牌がたくさんある↓取れる2枚を探す↓消す↓空きマスが増える↓次の2枚を消す</code></pre><p>と進みます。</p><p>盤面生成では、これを逆にします。</p><pre><code>空の盤面↓互いにつながる2マスを選ぶ↓同じ牌を置く↓また、現在の状態でつながる空きマスを2つ選ぶ↓同じ牌を置く↓盤面が埋まるまで続ける</code></pre><p>そして実際に遊ぶときは、</p><p><strong>最後に置いたペアから逆順に消せば必ず解ける</strong></p><p>という構造にします。</p><h1>なぜ逆順なら四川省の解法を保証できるのか</h1><p>例えば空の盤面に、最初のペアAを置きます。</p><pre><code>. . . . .. A . A .. . . . .</code></pre><p>A同士が四川省のルールでつながる場所を選んでいます。</p><p>次にBを置きます。</p><pre><code>. . B . .. A . A .. . B . .</code></pre><p>このときも、<strong>Aがすでに存在する状態でB同士がつながる場所</strong>だけを選びます。</p><p>さらにCを置く。</p><pre><code>. C B . .. A . A .. . B C .</code></pre><p>同じように、現在ある牌を障害物として扱いながら、C同士が接続可能な場所を選びます。</p><p>最終盤面が完成したら、</p><pre><code>C↓B↓A</code></pre><p>の逆順で消します。</p><p>Cを消した時点では、Cを配置したときより空きマスが増えています。</p><p>そのためCは取れます。</p><p>Cを消したあと、Bについても、Bを配置した時点と同じか、それ以上に空いています。</p><p>だからBも取れます。</p><p>同じ考え方で最後まで進められます。</p><h1>盤面データを用意する</h1><p>今回は、空きマスを <code>null</code> とします。</p><pre><code>type Position = {  row: number;  col: number;};type Tile = {  pairId: number;  type: string;};type Cell = Tile | null;type Board = Cell[][];</code></pre><p><code>type</code> は画面に表示する麻雀牌の種類。</p><p><code>pairId</code> は盤面生成時に作った「本来のペア」を識別するための内部IDです。</p><p>ここは分けておくと扱いやすいです。</p><p>例えば同じ「東」が4枚ある四川省でも、</p><pre><code>東 pairId=10東 pairId=10東 pairId=25東 pairId=25</code></pre><p>のように、生成時のペアを記録できます。</p><h1>まず空の四川省盤面を作る</h1><pre><code>function createEmptyBoard(  rows: number,  cols: number): Board {  return Array.from(    { length: rows },    () =&gt; Array&lt;Cell&gt;(cols).fill(null)  );}</code></pre><p>例えば、</p><pre><code>const board = createEmptyBoard(8, 12);</code></pre><p>なら8×12の盤面になります。</p><h1>空いている位置を取得する</h1><pre><code>function getEmptyPositions(board: Board): Position[] {  const positions: Position[] = [];  for (let row = 0; row &lt; board.length; row++) {    for (let col = 0; col &lt; board[row].length; col++) {      if (board[row][col] === null) {        positions.push({ row, col });      }    }  }  return positions;}</code></pre><p>この空きマスの中から、</p><p><strong>四川省のルールで互いにつながる2マス</strong></p><p>を探します。</p><h1>接続判定は既存の四川省ルールをそのまま使う</h1><p>ここでは、</p><pre><code>canConnect(  board,  start,  end)</code></pre><p>という関数がすでにある前提にします。</p><p>この関数は、</p><ul><li><p>同じ行・列の直線</p></li><li><p>1回曲がる経路</p></li><li><p>2回曲がる経路</p></li><li><p>盤面外周を使う経路</p></li><li><p>他の麻雀牌を通過しない</p></li></ul><p>という四川省・二角取りの接続ルールを判定します。</p><p>重要なのは、<strong>盤面生成専用の別ルールを作らないこと</strong>です。</p><p>実際のプレイで使う接続判定と、盤面生成で使う判定を同じ関数にします。</p><p>そうすると、</p><pre><code>生成時は取れる↓実際に遊ぶと取れない</code></pre><p>というズレを避けやすくなります。</p><h1>今置けるペアを探す</h1><p>まず空きマス同士を調べます。</p><pre><code>type PositionPair = {  a: Position;  b: Position;};function findPlaceablePairs(  board: Board): PositionPair[] {  const empty = getEmptyPositions(board);  const result: PositionPair[] = [];  for (let i = 0; i &lt; empty.length; i++) {    for (let j = i + 1; j &lt; empty.length; j++) {      const a = empty[i];      const b = empty[j];      if (canConnect(board, a, b)) {        result.push({ a, b });      }    }  }  return result;}</code></pre><p>ここで見つかった2マスなら、<strong>現在の盤面状態で四川省のルール上つながっています。</strong></p><p>その位置に同じ牌を置きます。</p><h1>1ペアずつ配置する</h1><pre><code>type GeneratedPair = {  pairId: number;  type: string;  a: Position;  b: Position;};function placePair(  board: Board,  pair: GeneratedPair): void {  board[pair.a.row][pair.a.col] = {    pairId: pair.pairId,    type: pair.type,  };  board[pair.b.row][pair.b.col] = {    pairId: pair.pairId,    type: pair.type,  };}</code></pre><p>この処理を盤面が埋まるまで続けます。</p><h1>四川省の「解ける盤面」を生成する</h1><p>簡略化するとこうなります。</p><pre><code>function generateBoard(  rows: number,  cols: number,  pairTypes: string[]) {  const board = createEmptyBoard(rows, cols);  const placementOrder: GeneratedPair[] = [];  for (    let pairId = 0;    pairId &lt; pairTypes.length;    pairId++  ) {    const candidates = findPlaceablePairs(board);    if (candidates.length === 0) {      return null;    }    const selected =      candidates[        Math.floor(Math.random() * candidates.length)      ];    const pair: GeneratedPair = {      pairId,      type: pairTypes[pairId],      a: selected.a,      b: selected.b,    };    placePair(board, pair);    placementOrder.push(pair);  }  return {    board,    solution: [...placementOrder].reverse(),  };}</code></pre><p>ポイントは、</p><pre><code>solution: [...placementOrder].reverse()</code></pre><p>です。</p><p>置いた順番を逆にすれば、そのまま1本の正解ルートになります。</p><h1>途中で配置不能になったら作り直す</h1><p>ランダムに候補を選んでいると、途中で、</p><pre><code>candidates.length === 0</code></pre><p>になる場合があります。</p><p>つまり、まだ空きマスはあるのに、現在の配置状態では安全に追加できる2マスが見つからない。</p><p>この場合、自分は無理に盤面を修復しません。</p><p>生成を最初からやり直します。</p><pre><code>function generateWithRetry(  rows: number,  cols: number,  pairTypes: string[],  maxAttempts = 100) {  for (    let attempt = 0;    attempt &lt; maxAttempts;    attempt++  ) {    const result = generateBoard(      rows,      cols,      shuffle(pairTypes)    );    if (result) {      return result;    }  }  throw new Error(    "四川省の盤面生成に失敗しました"  );}</code></pre><p>盤面生成はプレイ中に何百回も実行する処理ではないので、自分の場合はこの方法で十分でした。</p><h1>「必ず解ける」はどう検証するか</h1><p>生成アルゴリズムを書いたら、実際に解法を再生して確認します。</p><pre><code>function cloneBoard(board: Board): Board {  return board.map(row =&gt;    row.map(cell =&gt;      cell ? { ...cell } : null    )  );}</code></pre><p>そして解法順に牌を消します。</p><pre><code>function verifySolution(  initialBoard: Board,  solution: GeneratedPair[]): boolean {  const board = cloneBoard(initialBoard);  for (const pair of solution) {    const tileA =      board[pair.a.row][pair.a.col];    const tileB =      board[pair.b.row][pair.b.col];    if (!tileA || !tileB) {      return false;    }    if (tileA.type !== tileB.type) {      return false;    }    if (!canConnect(board, pair.a, pair.b)) {      return false;    }    board[pair.a.row][pair.a.col] = null;    board[pair.b.row][pair.b.col] = null;  }  return board.every(row =&gt;    row.every(cell =&gt; cell === null)  );}</code></pre><p>盤面生成後に、</p><pre><code>const result = generateWithRetry(  8,  12,  pairTypes);if (!verifySolution(  result.board,  result.solution)) {  throw new Error(    "生成した四川省盤面に解法がありません"  );}</code></pre><p>としておけば、生成ロジックと接続判定の変更によるバグも検出できます。</p><h1>麻雀牌の種類は「ペア単位」で割り当てる</h1><p>四川省では同じ絵柄の麻雀牌が複数枚存在することがあります。</p><p>その場合でも、</p><pre><code>牌を1枚ずつランダム配置</code></pre><p>にはしません。</p><p>例えば4枚ずつ使うなら、</p><pre><code>const pairTypes = [  "1m", "1m",  "2m", "2m",  "3m", "3m",];</code></pre><p>というように、<strong>ペア単位の牌プール</strong>を作ります。</p><p><code>"1m"</code> が2回入っているので、</p><pre><code>1m × 2枚1m × 2枚</code></pre><p>となり、最終的には同じ絵柄が4枚になります。</p><p>この配列自体をシャッフルしてから配置すれば、麻雀牌の種類も毎回変化します。</p><h1>「解法がある」と「適当に取っても必ずクリアできる」は別</h1><p>ここは四川省ゲームを作るときに分けて考えました。</p><p>今回の逆順生成で保証しているのは、</p><p><strong>その盤面に少なくとも1本、最後まで消せるルートが存在する</strong></p><p>ことです。</p><p>例えば同じ「東」が4枚ある場合、</p><pre><code>東A1東A2東B1東B2</code></pre><p>という本来のペアがあっても、プレイヤーは、</p><pre><code>東A1 + 東B1</code></pre><p>を選べる可能性があります。</p><p>四川省のルール上その2枚がつながれば、その操作自体は正しいです。</p><p>ただし、本来生成した正解ルートとは違います。</p><p>その後も必ずクリアできるとは限りません。</p><p>つまり、</p><p><strong>初期盤面に解法を保証すること</strong></p><p>と、</p><p><strong>プレイヤーがどんな取り方をしても絶対に詰まらないこと</strong></p><p>は別問題です。</p><p>通常の四川省ゲームとしては、まず「少なくとも1本の解法がある盤面」を保証できればかなり扱いやすくなります。</p><h1>ヒント機能では保存した解法をそのまま返さない</h1><p>盤面生成時には正解ルートを保存できます。</p><p>ただし、プレイヤーが正解ルートと違う組み合わせを取ったあとは、そのリストをそのままヒントに使えません。</p><p>そのためヒントボタンでは、現在の盤面から改めて、</p><pre><code>同じ絵柄+現在接続可能</code></pre><p>なペアを検索します。</p><pre><code>function findHint(board: Board) {  // 現在残っている牌を種類別に取得  // 同じ種類の組み合わせを調べる  // canConnect() が true の最初のペアを返す}</code></pre><p>四川省の盤面生成用solutionは、</p><ul><li><p>自動テスト</p></li><li><p>解法検証</p></li><li><p>デバッグ</p></li></ul><p>に使い、</p><p>実プレイ中のヒントは<strong>現在の盤面状態から計算する</strong>ように分けています。</p><h1>シャッフル機能も同じ考え方で作れる</h1><p>四川省ゲームで手詰まりになった場合、単純に残り牌をランダムシャッフルすると、また取れる牌がない配置になる可能性があります。</p><p>そこでシャッフルでも、</p><pre><code>残っている牌↓現在空いていないマスだけ取得↓解ける配置を再生成↓残存牌の種類を再割り当て</code></pre><p>という形にできます。</p><p>つまり、</p><p><strong>初期盤面だけ解けるようにするのではなく、四川省の盤面生成ロジック自体を再利用する</strong></p><p>ほうが管理しやすいです。</p><h1>実際の四川省ゲームを触りながら確認したポイント</h1><p>こういう生成処理を実装するときは、コードだけで考えるより、実際の四川省を何局か遊んでみると仕様を整理しやすかったです。</p><p>特に確認したのは、</p><ul><li><p>四川省ゲームで同じ絵柄の麻雀牌をどう選ぶか</p></li><li><p>二角以内でつながる2枚がどう見えるか</p></li><li><p>牌を消すたびに空きマスがどう増えるか</p></li><li><p>外周を使って取れる牌があること</p></li><li><p>最後まで牌を消したときの盤面</p></li><li><p>手詰まりになったときに何が必要か</p></li><li><p>PCやスマホのブラウザで盤面がどう見えるか</p></li></ul><p>です。</p><p><strong>四川省ゲームをブラウザで実際に遊びながら、同じ麻雀牌のペア、二角取りの接続ルール、牌を消したあとの空きマス、盤面の進み方を確認したい場合は、</strong><a href="https://shisenshou.com/"><strong>無料で四川省ゲームを遊べる Shisenshou.com</strong></a><strong> を開いて実際の盤面と実装データを見比べると分かりやすいです。</strong></p><p>四川省・二角取りを実装するときは、</p><pre><code>この2枚はなぜ取れる？↓この2枚を消すと何が空く？↓次にどのペアがつながる？</code></pre><p>を実際のゲーム画面と自分の <code>board</code> 配列で対応させると、盤面生成のバグも見つけやすくなります。</p><h1>自分の実装フロー</h1><p>最終的には、四川省ゲームの盤面生成を次の順番にしました。</p><pre><code>1. 空の盤面を作る2. 現在接続できる空きマスを2つ探す3. 同じ麻雀牌を1ペア配置する4. 配置順をsolutionとして保存する5. 盤面が埋まるまで繰り返す6. 途中で置けなくなったら最初から再生成する7. 配置順を逆転して正解ルートを作る8. 実際にそのルートで全牌を消せるか検証する9. 検証を通った盤面だけゲームに渡す</code></pre><p>これで、</p><p><strong>ランダムに牌をばらまいて、解けるかどうかをあとから調べる</strong></p><p>方式から、</p><p><strong>解けることを前提に四川省の盤面を組み立てる</strong></p><p>方式に変わりました。</p><p>四川省ゲームを作るなら、接続判定だけでなく、盤面生成もゲームロジックの中心部分です。</p><p>見た目はランダムでも、内部ではちゃんと1本の解法を持っている。</p><p>自分の場合は、この形にしてから盤面生成・ヒント・自動テストまでかなり扱いやすくなりました。</p>
]]>
</description>
<link>https://ameblo.jp/shisenshou/entry-12980154736.html</link>
<pubDate>Tue, 29 Sep 2026 21:51:37 +0900</pubDate>
</item>
</channel>
</rss>
