Note
この記事でいう「初級・中級・上級」は、この解説記事を3段階に分けた読み物としての順番です。Pattern本体のスタート画面には「盤面サイズ(難易度の保証ではありません)」という注記つきで5×5・8×8・10×10を選ぶだけの欄があり(pattern/index.htmlの実際の表記)、クリア後の得点計算も盤サイズだけで初級・中級・上級のレベルを決めています(pattern/rating.jsのLEVEL_BY_SIZE = { 5: 'easy', 8: 'medium', 10: 'hard' })。つまりPattern自身は「このシード・この盤面が解く上でどれくらい難しいか」を判定していません。この記事の初級・中級・上級は、あくまでこの記事が選んだ実例の解きやすさを指し、盤サイズとも完全には対応しません(初級編の実例は5×5、中級編は8×8、上級編は10×10ですが、これはPattern側の判定基準ではなく筆者による選定です)。
結論。Patternの数字は「その行(列)に連続して並ぶ塗りマスの長さの並び」を表し、runとrunの間には必ず1マス以上の空白が要る。ある行(列)の数字が許すすべての塗り方を実際に書き出し、あるマスの値がどの塗り方でも同じであれば、そのマスは確定できる。 この記事の実例(5×5・25マス)は、この「候補を書き出して見比べる」手順を行と列で交互に繰り返すだけで、仮定を一度も置かずに4ラウンドのうちに全25マスが確定し、実際の完成形(答えの盤面)と完全に一致します。
盤面の見方: 行・列の数字と、runという考え方
Patternの盤はn×n個のマスで、プレイヤーはこのマスを直接タップして塗ります。行の左・列の上に書かれた数字が、その行(列)の**手がかり(クルー)**です。
- 数字の意味: たとえば行の数字が
1 2なら、その行には「長さ1の連続した塗りマス(run)」と「長さ2の連続した塗りマス」が、この順番(左から右)で並びます。runとrunの間には、最低1マスの空白(塗らないマス)が必要です。数字が0(空欄で表示)の行(列)は、そのマス全部が空白です。 - runの並び方に自由度がある: 数字が同じでも、runを盤のどこに置くかには複数の候補がありえます。たとえば長さ5の行に
1 1という数字がある場合、2つの長さ1のrunを、間に1マス以上の空白を空けて収める置き方は複数通りあります(後述)。
この記事では、行を1始まりで「行r」、列を「列c」、マスを「行r列c」と呼びます。
使える操作(合法手)
- マスをタップ: そのマス1つの状態を「空白→塗り→×印(塗らないという自分用の印)→空白」の順に切り替えます(
pattern/app.jsのtapCell)。×印は正式なルール上の意味を持たず、プレイヤーが「ここは塗らない」と判断した箇所を忘れないための目印です。 - 「一手戻す」: 直前の1回のタップ(1マス分の状態変化)だけを取り消します。
- 「1マスのヒント」: まだ答えと状態が違うマスを1つだけ、自動で正しい状態(塗りか空白)に直します(
pattern/app.jsのhint。×印がついていても、ヒントは塗りか空白のどちらかにするだけです)。 - 「答えを見る」: 残り全マスを一括で正しい状態に直します(「1マスのヒント」「答えを見る」のどちらを使っても、クリア自体はできますが「解答補助あり」の扱いになります)。
回転やマスの追加・削除はありません。タップで切り替わる3状態(空白・塗り・×印)のうち、実際の判定(クリア条件)で意味を持つのは「塗りかどうか」だけです(pattern/app.jsのcurrentFillは×印も空白と同じ0として扱います)。
盤の下には、現在塗っているマスの数(「◯ / ◯ マス塗り」)が表示されます。塗り分けが、出題された全行・全列の数字とちょうど一致したときだけがクリアです。 Loopと違い、Pattern本体には「数字を超過しています」のような途中経過の警告表示はありません(pattern/app.jsを確認済み)。数字と食い違っていないかは、プレイヤー自身が見比べて判断する必要があります。
実例: 5×5盤を、仮定なしで最後まで解く
n=5・シード"notes-pattern-easy-scan-0"で生成した盤面です(E.generate(5, 'notes-pattern-easy-scan-0')、4回目の試行でこの条件を満たしました)。出題時点の数字は次のとおりです(マス自体はすべて未着手=空白の状態からスタートします)。
- 行の数字(上から行1〜行5): 「1 2」「1」「2」「3」「1 2」
- 列の数字(左から列1〜列5): 「2 1」「2」「2」「1 2」「1 1」
ステップ1: 1行・1列ぶんの候補を全部書き出す
まず行4の数字「3」(長さ5のマスに、長さ3のrunが1個だけ)を見ます。長さ3のrunを長さ5の行に置ける位置は、開始位置0〜2の3通りです。
[1,1,1,0,0]
[0,1,1,1,0]
[0,0,1,1,1]
この3通りを見比べると、行4列3(中央のマス)はどの候補でも必ず塗りです(overlapと呼ばれる考え方で、run長3×2 − 行の長さ5 = 1マスぶん、両端の候補が重なる部分です)。他の4マスは候補によって塗り/空白が分かれるため、この時点ではまだ確定しません。
同様に行1の数字「1 2」(長さ5)は次の3通りです。
[1,0,1,1,0]
[1,0,0,1,1]
[0,1,0,1,1]
行1列4(4番目のマス)は3通りすべてで塗りなので確定します。行1列1は1通り目・2通り目で塗り、3通り目で空白のため、この段階ではまだ確定しません。
この「その行(列)の数字が許す配置を全部書き出し、位置ごとに値が全候補で一致するか見る」という考え方を、全行・全列に対して機械的に繰り返したものが、実際のエンジンのpropagate関数です(pattern/engine.js)。以下はこの関数を、この盤面に対して実際に実行して得られた結果です。
ラウンド1〜4: 行と列を交互に見比べて、全マスを確定させる
| ラウンド | 確定したマス | 根拠 |
|---|---|---|
| 1 | 行1列4=塗り | 行1(1 2)の全候補が列4を塗りで一致 |
| 1 | 行4列3=塗り | 行4(3)の全候補が列3を塗りで一致 |
| 1 | 行5列4=塗り | 行5(1 2)の全候補が列4を塗りで一致 |
| 1 | 行2列1=塗り | 列1(2 1)の全候補が行2を塗りで一致 |
| 1 | 行1列3=空白・行2列3=空白 | 列3(2)の全候補が行1・行2を空白で一致 |
| 1 | 行2列4=空白・行3列4=空白 | 列4(1 2)の全候補が行2・行3を空白で一致 |
| 1 | 行4列4=塗り | 列4(1 2)の全候補が行4を塗りで一致 |
| 2 | 行1列5=塗り | 行1(1 2)、ラウンド1の結果を反映した残り候補が列5を塗りで一致 |
| 2 | 行2列2=空白・行2列5=空白 | 行2(1)、列1がすでに塗りで確定しているため残り4マスは空白 |
| 2 | 行3列2=塗り・行3列5=空白 | 行3(2) |
| 2 | 行4列1=空白 | 行4(3)、列3が塗りで確定した残り候補から |
| 2 | 行5列1=塗り | 列1(2 1) |
| 2 | 行1列2=空白・行4列2=塗り・行5列2=空白 | 列2(2) |
| 3 | 行1列1=塗り | 行1(1 2)、この時点で残る候補が1通りに絞られる |
| 3 | 行4列5=空白 | 行4(3) |
| 3 | 行3列1=空白 | 列1(2 1) |
| 3 | 行5列5=塗り | 列5(1 1) |
| 4 | 行3列3=塗り・行5列3=空白 | 行3(2)・行5(1 2)がそれぞれ残り1通りに絞られる |
ラウンド5では変化がなくなり(=これ以上絞れるマスがなくなり)、この時点で全25マスがちょうど確定しています(pattern/engine.jsのpropagate関数をNode.js上で直接実行し、この盤面のクルーに対して一度も分岐探索(仮定)に入らず全マスが確定することを確認済みです)。完成形は次のとおりです(#が塗り、.が空白)。
# . . # #
# . . . .
. # # . .
. # # # .
# . . # #
この塗り分けが、出題時点の全数字と一致することはpattern/engine.jsのcluesFor関数(実際に塗った結果からrunを数え直す)で確認済みです。またこの完成形は、E.generateが実際に生成時点で持っていた「答え」(answerフィールド)と1マスの違いもなく一致します。
誤りやすい判断
- 「候補を1つ見つけただけで確定した気になる」ことに注意する。 ある行の数字を満たす塗り方は複数あることが普通です。全候補を書き出し、位置ごとに全部が同じ値かどうかを確認するまで、そのマスは確定していません。上のステップ1の例(行4の数字「3」)のように、中央のマスだけが全候補で一致し、両端2マスずつはまだ確定しない、という状態はよくあります。
- runの間の空白1マスを忘れない。 数字
1 2を「1マス塗って、そのまま2マス塗る」(間に空白なし)と誤読すると、候補の書き出し自体が誤り、以降の判断がすべてずれます。 - ×印(2回タップ)と空白(3回タップで元に戻る)を混同しない。 ×印はルール上「空白」と同じ意味を持つプレイヤー用の目印ですが、盤面の判定処理(
currentFill・isSolved)は状態が「塗り」かどうかしか見ておらず、×印と空白を区別しません。 - 数字を超過しても、Pattern本体は途中で警告を出しません。 Loopのような「数字を超過」という表示はないため(前述)、行や列を塗りすぎていないかは自分で数字と数え合わせる必要があります。
読者の検証方法
- この記事と同じ盤面は、
n=5・シードnotes-pattern-easy-scan-0で誰でも再現できます(Pattern本体の「同じ問題を再現する」欄にシードを入力するほか、pattern/engine.jsをrequireしてE.generate(5, 'notes-pattern-easy-scan-0')を実行しても同じ結果が得られます)。 - 自分の手順が合っているか不安な場合は、1マスずつ**「1マスのヒント」**で答え合わせしながら進められます(ヒントを使うと「解答補助あり」の扱いになりますが、手順の検証には支障ありません)。
- 全部自力で確定させたあとは、タップ前に画面下の進捗表示(「◯ / 25 マス塗り」、この盤面では最終的に11マス)を見ながら1手ずつ進めると、狙った通りに塗り分けが埋まっていくかを都度確認できます。
この記事が確認していないこと
- 「1行・1列の候補列挙だけで、仮定なしに全マスが確定する」という展開は、この記事の実例(5×5・このシード)固有のものです。Patternには難易度を事前に判定する仕組み(
analyzeDifficultyのような関数)が実装されていないため、別の5×5盤面や、同じシードでも別のサイズで同じ展開になることは保証されません(実際、この記事を書く過程で調べた8×8・10×10の盤面の多くは、この手順だけでは全マスが確定せず、中級編・上級編で扱う「仮に置いて確かめる」判断が必要でした)。 - 行・列の候補列挙を、どういう順番・組み合わせで見ると最も早く解けるかという「最適な手順」は扱っていません。この記事の表は、実際に
propagate関数が辿った順序をそのまま示したものです。 - 中級・上級で必要になる「仮に置いて確かめる」判断は扱っていません。中級編(その2)・上級編(その3)で扱います。
この結果が言っていないこと
- 検証は
pattern/engine.js・pattern/app.js(エンジンv1、2026-09-29時点)を対象にしています。将来の版で表示・判定基準が変わる可能性があります。 - 「行r列c」という呼び方は、この記事独自の説明用の表記です。Pattern本体の画面上にはこのような座標表示はなく、実際のUIは行・列の数字とマスの見た目のみで判断します。