comment permettre au serpent de perdre d'une part en touchant une limite et d'autre part en se mordant la queue (garde un code clean) : import 'package:flutter_snake/models/game_model.dart';

class SnakeModel {
  int x;
  int y;
  int size = 1;
  GameModel gameModel;
  List<List<int>> bodyPositions = [];

  SnakeModel({required this.gameModel, this.x = 0, this.y = 0});

  void reset() {
    x = GameModel.NB_COLONNES ~/ 2;
    y = GameModel.NB_LIGNES ~/ 2;
    size = 2;
    bodyPositions = [
      [x, y],
      [y, x - 1]
    ];
    displaySnake();
  }

  void displaySnake() {
    bodyPositions.insert(0, [x, y]);
    gameModel.grid[y][x] = GameModel.SNAKE_HEAD;
    for (int i = 1; i < bodyPositions.length; i++) {
      gameModel.grid[bodyPositions[i][1]][bodyPositions[i][0]] =
          GameModel.SNAKE_HEAD;
    }
    print("new snake head: x: $x, y: $y");
    print("new snake body: x: ${bodyPositions}");
  }

  void moveSnake(int direction) {
    int newX = x;
    int newY = y;

    switch (direction) {
      case GameModel.DIRECTION_HAUT:
        newY--;
        break;
      case GameModel.DIRECTION_DROITE:
        newX++;
        break;
      case GameModel.DIRECTION_BAS:
        newY++;
        break;
      case GameModel.DIRECTION_GAUCHE:
        newX--;
        break;
    }

    if (!gameModel.isInGrid(newX, newY)) {
      return;
    }

    gameModel.grid[y][x] = 0;
    x = newX;
    y = newY;

    bool ateFood = gameModel.isFood(x, y);
    if (ateFood) {
      growSnake();
      gameModel.increaseScore();
      gameModel.foodModel.createFood();
    } else if (bodyPositions.isNotEmpty && bodyPositions.length > size) {
      List<int> lastBodyPart = bodyPositions.removeLast();
      gameModel.grid[lastBodyPart[1]][lastBodyPart[0]] = 0;
    }

    displaySnake();
  }

  void growSnake() {
    size++;
  }
}
import 'dart:math';

import 'package:flutter_snake/models/food_model.dart';
import 'package:flutter_snake/models/snake_model.dart';

class GameModel {
  static const int NB_CASES = 140;
  static const int NB_LIGNES = 14;
  static const int NB_COLONNES = 10;

  static const int DIRECTION_HAUT = 0;
  static const int DIRECTION_DROITE = 1;
  static const int DIRECTION_BAS = 2;
  static const int DIRECTION_GAUCHE = 3;

  static const int SNAKE_HEAD = 1;
  static const int SNAKE_BODY = 2;
  static const int FOOD = 3;

  int score = 0;
  int currentDirection = DIRECTION_DROITE;

  List<List<int>> grid =
      List.generate(NB_LIGNES, (i) => List.filled(NB_COLONNES, 0));

  late FoodModel foodModel;
  late SnakeModel snakeModel;

  GameModel() {
    foodModel = FoodModel(gameModel: this);
    snakeModel = SnakeModel(gameModel: this);
  }
  // Add your class properties and methods here

  void start() {
    // on réinitialise la matrice
    for (int i = 0; i < NB_LIGNES; i++) {
      for (int j = 0; j < NB_COLONNES; j++) {
        grid[i][j] = 0;
      }
    }
    foodModel.createFood();
    _displaySnakeBody();
  }

  static List<int> getRandomCoordinates() {
    Random random = Random();
    int randomX = random.nextInt(NB_COLONNES);
    int randomY = random.nextInt(NB_LIGNES);
    print("randomX: $randomX, randomY: $randomY");
    return [randomX, randomY];
  }

  void changeDirection(int newDirection) {
    currentDirection = newDirection;
    moveSnake();
  }

  void moveSnake() {
    snakeModel.moveSnake(currentDirection);
  }

  bool isFood(int x, int y) {
    return grid[y][x] == FOOD;
  }

  bool isInGrid(int x, int y) {
    return x >= 0 && x < NB_COLONNES && y >= 0 && y < NB_LIGNES;
  }

  void increaseScore() {
    score++;
  }

  void _displaySnakeBody() {
    if (snakeModel.bodyPositions.isNotEmpty) {
      for (var position in snakeModel.bodyPositions) {
        int y = position[0];
        int x = position[1];
        grid[y][x] = GameModel.SNAKE_BODY;
      }
      var head = snakeModel.bodyPositions.first;
      grid[head[0]][head[1]] = GameModel.SNAKE_HEAD;
    }
  }

  void eatFood() {}
}