一筆書きの判定をゲームにする:描ける図形と描けない図形
遊びをつくる執筆にClaudeを使用しています。

四角形に対角線を1本足した図形は、一筆書きで描けます。対角線を2本とも足すと、描けなくなります。線を1本増やしただけなのに、なぜ結果が変わるのでしょうか。この記事では、この違いを遊びながら自分の手で確かめる実験を設計します。 ここで一つ厄介な点があります。ゲームの中で何十回試しても描けなかったとき、それは「描けない図形」なのでしょうか。それとも「まだ見つけていないだけ」なのでしょうか。試行錯誤だけでは、描けないことは証明できません。一方で、頂点につながる線の本数を数えれば、試さなくても答えが決まります。オイラー路(すべての辺をちょうど1回ずつ通る道)の条件が、そこで効いてきます。 この記事の実験は、「予想する」「実際に辿る」「数えて答え合わせをする」の3段階で進みます。短いコードで、頂点をクリックして辺を辿る小さなゲームを作り、6つの図形で記録を取ります。結果は書きません。記録表を埋めると、予想と数え方のどちらが信頼できるかが、自分のデータで分かる設計です。
問い:試して描けないとき、描けないと言えるのか
実験の問いを二つに分けます。
- 問い1:図形を見ただけの予想と、実際に辿った結果は、どのくらい一致するか。
- 問い2:頂点ごとの「線の本数」を数えると、試す前に成否を言い当てられるか。
線の本数は、数学では次数と呼びます。次数が奇数の頂点を奇点、偶数の頂点を偶点と呼びます。確かめたい仮説は次の2つの条件です。
- 図形がひとつながりである(連結)。
- 奇点の数が0個か2個である。
両方を満たすなら一筆書きができ、どちらかを欠くとできない、という仮説です。奇点が0個なら、始点に戻る形で描けます。2個なら、片方の奇点から始めて、もう片方の奇点で終わります。奇点の数は必ず偶数になります。線の端は2つずつ頂点に付くので、次数の合計が辺の数の2倍になるためです。そのため、奇点が1個や3個の図形は存在しません。
仮説は読者が自分のデータで確かめるものです。この記事では、条件が成り立つとも成り立たないとも書きません。
準備:ミニゲームと6つの図形
ブラウザで開ける HTML ファイルを1つ作ります。index.html という名前で保存し、ダブルクリックで開いてください。外部ライブラリは使いません。頂点をクリックして始点を決め、続けて隣の頂点をクリックすると、その辺を通ったことになります。通った辺は赤くなり、同じ辺は二度と通れません。
<canvas id="c" width="320" height="240"></canvas>
<p id="m">頂点をクリックして始点を決めます</p>
<script>
// P=頂点の座標、E=辺(頂点番号は0始まり)
const P=[[60,40],[260,40],[260,200],[60,200]];
const E=[[0,1],[1,2],[2,3],[3,0],[0,2]];
const used=E.map(()=>false);
let cur=-1,n=0,tries=0;
const g=c.getContext("2d");
function draw(){
g.clearRect(0,0,320,240);
E.forEach(([a,b],i)=>{
g.strokeStyle=used[i]?"#d33":"#888";
g.lineWidth=used[i]?4:2;
g.beginPath();g.moveTo(...P[a]);g.lineTo(...P[b]);g.stroke();
});
P.forEach(([x,y],i)=>{
g.fillStyle=i==cur?"#36c":"#333";
g.beginPath();g.arc(x,y,9,0,7);g.fill();
});
}
// 答え合わせ用:コンソールで odd() と打つと奇点の数が出ます
function odd(){
const d=P.map(()=>0);
E.forEach(([a,b])=>{d[a]++;d[b]++});
return d.filter(x=>x%2).length;
}
c.onclick=e=>{
const r=c.getBoundingClientRect();
const x=e.clientX-r.left,y=e.clientY-r.top;
const v=P.findIndex(([px,py])=>Math.hypot(px-x,py-y)<14);
if(v<0)return;
if(cur<0){cur=v;}
else{
const i=E.findIndex(([a,b],k)=>!used[k]&&((a==cur&&b==v)||(a==v&&b==cur)));
if(i<0){m.textContent="その辺は使えません";return;}
used[i]=true;cur=v;n++;
}
m.textContent=`使った辺 ${n}/${E.length}`+(n==E.length?":すべて通れました":"");
draw();
};
draw();
</script>奇点の数は、画面には表示しません。表示すると、予想の段階で答えが見えてしまうためです。確かめたいときは、ブラウザの開発者ツールのコンソールで odd() と入力します。手計算の答え合わせに使ってください。
図形は P(頂点の座標)と E(辺の組)を書き換えて切り替えます。頂点番号は0から数えます。6つの図形は次のとおりです。座標は読者が決めてください。
- A 三角形、頂点数:3、辺(頂点番号の組):01, 12, 20
- B 四角形+対角線1本、頂点数:4、辺(頂点番号の組):01, 12, 23, 30, 02
- C 四角形+対角線2本、頂点数:4、辺(頂点番号の組):01, 12, 23, 30, 02, 13
- D 離れた2つの三角形、頂点数:6、辺(頂点番号の組):01, 12, 20, 34, 45, 53
- E 家の形、頂点数:5、辺(頂点番号の組):01, 12, 23, 30, 24, 34
- F 五角形の全対角線入り、頂点数:5、辺(頂点番号の組):すべての2頂点の組(全10本)
Eは、頂点0〜3を四角形の左下・右下・右上・左上とし、頂点4を屋根の先に置きます。Dは、2つの三角形を離して置きます。Cの2本の対角線は、図の上では中央で交差します。しかし交点には頂点がないので、その場所で曲がることはできません。この点は、実験の中で確認できます。
手順:予想、挑戦、数える
図形1つにつき、次の順序で進めます。順序を守ることが、この実験の肝です。
- 図形を表示し、数える前に「描ける」「描けない」を予想して書き留めます。
- 始点を自由に選び、制限時間を決めて挑戦します。時間は1図形あたり3分、または5回までなど、先に決めておきます。行き止まりになったらページを再読み込みして、やり直します。
- 時間内に描けたかどうかと、挑戦回数を記録します。描けたなら、始点と終点も書き留めます。
- 各頂点の次数を紙に書き、奇点の数と連結かどうかを数えます。
- コンソールで odd() を呼び、手計算と合っているか確かめます。
ここで、手順2と手順4の順序を入れ替えないでください。先に数えてしまうと、「数えれば分かる」という発見が、ただの確認作業に変わります。まず試行錯誤の限界を体験し、そのあとで数える流れにします。
予想は、2周行うとさらによいです。1周目は見た目の印象だけで予想します。2周目は、A〜Fの記録がそろってから、まだ試していない自作の図形について、次数を数えて予想します。自作図形は、頂点4〜7個、辺は5〜9本くらいが扱いやすい大きさです。
記録の取り方
記録は、次のような表にまとめます。1行が1図形、1回の実験です。
図形 / 予想(描ける/描けない) / 奇点の数(手計算) / 連結か / 挑戦回数 / 描けたか / 始点→終点
記録のコツは3つあります。
- 予想は、挑戦する前に書きます。あとから書くと、結果に引きずられた記録になります。
- 次数は、頂点ごとに書き出します。「だいたい偶数だった」という記憶では、数え間違いが残ります。
- 描けなかった場合は、どこで行き止まりになったかも書きます。行き止まりの頂点が、残りの辺と無関係な場所なら、始点の選び方に原因がある場合があります。
各図形の挑戦は、できれば異なる始点で数回ずつ行います。始点によって成否が変わるのか、変わらないのかも観察の対象です。
結果の読み方
記録がそろったら、列を横に見て、次の順番で判断します。
予想と実際を比べる
予想が外れた図形に印を付けます。外れが多い図形の共通点を探します。たとえばCやFのように、辺が多く交差する図形で外れやすいかどうかを見ます。
数え方の予言を比べる
「連結であり、かつ奇点が0個か2個」という条件で予言した成否と、実際の成否を比べます。判断の目安は次のとおりです。
- 予言と実際がすべて一致していれば、この条件は、この6図形では説明に使えます。
- 奇点が2個の図形で、描けた記録がある場合は、始点と終点がその2つの奇点になっているか確かめます。
- 奇点が0個で描けた図形は、始点に戻って終わっているか確かめます。
- 一致しない行があれば、まず数え間違いを疑います。次に、辺の入力ミスや頂点番号の取り違えを疑います。それでも合わないときは、条件の側を疑い、その図形を紙に描き直して見直します。
「描けなかった」の意味を比べる
挑戦回数が多いのに描けなかった図形について、奇点の数が4個以上だったか、連結でなかったかを確認します。ここで、描けなかった理由が数えて説明できるなら、試行回数を増やす必要はありません。数えた結果と挑戦の記録が一緒になったとき、「試して描けない」と「条件から描けない」の違いが、手元のデータで見えてきます。
起こりやすい誤り
実験の結果をゆがめやすい誤りを挙げます。
- 連結かどうかを忘れる:Dは、各頂点の次数がすべて偶数です。それでも、2つの三角形は離れています。次数だけを見て予言すると、外れやすい図形です。
- 交点を頂点と数える:Cの対角線の交点は頂点ではありません。次数は頂点にだけ付きます。交点を頂点に追加したい場合は、P に頂点を足して辺を分割し、別の図形として記録します。
- 多重辺や自己ループの扱い:同じ2頂点を結ぶ辺を2回書くと、2本の辺として数えます。画面上は重なって見えるので、E の件数と画面の見た目がずれます。自分の頂点にもどるループは、次数に2を足して数えます。
- ヒントなしの限界を理解しない:描けなかった回数を数えるだけでは、描けない証拠になりません。必ず次数を数えてから、結論を書いてください。
- 入力ミス:E の頂点番号を1つ間違えると、図形そのものが変わります。画面の見た目と、辺リストの両方を確認してください。
- 座標が近すぎる:頂点の判定半径は14ピクセルです。頂点同士が近いと、思った頂点を選べません。頂点は離して置いてください。
次の行動
まず、index.html を作って図形Bで動作を確かめ、A〜Fの記録表を紙に用意してください。予想欄を先に埋めてから挑戦を始めます。最後に、自作図形を1つ作り、次数を数えて、試す前に成否を予想してみてください。
作ったものをアソバースに投稿する場合は、直下の index.html を入口にして HTML のまま、またはZIPで上げられます。投稿は入力、表示の確認、公開の3段階で進み、公開にはメールアドレスの確認が必要です。「奇点を数えるとどうなるか」を遊びとして見せる仕組みを、ぜひ自分の作品に育ててみてください。

