pourquoi depuis que j'essaie de gérer la taille du serpent qui s'agrandit j'ai cette erreur lorsque je vais sur la page du snake : "Bad state : No element. Qee also : https://fluter/.dev/docs/testing/errors" Voici le code utilisée : import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_snake/models/game_model.dart';

class SnakePage extends StatefulWidget {
  const SnakePage({Key? key}) : super(key: key);

  @override
  State<SnakePage> createState() => _SnakePageState();
}

class _SnakePageState extends State<SnakePage> {
  GameModel gameModel = GameModel();
  Timer? timer;

  @override
  void initState() {
    // TODO: implement initState
    print("start");
    gameModel.start();
    timer = Timer.periodic(Duration(milliseconds: 500), (timer) {
      setState(() {
        gameModel.moveSnake();
      });
    });
  }

  void resetTimer() {
    timer?.cancel();
    timer = Timer.periodic(Duration(milliseconds: 500), (timer) {
      setState(() {
        gameModel.moveSnake();
      });
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.arrow_back),
          onPressed: () {
            // TODO: Implement your back button logic here
            Navigator.pop(context);
          },
        ),
        title: Text('Snake Game. Score: ' + gameModel.score.toString()),
        actions: <Widget>[
          PopupMenuButton<String>(
            onSelected: (String result) {
              // TODO: Implement your menu actions here
            },
            itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
              const PopupMenuItem<String>(
                value: 'Pause',
                child: Text('Pause'),
              ),
              const PopupMenuItem<String>(
                value: 'Replay',
                child: Text('Replay'),
              ),
            ],
          ),
        ],
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            flex: 7,
            child: Container(
              color: Colors.green,
              child: GridView.builder(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 10, // Change this number as per your need
                ),
                itemBuilder: (BuildContext context, int index) {
                  int y = index ~/ GameModel.NB_COLONNES;
                  int x = index - ((index ~/ GameModel.NB_COLONNES) * GameModel.NB_COLONNES);

                  Color cellColor;

                  switch (gameModel.grid[y][x]) {
                    case GameModel.SNAKE_HEAD:
                      cellColor = Colors.yellow;
                      break;
                    case GameModel.SNAKE_BODY:
                      cellColor = Colors.green;
                      break;
                    case GameModel.FOOD:
                      print(index.toString() + " " + x.toString() + " " + y.toString());
                      cellColor = Colors.red;
                      break;
                    default:
                      cellColor = Colors.lightGreen;
                  }

                  return GridTile(
                    child: Container(
                      decoration: BoxDecoration(
                        color: cellColor,
                        border: Border.all(color: Colors.white),
                      ),
                      // TODO: Add your game cell here
                    ),
                  );
                },
                itemCount:
                    GameModel.NB_CASES, // Change this number as per your need
              ),
            ),
          ),
          Expanded(
            flex: 2,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                ElevatedButton(
                  onPressed: () {
                    // TODO: Implement left direction logic
                    setState(() {
                      resetTimer();
                      gameModel.changeDirection(GameModel.DIRECTION_GAUCHE);
                    });
                  },
                  child: Icon(Icons.arrow_left),
                ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    ElevatedButton(
                      onPressed: () {
                        // TODO: Implement up direction logic
                        setState(() {
                          resetTimer();
                          gameModel.changeDirection(GameModel.DIRECTION_HAUT);
                        });
                      },
                      child: Icon(Icons.arrow_upward),
                    ),
                    ElevatedButton(
                      onPressed: () {
                        // TODO: Implement down direction logic
                        setState(() {
                          resetTimer();
                          gameModel.changeDirection(GameModel.DIRECTION_BAS);
                        });
                      },
                      child: Icon(Icons.arrow_downward),
                    ),
                  ],
                ),
                ElevatedButton(
                  onPressed: () {
                    // TODO: Implement right direction logic
                    setState(() {
                      resetTimer();
                      gameModel.changeDirection(GameModel.DIRECTION_DROITE);
                    });
                  },
                  child: Icon(Icons.arrow_right),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
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() {
    if (gameModel.isFood(x, y)) {
      growSnake();
      gameModel.increaseScore();
      gameModel.foodModel.createFood();
    } else {
      bodyPositions.removeLast();
    }
    bodyPositions.insert(0, [x, y]);
    print("new snake head: x: $x, y: $y");
  }

  void moveSnake(int direction) {
    switch (direction) {
      case GameModel.DIRECTION_HAUT:
        if (gameModel.isInGrid(x, y - 1)) {
          gameModel.grid[y][x] = 0;
          y--;
        }
        break;
      case GameModel.DIRECTION_DROITE:
        if (gameModel.isInGrid(x + 1, y)) {
          gameModel.grid[y][x] = 0;
          x++;
        }
        break;
      case GameModel.DIRECTION_BAS:
        if (gameModel.isInGrid(x, y + 1)) {
          gameModel.grid[y][x] = 0;
          y++;
        }
        break;
      case GameModel.DIRECTION_GAUCHE:
        if (gameModel.isInGrid(x - 1, y)) {
          gameModel.grid[y][x] = 0;
          x--;
        }
        break;
    }

    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() {
    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() {}
}
import 'dart:ffi';

import 'package:flutter_snake/models/game_model.dart';

class FoodModel{

  GameModel gameModel;

  FoodModel({required this.gameModel});


  void createFood(){
    List<int> coordinates = GameModel.getRandomCoordinates();
    gameModel.grid[coordinates[1]][coordinates[0]] = GameModel.FOOD;
  }
}