はじめに
こんにちは。
今回は作ってみたシリーズ!第2弾として【オセロ(Step1)】を制作しました。
Step1では盤表示・PlayerとCPU交互に石を置く・CPUのレベル分けまで。
イメージしたゲームはオセロニアです。
仕様
- 正方形の盤であること
- 先攻後攻を選択できること
- オセロのルールを適切に反映していること
テスト
仕様をChatGPTに投げかけコードを生成してもらい、すぐに実行。
見た目はちゃんとオセロになっています。
先攻後攻を選択し、いざゲームをスタート!
「黒色のオセロを置いて白色を挟むと黒色に反転」
オセロのルール通りに反転しました。
また、プロンプトで指示を出していないが、黒色と白色の石の数がリアルタイムで表示される機能も表示されていました。
追加実装
このままでは味気ないのでもう少し機能を追加しようと思います。
まずは、
- 盤のマスが崩れている部分があるので常時正方形になるように
- 石が裏返ったときにマスが光る演出を追加
- CPUのレベル分け
この3つの機能を盛り込みコードを生成!
石が裏返ったときにマスが光る演出を追加
裏返ったマスが光る演出の構成はCSSとJavaScriptにてくみ上げています。
裏返す座標ごとに.flashを一瞬付与して発光、石に.flipをつけてY回転。中間で色クラスを入れ替えます。
css /* マス発光 */ .cell{ position: relative; } .cell.flash::after{ content:""; position:absolute; inset:-2px; border-radius:6px; box-shadow:0 0 0 10px rgba(255,255,150,.85); opacity:0; animation:glow .45s ease-out; } @keyframes glow{ 0%{opacity:1; transform:scale(1)} 100%{opacity:0; transform:scale(1.08)} } /* 石フリップ */ .piece{ position:absolute; inset:10%; border-radius:50%; backface-visibility:hidden; will-change:transform; } .piece.black{ background: radial-gradient(circle at 35% 35%, #5a5a5a, #111); } .piece.white{ background: radial-gradient(circle at 35% 35%, #fff, #cfcfcf); } .piece.flip{ transform-style:preserve-3d; animation:flip .28s ease-in-out; } @keyframes flip{ 0%{ transform:rotateY(0) } 50%{ transform:rotateY(90deg) } /* ← この瞬間に色差し替え */ 100%{ transform:rotateY(180deg) } }
JS
const SIZE=8, BLACK=1, WHITE=-1; const boardEl = document.getElementById('board'); function flashCell(x,y){ const cell = boardEl.children[y*SIZE + x]; cell.classList.remove('flash'); void cell.offsetWidth; // リスタート cell.classList.add('flash'); } function flipPiece(el, toColor){ el.classList.add('flip'); setTimeout(()=>{ el.classList.toggle('black', toColor===BLACK); el.classList.toggle('white', toColor===WHITE); }, 140); // 0.28sの半分=50% el.addEventListener('animationend', ()=> el.classList.remove('flip'), {once:true}); }
まだあまりまだ地味ですが、Step1としては十分な成果としました。
Step3までにはオセロニア風を目指します。
CPUのレベル分け
レベルは1~8までに分けました。
コードは少し長いので省略します。
各レベル別の考え方ですが、
Lv | 方針 | 内容 |
---|---|---|
1 | ランダム | 合法手から完全ランダム。デバッグに最適。 |
2 | ランダム(危険マス回避) | X/C(角の隣)を極力避けるフィルタ付きランダム。 |
3 | 貪欲(枚数最大) | flips.length が最大の手。短期は強いが罠に弱い。 |
4 | 貪欲+危険回避+角最優先 | 角は最優先、X/Cは強い減点して選択。 |
5 | 静的位置評価(W) | score = W[y][x] 。角重視、危険マスは低評価。 |
6 | W+枚数+可動性 | W + 10*flips - 3*oppMobility で相手の手数を減らす。 |
7 | 1手先読み(深さ1) | 相手の最善応手を見て悪手を避ける(擬似ミニマックス)。 |
8 | 2手先読み(αβ)+終盤ボーナス | 深さ2のαβ探索。角/確定石/可動性も加点、終盤は重み。 |
このように分けました。
ちなみにレベル3まで対戦しましたがなんとか勝つことができています💦
まとめ
今回はじゃんけんゲームよりも1段階ゲームらしいものを制作できました。
まぁオセロなのでコードもありふれていますし、ゲーム性も単純で比較的難易度も易しく作りやすかったです。
それでも石が裏返しの瞬間にマスが発光する演出やCPUのレベル分けを実装できたときはうれしく思いました。
自分で作ることで、CPUや演出を自由に加えられるのでPlayとは違った楽しさもあります。
次はStep2としてキャラクターを配置して動きを加えたり、もっと演出を強化したりしてより今どきのゲームアプリらしく装飾できたらと思います。
コメント