注意事項
この記事は、ChatGPTに対して
- 問題と解決策の概要
- 例示用のコード
を渡して生成した実験的な記事になります。
概要
ChatGPTを用いてブロック崩しのゲームを実装する方法と、プロンプトの工夫によって生成されるコードの可能性について説明する記事です。
記事に実際に生成されたコードがあるので、手元で動かしてみてください。
動きはしますが、課題が残るような挙動ではありそうです。
ChatGPTを使ってブロック崩しのゲームを生成する方法とプロンプトの形式
ChatGPTを使用してブロック崩しのゲームを生成する際には、特定のプロンプトを用意します。
この例では、プログラマーとしてロールプレイをすることを指示し、ブラウザ上で動作するブロック崩しゲームのプログラムを実装するよう要求されます。
その後、必要なファイルの一覧作成やコード実装を行う手順に従って進めます。
- あなたはプログラマーとしてロールプレイをしてください - [Platform] ... ブラウザ - [Goal] ... ブロック崩し - あなたは、[Goal]のゲームを[Platform]で動かすために必要なプログラムを書く必要があります - ゲームを書くためにあなたは以下の手順に従って行動してください - 必要なファイルの一覧を作成する - 各ファイルに必要なコードを実装する - 実装する場合、キー入力によって動きが与えられる場合には、キー入力を受け取り、それに応じて動きを変えるようにしてください
生成されたコードの構成と機能
ChatGPTによって生成されたコードは、index.html, styles.css, script.jsの3つのファイルで構成されています。
これらのファイルは、ブロック崩しのゲームをブラウザ上で実行するために必要な機能を提供しています。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ブロック崩し</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <canvas id="canvas"></canvas> <script src="script.js"></script> </body> </html>
#canvas { background-color: black; border: solid 1px white; }
// キャンバス要素の取得 const canvas = document.getElementById("canvas"); // キャンバスのコンテキストの取得 const ctx = canvas.getContext("2d"); // ボールの初期位置・半径・速度の設定 let x = canvas.width / 2; let y = canvas.height - 30; let dx = 2; let dy = -2; const ballRadius = 10; // パドルの初期位置・幅・高さの設定 const paddleHeight = 10; const paddleWidth = 75; let paddleX = (canvas.width - paddleWidth) / 2; // パドルの移動用のフラグ let rightPressed = false; let leftPressed = false; // ブロックの初期位置・幅・高さの設定 const brickRowCount = 3; const brickColumnCount = 5; const brickWidth = 75; const brickHeight = 20; const brickPadding = 10; const brickOffsetTop = 30; const brickOffsetLeft = 30; // スコア・ライフの初期値の設定 let score = 0; let lives = 3; // ブロックの位置を表す2次元配列の初期化 const bricks = []; for (let c = 0; c < brickColumnCount; c++) { bricks[c] = []; for (let r = 0; r < brickRowCount; r++) { bricks[c][r] = { x: 0, y: 0, status: 1 }; } } // キーイベントのリスナーを追加 document.addEventListener("keydown", keyDownHandler, false); document.addEventListener("keyup", keyUpHandler, false); // キーを押したときに呼ばれる関数 function keyDownHandler(e) { if (e.keyCode === 39) { rightPressed = true; } else if (e.keyCode === 37) { leftPressed = true; } } // キーを離したときに呼ばれる関数 function keyUpHandler(e) { if (e.keyCode === 39) { rightPressed = false; } else if (e.keyCode === 37) { leftPressed = false; } } // 衝突判定の関数 function collisionDetection() { for (let c = 0; c < brickColumnCount; c++) { for (let r = 0; r < brickRowCount; r++) { const b = bricks[c][r]; if (b.status === 1) { if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) { dy = -dy; b.status = 0; score++; if (score === brickRowCount * brickColumnCount) { alert("You win!"); document.location.reload(); } } } } } } // 描画の関数 function draw() { // キャンバス全体をクリア ctx.clearRect(0, 0, canvas.width, canvas.height); // ブロックの描画 for (let c = 0; c < brickColumnCount; c++) { for (let r = 0; r < brickRowCount; r++) { if (bricks[c][r].status === 1) { const brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft; const brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop; bricks[c][r].x = brickX; bricks[c][r].y = brickY; ctx.beginPath(); ctx.rect(brickX, brickY, brickWidth, brickHeight); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } } } // ボールの描画 ctx.beginPath(); ctx.arc(x, y, ballRadius, 0, Math.PI * 2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); // パドルの描画 ctx.beginPath(); ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); // スコアの描画 ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Score: " + score, 8, 20); // ライフの描画 ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Lives: " + lives, canvas.width - 65, 20); // ボールが画面外に出たときの処理 if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) { dx = -dx; } if (y + dy < ballRadius) { dy = -dy; } else if (y + dy > canvas.height - ballRadius) { if (x > paddleX && x < paddleX + paddleWidth) { dy = -dy; } else { lives--; if (!lives) { alert("Game over"); document.location.reload(); } else { x = canvas.width / 2; y = canvas.height - 30; dx = 3; dy = -3; paddleX = (canvas.width - paddleWidth) / 2; } } } // パドルの移動 if (rightPressed && paddleX < canvas.width - paddleWidth) { paddleX += 7; } else if (leftPressed && paddleX > 0) { paddleX -= 7; } // ボールの移動 x += dx; y += dy; // 衝突判定の呼び出し collisionDetection(); // 次のフレームの描画をリクエスト requestAnimationFrame(draw); } // 初期描画の呼び出し draw();
コードの不完全な部分と改善方法
生成されたコードはほぼ動作するものの、一部のコードが未定義であることが課題です。
これは、GPT-3.5が学習データに基づいてコードを生成しているため、ブロック崩しに関連するデータが多く含まれている可能性があります。
不完全な部分を改善するためには、コードの修正や追加が必要です。
今回の場合は、以下の画像の部分のみが不足していたコードでした。
プロンプトの工夫がコード生成の精度に与える影響
プロンプトや質問の仕方を工夫することで、より正確なコードが生成される可能性があります。
ChatGPTは、与えられたプロンプトに応じて異なる結果を生成するため、プロンプトの最適化によってコード生成の精度が向上することが期待されます。
結論
ChatGPTを用いてブロック崩しのゲームを実装する方法と、プロンプトの工夫によって生成されるコードの可能性を学びました。この知識を活かして、さらに多様なプロジェクトに取り組むことができるでしょう。