お久しぶりです。前回投稿が2022-08-15なので、サボりすぎですね…
情報のインプットは好奇心から頑張れるというか知識を得るのが楽しいのでやるんですが、情報のアウトプットって既に知っている知識を使うことなので気が進まないものですよね…定着させるには大事なんですが、特に定着させるモチベーションもなく…
ただ、やっとそのアウトプットを勝手にやってくれる時代がやってきました。そうChatGPTです。こやつにコンテンツを作ってもらう取り組みがどれくらい続くかチャレンジをやってみようと思い、ChatGTP Plus課金しちゃいました!
こやつを使って今日はテトリス作っちゃいます!
完成形 テトリスって、どんなブロックがあってどういうふうに回転してどこで壁にぶつかってとか、まじめに実装すると考えることいっぱいあるのですが、そんなことを考えずに一瞬で作ってくれました。天才です。
が、それを作ってから手直ししていく過程が大変だったので、会話の過程をご覧いただけたらと思います。
会話highlight 一瞬でコード書けるスーパーエンジニア ## USER # 命令書: あなたはフロントエンドエンジニアです。 以下の制約条件と入力文をもとにゲームのソースコードを出力してください。 # 制約条件: * HTML、CSS、Javascriptのみで動く # 入力文: テトリス # 出力文: 深津式プロンプト(https://chatgpt-lab.com/n/ne1643b7f10e6)を使ってみようとしたのですが、大して制約条件を書くことなく出力しちゃいました。
index.html を作って動かしたらこれ
もうエンジニアいらんやん…
すぐ解決策に走る初心者エンジニア なんか右の画面いっぱいまでブロックが動かせなくて質問するのですが…
これやっても直りませんでした。どこが問題かを分析せず解決策に走る初心者エンジニアみたいです。でも、根気よく質問すると…
ちゃんとうごきました!
「コード見せて」といってくるベテランエンジニア 「次のブロックを表示」という機能追加もちょっとバグっていて、いろいろ質問して直そうとしたのですが
なかなか直らないとみたやコード全体を要求してきました。今度はこっちがなかなかバグを治せない初心者エンジニアみたいです…
かわいい 最後にお礼にコードレビューしてみると…? GPT-4の使用上限にひっかかって、GPT-3.5になりました。。。コンテキストをちゃんと解釈してくれてない回答感ありますよね…KY…
ChatGPTと喋った内容 Takaaki # 命令書: あなたはフロントエンドエンジニアです。 以下の制約条件と入力文をもとにゲームのソースコードを出力してください。 # 制約条件: * HTML、CSS、Javascriptのみで動く # 入力文: テトリス # 出力文: ChatGPT 以下は、HTML、CSS、Javascriptを使用してテトリスゲームを実装するための簡単なソースコードです。このコードをhtmlファイルにコピーして実行することができます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>テトリス</title> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } canvas { border: 1px solid #000; } </style> </head> <body> <canvas id="game" width="320" height="640"></canvas> <script> const canvas = document.getElementById("game"); const context = canvas.getContext("2d"); const scale = 20; context.scale(scale, scale); const arenaSweep = () => { outer: for (let y = arena.length - 1; y > 0; y--) { for (let x = 0; x < arena[y].length; x++) { if (!arena[y][x]) { continue outer; } } const row = arena.splice(y, 1)[0].fill(0); arena.unshift(row); ++y; } }; const collide = (arena, player) => { const [m, o] = [player.matrix, player.pos]; for (let y = 0; y < m.length; ++y) { for (let x = 0; x < m[y].length; ++x) { if (m[y][x] && (arena[y + o.y] && arena[y + o.y][x + o.x]) !== 0) { return true; } } } return false; }; const createMatrix = (w, h) => { const matrix = []; while (h--) { matrix.push(new Array(w).fill(0)); } return matrix; }; const draw = () => { context.fillStyle = "#000"; context.fillRect(0, 0, canvas.width, canvas.height); drawMatrix(arena, { x: 0, y: 0 }); drawMatrix(player.matrix, player.pos); }; const drawMatrix = (matrix, offset) => { matrix.forEach((row, y) => { row.forEach((value, x) => { if (value) { context.fillStyle = "red"; context.fillRect(x + offset.x, y + offset.y, 1, 1); } }); }); }; const merge = (arena, player) => { player.matrix.forEach((row, y) => { row.forEach((value, x) => { if (value) { arena[y + player.pos.y][x + player.pos.x] = value; } }); }); }; const playerDrop = () => { player.pos.y++; if (collide(arena, player)) { player.pos.y--; merge(arena, player); playerReset(); arenaSweep(); } dropCounter = 0; }; const playerMove = (offset) => { player.pos.x += offset; if (collide( #### Takaaki 続けてください #### ChatGPT arena, player)) { player.pos.x -= offset; } }; const playerReset = () => { const pieces = "TJLOSZI"; player.matrix = createPiece(pieces[(pieces.length * Math.random()) | 0]); player.pos.y = 0; player.pos.x = ((arena[0].length / 2) | 0) - ((player.matrix[0].length / 2) | 0); if (collide(arena, player)) { arena.forEach(row => row.fill(0)); alert("ゲームオーバー"); } }; const playerRotate = (dir) => { const pos = player.pos.x; let offset = 1; rotate(player.matrix, dir); while (collide(arena, player)) { player.pos.x += offset; offset = -(offset + (offset > 0 ? 1 : -1)); if (offset > player.matrix[0].length) { rotate(player.matrix, -dir); player.pos.x = pos; return; } } }; const rotate = (matrix, dir) => { for (let y = 0; y < matrix.length; ++y) { for (let x = 0; x < y; ++x) { [matrix[x][y], matrix[y][x]] = [matrix[y][x], matrix[x][y]]; } } if (dir > 0) { matrix.forEach(row => row.reverse()); } else { matrix.reverse(); } }; const createPiece = (type) => { if (type === "T") { return [ [1, 1, 1], [0, 1, 0], [0, 0, 0] ]; } else if (type === "J") { return [ [0, 1, 0], [0, 1, 0], [1, 1, 0] ]; } else if (type === "L") { return [ [0, 1, 0], [0, 1, 0], [0, 1, 1] ]; } else if (type === "O") { return [ [1, 1], [1, 1] ]; } else if (type === "S") { return [ [0, 1, 1], [1, 1, 0], [0, 0, 0] ]; } else if (type === "Z") { return [ [1, 1, 0], [0, 1, 1], [0, 0, 0] ]; } else if (type === "I") { return [ [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0] ]; } }; let dropCounter = 0; let dropInterval = 1000; let lastTime = 0; const update = (time = 0) => { const deltaTime = time - lastTime; lastTime = time; dropCounter += deltaTime; if (dropCounter > dropInterval) { playerDrop(); } draw(); requestAnimationFrame(update); }; #### Takaaki 続けてください #### ChatGPT const arena = createMatrix(10, 20); const player = { pos: { x: 0, y: 0 }, matrix: null }; document.addEventListener("keydown", event => { if (event.keyCode === 37) { playerMove(-1); } else if (event.keyCode === 39) { playerMove(1); } else if (event.keyCode === 40) { playerDrop(); } else if (event.keyCode === 81) { playerRotate(-1); } else if (event.keyCode === 87 || event.keyCode === 38) { playerRotate(1); } }); playerReset(); update(); </script> </body> </html> このコードは、テトリスゲームの基本的な機能を実装しています。プレイヤーは矢印キーを使ってピースを操作し、Qキーで反時計回りに回転、Wキーまたは上矢印キーで時計回りに回転させることができます。行が埋まると消え、ゲームが続行します。ピースがスタックして画面上部に達すると、ゲームオーバーになります。このコードを自由にカスタマイズして、さらに機能を追加したり、見た目を改善したりすることができます。
...