chatGPTで書いたソース snake
<!DOCTYPE html>
<html>
<head>
<title>Snake Game</title>
<meta charset=”utf-8″>
<link rel=”stylesheet” href=”style.css”>
</head>
<body>
<div class=”container”>
<canvas id=”canvas”></canvas>
<div class=”score”>Score: <span id=”score”>0</span></div>
<button id=”restart-btn”>Restart</button>
</div>
<script>
// Snake
class Snake {
constructor(x, y) {
this.body = [{ x, y }];
this.direction = “right”;
}
move() {
const head = { …this.body[0] };
switch (this.direction) {
case “up”:
head.y -= 1;
break;
case “down”:
head.y += 1;
break;
case “left”:
head.x -= 1;
break;
case “right”:
head.x += 1;
break;
}
this.body.unshift(head);
this.body.pop();
}
grow() {
const head = this.getHead();
this.body.unshift({ …head });
}
getHead() {
return { …this.body[0] };
}
checkCollision(canvasWidth, canvasHeight) {
const head = this.getHead();
if (
head.x < 0 ||
head.x >= canvasWidth ||
head.y < 0 ||
head.y >= canvasHeight
) {
return true;
}
return this.body.slice(1).some(
segment => segment.x === head.x && segment.y === head.y
);
}
}
// Food
class Food {
constructor(canvasWidth, canvasHeight, blockSize) {
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.blockSize = blockSize;
this.respawn();
}
respawn() {
const maxX = Math.floor(this.canvasWidth / this.blockSize);
const maxY = Math.floor(this.canvasHeight / this.blockSize);
this.pos = {
x: Math.floor(Math.random() * maxX) * this.blockSize,
y: Math.floor(Math.random() * maxY) * this.blockSize,
};
}
getPos() {
return { …this.pos };
}
}
// Game
class Game {
constructor(canvas, canvasWidth, canvasHeight, blockSize) {
this.canvas = canvas;
this.ctx = canvas.getContext(“2d”);
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.blockSize = blockSize;
this.snake = new Snake(5, 5);
this.food = new Food(canvasWidth, canvasHeight, blockSize);
this.score = 0;
this.isGameOver = false;
this.init();
}
init() {
this.canvas.width = this.canvasWidth;
this.canvas.height = this.canvasHeight;
this.canvas.style.border = “1px solid #ccc”;
this.canvas.style.background = “#fff”;
document.addEventListener(“keydown”, this.handleInput.bind(this));
const restartBtn = document.getElementById(“restart-btn”);
restartBtn.addEventListener(“click”, () => this.restart());
this.start();
}
start() {
const interval = 100;
const animate = (timestamp) => {
if (!this.lastFrameTime) {
this.lastFrameTime = timestamp;
}
const elapsed = timestamp – this.lastFrameTime;
if (elapsed >= interval) {
this.update();
this.draw();
this.lastFrameTime = timestamp;
}
if (!this.isGameOver) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
}
stop() {
this.isGameOver = true;
}
restart() {
this.snake = new Snake(5, 5);
this.food.respawn();
this.score = 0;
this.updateScore();
if (this.isGameOver) {
this.isGameOver = false;
this.start();
}
}
update() {
if (this.isGameOver) {
return;
}
this.snake.move();
if (this.snake.checkCollision(
this.canvasWidth / this.blockSize,
this.canvasHeight / this.blockSize
)) {
this.stop();
alert(`Game over! Your score is ${this.score}.`);
return;
}
const head = this.snake.getHead();
const foodPos = this.food.getPos();
if (
head.x * this.blockSize === foodPos.x &&
head.y * this.blockSize === foodPos.y
) {
this.snake.grow();
this.food.respawn();
this.score++;
this.updateScore();
}
}
draw() {
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
this.ctx.fillStyle = “#4CAF50”;
this.snake.body.forEach(segment => {
this.ctx.fillRect(
segment.x * this.blockSize,
segment.y * this.blockSize,
this.blockSize,
this.blockSize
);
});
this.ctx.fillStyle = “#f44336”;
this.ctx.fillRect(
this.food.pos.x,
this.food.pos.y,
this.blockSize,
this.blockSize
);
}
handleInput(event) {
const keyMap = {
38: “up”,
40: “down”,
37: “left”,
39: “right”,
};
const newDirection = keyMap[event.keyCode];
if (newDirection) {
this.snake.direction = newDirection;
}
}
updateScore() {
const scoreElem = document.getElementById(“score”);
scoreElem.textContent = this.score;
}
}
const canvas = document.getElementById(“canvas”);
const game = new Game(canvas, 400, 400, 10);
</script>
</body>
</html>