
【ゲーム】JavaScript:65 パネル反転チャレンジ
「💡 パネル反転チャレンジ 💡」は、クリックしたパネルとその上下左右のパネルが一緒に反転(ON↔OFF)する仕組みを使った“ライトアウト”風パズルゲームです。全パネルをOFFにできればクリアとなり、クリック手数を競います。
遊び方・操作方法
- スタートボタンを押してゲーム開始。
- 5×5 のグリッド上で、ON状態のパネルは電球マーク💡が表示。
- パネルをクリックすると、そのパネルと上下左右のパネルがON⇄OFFに切り替わる。
- すべてのパネルをOFF状態(電球マークなし)にすればクリア。
- 手数(クリック回数)がそのままスコアに。少ない手数を目指しましょう!
ルール
- 盤面サイズ:5行×5列
- 初期状態:ランダムに12回ほど反転操作を繰り返した状態からスタート
- 操作:パネルをクリックすると「自身+上下左右」の5か所が反転
- クリア条件:全25枚をOFF(電球なし)にする
- スコア:クリック手数(少なければ少ないほど高評価)
🎮ゲームプレイ
以下のリンク先から実際にプレイできます。
65 パネル反転チャレンジ
素材のダウンロード
以下のリンクから使用する素材をダウンロードできます。
panel_flip_challenge_title.png | panel_flip_challenge_bg.png |
---|---|
![]() | ![]() |
ゲーム画面イメージ
プログラム全文(panel_flip_challenge.html)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>💡 パネル反転チャレンジ 💡</title>
<style>
html, body {
margin: 0; padding: 0;
width: 100vw; height: 100vh;
font-family: 'Yu Gothic', 'Meiryo', sans-serif;
background: url('panel_flip_challenge_bg.png') no-repeat center center fixed;
background-size: cover;
}
body {
width: 100vw;
height: 100vh;
overflow: auto;
}
.container {
width: 800px;
margin: 40px auto;
background: rgba(255,255,255,0.96);
border-radius: 22px;
box-shadow: 0 4px 24px rgba(0,0,0,0.13);
padding-bottom: 32px;
min-height: 520px;
position: relative;
}
.title-img {
display: block;
margin: 20px auto 18px auto;
width: 340px;
max-width: 80%;
height: auto;
}
h1 {
text-align: center;
font-size: 2.1em;
margin: 0.6em 0 0.15em 0;
color: #1976d2;
text-shadow: 1px 1px 7px #fff;
letter-spacing: 0.04em;
}
.rule-section {
background: rgba(235,245,255,0.98);
border-radius: 14px;
margin: 28px 32px 14px 32px;
padding: 16px 24px;
box-shadow: 0 2px 8px #4d90fe22;
}
.rule-title {
text-align: center;
font-weight: bold;
font-size: 1.3em;
margin-bottom: 10px;
color: #1976d2;
}
.rule-text {
text-align: left;
font-size: 1.09em;
line-height: 1.65;
color: #174078;
letter-spacing: 0.01em;
}
.btn {
display: block;
margin: 28px auto 0 auto;
padding: 14px 50px;
font-size: 1.2em;
border: none;
border-radius: 28px;
background: linear-gradient(90deg, #87c9fa, #1565c0);
color: #fff;
font-weight: bold;
box-shadow: 0 2px 8px #1976d266;
cursor: pointer;
transition: background 0.2s;
}
.btn:hover { background: linear-gradient(90deg, #b7e4fe, #1976d2); }
.game-area {
width: 740px;
margin: 36px auto 0 auto;
background: rgba(240,248,255,0.96);
border-radius: 16px;
box-shadow: 0 1px 10px #1565c055;
display: flex;
flex-direction: column;
align-items: center;
min-height: 320px;
padding: 16px 0 20px 0;
user-select: none;
}
.info {
text-align: center;
color: #1976d2;
font-size: 1.19em;
margin: 5px 0 0 0;
}
.panel-board {
display: grid;
grid-template-columns: repeat(5, 65px);
grid-gap: 16px 20px;
justify-content: center;
margin-top: 32px;
margin-bottom: 10px;
}
.panel-cell {
width: 65px; height: 65px;
background: #eee;
border: 2.5px solid #1976d2;
border-radius: 14px;
box-shadow: 0 2px 8px #1976d266;
cursor: pointer;
font-size: 2.1em;
display: flex; align-items: center; justify-content: center;
transition: background 0.14s, border-color 0.14s;
user-select: none;
position: relative;
outline: none;
}
.panel-cell.on {
background: #fffde7;
border-color: #ffd600;
color: #ffab00;
box-shadow: 0 0 12px #ffe08277;
}
.panel-cell:active {
background: #c3fdff;
transform: scale(0.96);
}
.message-box {
text-align: center;
background: rgba(235,245,255,0.98);
font-size: 1.7em;
color: #1976d2;
font-weight: bold;
border-radius: 16px;
box-shadow: 0 4px 24px #1976d233;
width: 80%;
max-width: 480px;
margin: 34px auto 0 auto;
padding: 32px 18px;
position: relative;
z-index: 2;
}
.center-btn { margin: 22px auto 0 auto; }
</style>
</head>
<body>
<div class="container" id="main-container"></div>
<script>
// ==========================================
// 💡 パネル反転チャレンジ(ライトアウト風)
// ==========================================
const ROWS = 5, COLS = 5;
let panel = [];
let moveCount = 0;
// タイトル画面表示
function showTitleScreen() {
document.getElementById('main-container').innerHTML = `
<h1>💡 パネル反転チャレンジ 💡</h1>
<img src="panel_flip_challenge_title.png" class="title-img" alt="パネル反転チャレンジ タイトル">
<div class="rule-section">
<div class="rule-title">💡 遊び方・ルール 💡</div>
<div class="rule-text">
・クリックしたパネルと、その上下左右のパネルが反転します。<br>
・すべてのパネルを消灯(OFF)できればクリア!<br>
・手数(クリック回数)が少ないほど高難度!
</div>
</div>
<button class="btn" id="start-btn">スタート</button>
`;
document.getElementById('start-btn').onclick = startGame;
}
// ゲーム開始
function startGame() {
// ランダムな状態からスタート
panel = Array.from({length: ROWS}, ()=>Array(COLS).fill(false));
// 適当にランダムな手でかき混ぜる
for(let i=0; i<12; i++) {
let r = Math.floor(Math.random()*ROWS), c = Math.floor(Math.random()*COLS);
flipPanel(r, c, false);
}
moveCount = 0;
showGameScreen();
}
// ゲーム画面
function showGameScreen() {
let html = `<h1>💡 パネル反転チャレンジ 💡</h1>
<div class="game-area">
<div class="info">パネルをクリックして全てOFFにしよう!(手数: ${moveCount})</div>
<div class="panel-board" id="panel-board"></div>
</div>
`;
document.getElementById('main-container').innerHTML = html;
renderBoard();
}
// パネル描画
function renderBoard() {
let html = "";
for(let r=0; r<ROWS; r++) {
for(let c=0; c<COLS; c++) {
html += `<div class="panel-cell${panel[r][c] ? " on" : ""}" onclick="clickPanel(${r},${c})">${panel[r][c] ? "💡" : ""}</div>`;
}
}
document.getElementById('panel-board').innerHTML = html;
}
// パネル反転処理
function flipPanel(r, c, user=true) {
// 範囲内の時だけ反転
function flip(rr, cc){
if(rr>=0 && rr<ROWS && cc>=0 && cc<COLS){
panel[rr][cc] = !panel[rr][cc];
}
}
flip(r, c); // 自分
flip(r-1, c); // 上
flip(r+1, c); // 下
flip(r, c-1); // 左
flip(r, c+1); // 右
if(user) {
moveCount++;
showGameScreen();
if(checkClear()) {
setTimeout(showEndScreen, 400);
}
}
}
// クリック時
window.clickPanel = function(r, c) {
flipPanel(r, c);
};
// 全OFFかチェック
function checkClear() {
return panel.flat().every(v=>!v);
}
// 終了画面
function showEndScreen() {
document.getElementById('main-container').innerHTML = `
<h1>💡 パネル反転チャレンジ 💡</h1>
<img src="panel_flip_challenge_title.png" class="title-img" alt="パネル反転チャレンジ タイトル">
<div class="message-box">
🎉 全てのパネルを消灯しました!<br>あなたの手数:<b>${moveCount}</b>
</div>
<button class="btn center-btn" id="back-title-btn">タイトル画面に戻る</button>
`;
document.getElementById('back-title-btn').onclick = showTitleScreen;
}
// 初期表示
showTitleScreen();
</script>
</body>
</html>
アルゴリズムの流れ
ステップ | 関数 | 処理内容 |
---|---|---|
1 | showTitleScreen | タイトル画面の描画。ルール&スタートボタン設置。 |
2 | startGame | 盤面を全OFFで初期化→ランダムに12手で反転 → 手数リセット → ゲーム画面表示 |
3 | showGameScreen | ゲーム画面HTML生成 → renderBoard() 呼び出し |
4 | renderBoard | panel 配列を読み込み、各パネル要素をON/OFF状態に応じて描画 |
5 | clickPanel | クリック時に flipPanel(r,c,true) を呼び出し |
6 | flipPanel | 指定パネル+上下左右を反転。user===true なら手数+画面更新+クリア判定 |
7 | checkClear | 全パネルがOFFか判定 |
8 | showEndScreen | クリアメッセージ+手数表示+タイトルに戻るボタン設置 |
関数の詳細
関数名 | 役割 | 説明 |
---|---|---|
showTitleScreen() | タイトル画面描画 | 初期画面をDOM生成。スタートボタンのクリックで startGame() |
startGame() | ゲーム初期化&開始 | 全OFF盤面を用意し、ランダムに12回反転してからゲーム画面を表示 |
showGameScreen() | ゲーム画面生成&描画 | スコア表示と盤面ボード用コンテナを生成、renderBoard() 実行 |
renderBoard() | 盤面(パネル)の描画 | panel の二次元配列を走査し、ON/OFFに応じたパネルDIVを生成しDOMに埋め込む |
flipPanel(r,c,user) | パネル反転ロジック | クリック or 初期シャッフル用に指定パネルと上下左右を反転。user=true 時は手数加算・画面更新・クリア判定 |
clickPanel(r,c) | クリックイベントハンドラ | パネルクリック時に flipPanel(r,c,true) を呼び出し |
checkClear() | クリア判定 | 盤面がすべてOFF(false)の場合に true を返す |
showEndScreen() | 終了画面描画 | クリアメッセージと手数を表示、タイトルに戻るボタン設置 |
改造のポイント
- 難易度設定:初期シャッフル回数(ここでは12)を増減して複雑さを調整。少なめで初心者向け、多めで上級者向けに。
- 盤面サイズの変更:
ROWS
/COLS
を変更して 4×4 や 6×6 モードを追加。 - 手数制限モード:制限手数以内でクリアしないとゲームオーバーにするチャレンジモードを実装。
- 演出強化:反転時のアニメーション(CSSアニメ or JavaScriptでトランジション)、サウンド効果を追加。
- 段階ステージ:複数ステージを用意し、ステージクリアごとにシャッフル回数や盤面を変える「ステージ制」にすると継続プレイ性UP。
アドバイス
まずは反転ロジックとクリア判定をしっかりテストし、安定動作を確保。その後、難易度や演出を段階的に強化すると、ユーザーのモチベーションを維持しやすくなります!