Created
October 20, 2023 19:33
-
-
Save esshka/0e721e7ca89cb84ed5700a0ab1feb1b9 to your computer and use it in GitHub Desktop.
snake game state
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { makeAutoObservable } from 'mobx'; | |
class SnakeGameStore { | |
// Defining the game grid size | |
gridSize = 10; | |
// Defining the snake's initial position and direction | |
snake = [{ x: 5, y: 5 }]; | |
direction = { x: 0, y: 1 }; // Starts moving downwards | |
// Randomly place food on the grid | |
food = { | |
x: Math.floor(Math.random() * this.gridSize), | |
y: Math.floor(Math.random() * this.gridSize), | |
}; | |
constructor() { | |
makeAutoObservable(this); | |
} | |
// Action to move the snake | |
moveSnake = () => { | |
// Calculate new head based on direction | |
const newHead = { | |
x: this.snake[0].x + this.direction.x, | |
y: this.snake[0].y + this.direction.y, | |
}; | |
// Check for collisions with walls or itself | |
if ( | |
newHead.x < 0 || | |
newHead.y < 0 || | |
newHead.x >= this.gridSize || | |
newHead.y >= this.gridSize || | |
this.snake.some(segment => segment.x === newHead.x && segment.y === newHead.y) | |
) { | |
// Reset the game if collision | |
this.resetGame(); | |
return; | |
} | |
// Add the new head to the snake | |
this.snake.unshift(newHead); | |
// Check if snake has eaten food | |
if (newHead.x === this.food.x && newHead.y === this.food.y) { | |
this.placeFood(); // Place new food on the grid | |
} else { | |
// If not, remove the tail segment to keep the snake's length consistent | |
this.snake.pop(); | |
} | |
} | |
// Action to change the direction of the snake | |
setDirection(x, y) { | |
// Prevents the snake from reversing its direction | |
if (-x !== this.direction.x && -y !== this.direction.y) { | |
this.direction = { x, y }; | |
} | |
} | |
// Action to place food randomly on the grid | |
placeFood() { | |
this.food = { | |
x: Math.floor(Math.random() * this.gridSize), | |
y: Math.floor(Math.random() * this.gridSize), | |
}; | |
} | |
// Action to reset the game | |
resetGame() { | |
this.snake = [{ x: 5, y: 5 }]; | |
this.direction = { x: 0, y: 1 }; | |
this.placeFood(); | |
} | |
} | |
export const snakeGameStore = new SnakeGameStore(); | |
import React from 'react'; | |
import { observer } from 'mobx-react-lite'; | |
import { useSnakeGame } from './useSnakeGame'; // Adjust the import path to your hook file | |
const cellSize = 20; // Defines the size of each grid cell in pixels | |
function SnakeGrid() { | |
const { snake, food, moveSnake } = useSnakeGame(); | |
// Call the moveSnake function at regular intervals to make the snake move | |
React.useEffect(() => { | |
const interval = setInterval(moveSnake, 200); | |
return () => clearInterval(interval); | |
}, [moveSnake]); | |
return ( | |
<div style={{ | |
width: cellSize * 10, | |
height: cellSize * 10, | |
border: '1px solid black', | |
position: 'relative' | |
}}> | |
{snake.map((segment, index) => ( | |
<div | |
key={index} | |
style={{ | |
width: cellSize, | |
height: cellSize, | |
backgroundColor: 'green', | |
position: 'absolute', | |
left: segment.x * cellSize, | |
top: segment.y * cellSize, | |
}} | |
></div> | |
))} | |
<div | |
style={{ | |
width: cellSize, | |
height: cellSize, | |
backgroundColor: 'red', | |
position: 'absolute', | |
left: food.x * cellSize, | |
top: food.y * cellSize, | |
}} | |
></div> | |
</div> | |
); | |
} | |
export default observer(SnakeGrid); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment