xxxxxxxxxx
190
// Global variables
let gridSize = 20;
let cellSize = 20;
let snake;
let food;
// p5.js setup and draw functions
function setup() {
createCanvas(gridSize * cellSize, gridSize * cellSize);
snake = new Snake();
food = new Food();
frameRate(10);
}
function draw() {
background(220);
drawGrid();
// AI logic for the snake to play itself
// Update and display the snake and food
snake.update();
snake.show();
food.show();
autoPlay();
// Check for collisions
if (snake.eat(food)) {
food = new Food();
}
if (snake.collide()) {
// End the game or reset the snake
}
}
// Helper functions
function drawGrid() {
stroke(200);
for (let i = 0; i < gridSize; i++) {
for (let j = 0; j < gridSize; j++) {
line(i * cellSize, 0, i * cellSize, gridSize * cellSize);
line(0, j * cellSize, gridSize * cellSize, j * cellSize);
}
}
}
// Snake class
class Snake {
constructor() {
this.body = [];
this.body[0] = createVector(floor(gridSize / 2) * cellSize, floor(gridSize / 2) * cellSize);
this.xdir = 1;
this.ydir = 0;
this.size = cellSize;
}
// Update the snake's position
update() {
let head = this.body[this.body.length - 1].copy();
head.x += this.xdir * cellSize;
head.y += this.ydir * cellSize;
this.body.shift();
this.body.push(head);
}
// Display the snake on the canvas
show() {
fill(0);
for (let i = 0; i < this.body.length; i++) {
rect(this.body[i].x, this.body[i].y, this.size, this.size);
}
}
// Set the snake's direction
setDirection(x, y) {
this.xdir = x;
this.ydir = y;
}
// Check if the snake has collided with itself or the canvas edges
collide() {
let head = this.body[this.body.length - 1];
if (head.x < 0 || head.x >= gridSize * cellSize || head.y < 0 || head.y >= gridSize * cellSize) {
return true;
}
for (let i = 0; i < this.body.length - 1; i++) {
if (head.x === this.body[i].x && head.y === this.body[i].y) {
return true;
}
}
return false;
}
// Check if the snake has eaten the food
eat(food) {
let head = this.body[this.body.length - 1];
if (head.x === food.x && head.y === food.y) {
this.grow();
return true;
}
return false;
}
// Add a new segment to the snake
grow() {
let newSegment = this.body[this.body.length - 1].copy();
this.body.push(newSegment);
}
}
// Food class
class Food {
constructor() {
this.x = floor(random(gridSize)) * cellSize;
this.y = floor(random(gridSize)) * cellSize;
this.size = cellSize;
}
// Display the food on the canvas
show() {
fill(255, 0, 0);
rect(this.x, this.y, this.size, this.size);
}
// Generate a new position for the food
newLocation() {
this.x = floor(random(gridSize)) * cellSize;
this.y = floor(random(gridSize)) * cellSize;
}
// Check if the food is in the same position as any part of the snake
isOnSnake(snake) {
for (let i = 0; i < snake.body.length; i++) {
if (this.x === snake.body[i].x && this.y === snake.body[i].y) {
return true;
}
}
return false;
}
}
function autoPlay() {
let head = snake.body[snake.body.length - 1];
let nextMove = { x: snake.xdir, y: snake.ydir };
let minDist = Infinity;
let dista = 0;
// Check all possible moves (up, down, left, right)
let moves = [
{ x: 0, y: -1 },
{ x: 0, y: 1 },
{ x: -1, y: 0 },
{ x: 1, y: 0 },
];
for (let move of moves) {
let newX = head.x + move.x * cellSize;
let newY = head.y + move.y * cellSize;
let newHead = createVector(newX, newY);
// Skip the move if it causes a collision with the snake's body or the grid borders
if (
newX < 0 ||
newX >= gridSize * cellSize ||
newY < 0 ||
newY >= gridSize * cellSize ||
snake.body.some((segment) => segment.x === newX && segment.y === newY)
) {
continue;
}
// Calculate the distance between the new position and the food
let dista = dist(newHead.x, newHead.y, food.x, food.y);
// Update the best move if the distance is smaller
if (dista < minDist) {
minDist = dista;
nextMove = move;
}
}
// Set the direction of the snake according to the best move
snake.setDirection(nextMove.x, nextMove.y);
}