diff --git a/assets/images/crystal0.png b/assets/images/crystal7.png
similarity index 100%
rename from assets/images/crystal0.png
rename to assets/images/crystal7.png
diff --git a/lib/flame_components/sprites.dart b/lib/flame_components/sprites.dart
deleted file mode 100644
index 6d0c9e9..0000000
--- a/lib/flame_components/sprites.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-import 'package:flame/flame.dart';
-
-Future<void> loadImages() async {
-  final imageNames = [
-    'crystal1.png',
-    'crystal2.png',
-    'crystal3.png',
-    'crystal4.png',
-    'crystal5.png',
-    'crystal6.png',
-    'crystal7.png',
-  ];
-  await Future.wait(imageNames.map((name) => Flame.images.load(name)));
-}
diff --git a/lib/game/board.dart b/lib/game/board.dart
new file mode 100644
index 0000000..34fb86c
--- /dev/null
+++ b/lib/game/board.dart
@@ -0,0 +1,226 @@
+import 'dart:math';
+import 'package:flame/components.dart';
+import 'package:flame/game.dart';
+import 'package:provider/provider.dart';
+import 'tile.dart';
+import 'swap_notifier.dart';
+import 'package:flame/sprite.dart';
+
+class Board extends FlameGame {
+  final List<Sprite> sprites;
+  static const int rows = 8;
+  static const int cols = 8;
+  late double tileSize;
+  List<List<Tile?>> tiles = [];
+  int? selectedRow;
+  int? selectedCol;
+
+  Board({required this.sprites});
+
+  @override
+  Future<void> onLoad() async {
+    super.onLoad();
+
+    tileSize = size.x / cols;
+    _initializeGrid();
+    _removeInitialMatches();
+  }
+
+  void _initializeGrid() {
+    for (int row = 0; row < rows; row++) {
+      List<Tile?> rowTiles = [];
+      for (int col = 0; col < cols; col++) {
+        int spriteIndex = _randomElement();
+        var tile = Tile(
+          sprite: sprites[spriteIndex],
+          spriteIndex: spriteIndex,
+          size: Vector2.all(tileSize),
+          position: Vector2(col * tileSize, row * tileSize),
+          row: row,
+          col: col,
+          onTileTap: handleTileTap,
+        );
+        rowTiles.add(tile);
+        add(tile);
+      }
+      tiles.add(rowTiles);
+    }
+  }
+
+  int _randomElement() {
+    return Random().nextInt(7);
+  }
+
+  void _removeInitialMatches() {
+    bool hasMatches;
+    do {
+      hasMatches = false;
+      for (int row = 0; row < rows; row++) {
+        for (int col = 0; col < cols; col++) {
+          if (_hasMatch(row, col)) {
+            int spriteIndex = _randomElement();
+            tiles[row][col]!.sprite = sprites[spriteIndex];
+            tiles[row][col]!.spriteIndex = spriteIndex;
+            hasMatches = true;
+          }
+        }
+      }
+    } while (hasMatches);
+  }
+
+  void handleTileTap(Tile tappedTile) {
+    int row = tappedTile.row;
+    int col = tappedTile.col;
+
+    if (selectedRow == null || selectedCol == null) {
+      selectedRow = row;
+      selectedCol = col;
+    } else {
+      if (_isAdjacent(selectedRow!, selectedCol!, row, col)) {
+        swapTiles(tiles[selectedRow!][selectedCol!]!, tiles[row][col]!);
+        Future.delayed(const Duration(milliseconds: 300), () {
+          if (!_checkMatches()) {
+            swapTiles(tiles[row][col]!, tiles[selectedRow!][selectedCol!]!);
+          }
+          selectedRow = null;
+          selectedCol = null;
+        });
+      } else {
+        selectedRow = row;
+        selectedCol = col;
+      }
+    }
+  }
+
+  bool _isAdjacent(int row1, int col1, int row2, int col2) {
+    return (row1 == row2 && (col1 - col2).abs() == 1) ||
+        (col1 == col2 && (row1 - row2).abs() == 1);
+  }
+
+  void swapTiles(Tile tile1, Tile tile2) {
+    final tempPosition = tile1.position;
+    final tempRow = tile1.row;
+    final tempCol = tile1.col;
+
+    tile1.position = tile2.position;
+    tile1.row = tile2.row;
+    tile1.col = tile2.col;
+
+    tile2.position = tempPosition;
+    tile2.row = tempRow;
+    tile2.col = tempCol;
+
+    tiles[tile1.row][tile1.col] = tile1;
+    tiles[tile2.row][tile2.col] = tile2;
+
+    tile1.animateMoveTo(tile1.position, () {});
+    tile2.animateMoveTo(tile2.position, () {});
+
+    _checkMatches();
+  }
+
+  bool _checkMatches() {
+    final matches = <List<int>>[];
+    for (int row = 0; row < rows; row++) {
+      for (int col = 0; col < cols; col++) {
+        if (_hasMatch(row, col)) {
+          matches.add([row, col]);
+        }
+      }
+    }
+
+    if (matches.isNotEmpty) {
+      for (final match in matches) {
+        _removeMatchedElements(match[0], match[1]);
+      }
+      _applyGravity();
+      Future.delayed(const Duration(milliseconds: 300), () {
+        _fillEmptySpaces();
+        _checkMatches();
+      });
+      return true;
+    }
+    return false;
+  }
+
+  bool _hasMatch(int row, int col) {
+    final value = tiles[row][col]!.spriteIndex;
+
+    int count = 1;
+    for (int i = col + 1; i < cols && tiles[row][i]!.spriteIndex == value; i++)
+      count++;
+    for (int i = col - 1; i >= 0 && tiles[row][i]!.spriteIndex == value; i--)
+      count++;
+    if (count >= 3) return true;
+
+    count = 1;
+    for (int i = row + 1; i < rows && tiles[i][col]!.spriteIndex == value; i++)
+      count++;
+    for (int i = row - 1; i >= 0 && tiles[i][col]!.spriteIndex == value; i--)
+      count++;
+    return count >= 3;
+  }
+
+  void _removeMatchedElements(int row, int col) {
+    final value = tiles[row][col]!.spriteIndex;
+
+    int left = col;
+    while (left > 0 && tiles[row][left - 1]!.spriteIndex == value) left--;
+    int right = col;
+    while (right < cols - 1 && tiles[row][right + 1]!.spriteIndex == value)
+      right++;
+    if (right - left + 1 >= 3) {
+      for (int i = left; i <= right; i++) {
+        tiles[row][i] = null;
+      }
+    }
+
+    int top = row;
+    while (top > 0 && tiles[top - 1][col]!.spriteIndex == value) top--;
+    int bottom = row;
+    while (bottom < rows - 1 && tiles[bottom + 1][col]!.spriteIndex == value)
+      bottom++;
+    if (bottom - top + 1 >= 3) {
+      for (int i = top; i <= bottom; i++) {
+        tiles[i][col] = null;
+      }
+    }
+  }
+
+  void _applyGravity() {
+    for (int col = 0; col < cols; col++) {
+      int emptyRow = rows - 1;
+      for (int row = rows - 1; row >= 0; row--) {
+        if (tiles[row][col] != null) {
+          if (row != emptyRow) {
+            tiles[emptyRow][col] = tiles[row][col];
+            tiles[emptyRow][col]!.row = emptyRow;
+            tiles[row][col] = null;
+          }
+          emptyRow--;
+        }
+      }
+    }
+  }
+
+  void _fillEmptySpaces() {
+    for (int col = 0; col < cols; col++) {
+      for (int row = rows - 1; row >= 0; row--) {
+        if (tiles[row][col] == null) {
+          int spriteIndex = _randomElement();
+          var tile = Tile(
+            sprite: sprites[spriteIndex],
+            spriteIndex: spriteIndex,
+            size: Vector2.all(tileSize),
+            position: Vector2(col * tileSize, row * tileSize),
+            row: row,
+            col: col,
+            onTileTap: handleTileTap,
+          );
+          tiles[row][col] = tile;
+          add(tile);
+        }
+      }
+    }
+  }
+}
diff --git a/lib/game/match_magic_game.dart b/lib/game/match_magic_game.dart
index 6cba590..a964713 100644
--- a/lib/game/match_magic_game.dart
+++ b/lib/game/match_magic_game.dart
@@ -1,117 +1,23 @@
 import 'package:flame/components.dart';
-import 'package:flame/events.dart';
-import 'package:flame/flame.dart';
 import 'package:flame/game.dart';
-import 'package:match_magic/models/game_state.dart';
 import 'package:flutter/material.dart';
-import 'dart:ui';
+import 'package:provider/provider.dart';
+import 'sprite_loader.dart';
+import 'board.dart';
+import 'swap_notifier.dart';
 
-class MatchMagicGame extends FlameGame with TapDetector {
-  final GameState gameState;
+class MatchMagicGame extends StatelessWidget {
+  final List<Sprite> sprites;
 
-  MatchMagicGame(this.gameState);
-
-  late double tileSize;
-  late double gridWidth;
-  late double gridHeight;
-  late double gridOffsetX;
-  late double gridOffsetY;
-  final Map<String, Sprite> sprites = {};
-  late SpriteComponent selectedTile;
-  bool hasSelectedTile = false;
-  final selectedPaint = Paint()..color = Colors.white.withOpacity(0.5);
+  const MatchMagicGame({required this.sprites, Key? key}) : super(key: key);
 
   @override
-  Future<void> onLoad() async {
-    await super.onLoad();
-    await loadImages();
-    loadGrid();
-  }
-
-  Future<void> loadImages() async {
-    final imageNames = [
-      'crystal1.png',
-      'crystal2.png',
-      'crystal3.png',
-      'crystal4.png',
-      'crystal5.png',
-      'crystal6.png',
-      'crystal0.png',
-    ];
-    for (var name in imageNames) {
-      final sprite = Sprite(await Flame.images.load(name));
-      sprites[name] = sprite;
-    }
-  }
-
-  void loadGrid() {
-    tileSize = size.x / gameState.cols;
-    gridWidth = tileSize * gameState.cols;
-    gridHeight = tileSize * gameState.rows;
-
-    gridOffsetX = (size.x - gridWidth) / 2;
-    gridOffsetY = (size.y - gridHeight) / 2;
-
-    addGrid();
-  }
-
-  void addGrid() {
-    children
-        .whereType<SpriteComponent>()
-        .forEach((component) => component.removeFromParent());
-
-    for (var row = 0; row < gameState.rows; row++) {
-      for (var col = 0; col < gameState.cols; col++) {
-        final value = gameState.grid[row][col];
-        final spriteName = 'crystal$value.png';
-        final sprite = sprites[spriteName];
-        final spriteComponent = SpriteComponent()
-          ..sprite = sprite
-          ..width = tileSize
-          ..height = tileSize
-          ..x = gridOffsetX + col * tileSize
-          ..y = gridOffsetY + row * tileSize;
-        add(spriteComponent);
-      }
-    }
-  }
-
-  @override
-  void render(Canvas canvas) {
-    super.render(canvas);
-    if (hasSelectedTile) {
-      canvas.drawRect(
-        Rect.fromLTWH(
-          selectedTile.x,
-          selectedTile.y,
-          tileSize,
-          tileSize,
-        ),
-        selectedPaint,
-      );
-    }
-  }
-
-  @override
-  void onTapDown(TapDownInfo info) {
-    final x = info.eventPosition.global.x;
-    final y = info.eventPosition.global.y;
-    final col = ((x - gridOffsetX) / tileSize).floor();
-    final row = ((y - gridOffsetY) / tileSize).floor();
-
-    if (col >= 0 && col < gameState.cols && row >= 0 && row < gameState.rows) {
-      if (hasSelectedTile) {
-        gameState.selectElement(row, col);
-        hasSelectedTile = false;
-        addGrid();
-      } else {
-        selectedTile = SpriteComponent()
-          ..x = gridOffsetX + col * tileSize
-          ..y = gridOffsetY + row * tileSize
-          ..width = tileSize
-          ..height = tileSize;
-        hasSelectedTile = true;
-      }
-    }
+  Widget build(BuildContext context) {
+    return ChangeNotifierProvider(
+      create: (_) => SwapNotifier(),
+      child: GameWidget(
+        game: Board(sprites: sprites),
+      ),
+    );
   }
 }
diff --git a/lib/game/sprite_loader.dart b/lib/game/sprite_loader.dart
new file mode 100644
index 0000000..7907be9
--- /dev/null
+++ b/lib/game/sprite_loader.dart
@@ -0,0 +1,11 @@
+import 'package:flame/components.dart';
+
+class SpriteLoader {
+  static Future<List<Sprite>> loadSprites() async {
+    List<Sprite> sprites = [];
+    for (int i = 1; i <= 7; i++) {
+      sprites.add(await Sprite.load('crystal$i.png'));
+    }
+    return sprites;
+  }
+}
diff --git a/lib/game/swap_notifier.dart b/lib/game/swap_notifier.dart
new file mode 100644
index 0000000..20ca3c9
--- /dev/null
+++ b/lib/game/swap_notifier.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'board.dart';
+import 'tile.dart';
+
+class SwapNotifier extends ChangeNotifier {
+  Tile? selectedTile;
+
+  void selectTile(Tile tile, Board board) {
+    if (selectedTile == null) {
+      selectedTile = tile;
+    } else {
+      if (_isNeighbor(selectedTile!, tile)) {
+        board.swapTiles(selectedTile!, tile);
+        selectedTile = null;
+      } else {
+        selectedTile = tile;
+      }
+    }
+    notifyListeners();
+  }
+
+  bool _isNeighbor(Tile tile1, Tile tile2) {
+    return (tile1.row == tile2.row && (tile1.col - tile2.col).abs() == 1) ||
+        (tile1.col == tile2.col && (tile1.row - tile2.row).abs() == 1);
+  }
+}
diff --git a/lib/game/tile.dart b/lib/game/tile.dart
new file mode 100644
index 0000000..d070d03
--- /dev/null
+++ b/lib/game/tile.dart
@@ -0,0 +1,36 @@
+import 'package:flame/components.dart';
+import 'package:flame/effects.dart';
+import 'package:flame/events.dart';
+import 'package:flame/input.dart';
+import 'package:flutter/material.dart';
+
+class Tile extends SpriteComponent with TapCallbacks {
+  int row;
+  int col;
+  int spriteIndex;
+  final void Function(Tile) onTileTap;
+
+  Tile({
+    required Sprite sprite,
+    required this.spriteIndex,
+    required Vector2 size,
+    required Vector2 position,
+    required this.row,
+    required this.col,
+    required this.onTileTap,
+  }) : super(sprite: sprite, size: size, position: position);
+
+  @override
+  bool onTapDown(TapDownEvent event) {
+    onTileTap(this);
+    return true;
+  }
+
+  void animateMoveTo(Vector2 newPosition, VoidCallback onComplete) {
+    add(MoveEffect.to(
+      newPosition,
+      EffectController(duration: 0.5),
+      onComplete: onComplete,
+    ));
+  }
+}
diff --git a/lib/main.dart b/lib/main.dart
index 5364453..b42f2c9 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,12 +1,16 @@
+import 'package:flame/sprite.dart';
 import 'package:flutter/material.dart';
+import 'package:match_magic/game/sprite_loader.dart';
 import 'package:provider/provider.dart';
-import 'package:match_magic/screen/game_screen.dart';
-import 'package:match_magic/models/game_state.dart';
+import 'game/match_magic_game.dart';
+import 'game/swap_notifier.dart';
 
 void main() {
   runApp(
-    ChangeNotifierProvider(
-      create: (context) => GameState(),
+    MultiProvider(
+      providers: [
+        ChangeNotifierProvider(create: (_) => SwapNotifier()),
+      ],
       child: const MyApp(),
     ),
   );
@@ -22,7 +26,34 @@ class MyApp extends StatelessWidget {
       theme: ThemeData(
         primarySwatch: Colors.blue,
       ),
-      home: const GameScreen(),
+      home: const Scaffold(
+        body: MatchMagicGameScreen(),
+      ),
+    );
+  }
+}
+
+class MatchMagicGameScreen extends StatelessWidget {
+  const MatchMagicGameScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder<List<Sprite>>(
+      future: SpriteLoader.loadSprites(),
+      builder: (context, snapshot) {
+        if (snapshot.connectionState == ConnectionState.done) {
+          if (snapshot.hasError) {
+            return Center(child: Text('Error: ${snapshot.error}'));
+          } else if (!snapshot.hasData || snapshot.data == null) {
+            return const Center(child: Text('No sprites found'));
+          } else {
+            final sprites = snapshot.data!;
+            return MatchMagicGame(sprites: sprites);
+          }
+        } else {
+          return const Center(child: CircularProgressIndicator());
+        }
+      },
     );
   }
 }
diff --git a/lib/models/game_state.dart b/lib/models/game_state.dart
deleted file mode 100644
index 094a878..0000000
--- a/lib/models/game_state.dart
+++ /dev/null
@@ -1,163 +0,0 @@
-import 'dart:math';
-import 'package:flutter/material.dart';
-
-class GameState extends ChangeNotifier {
-  final int rows = 8;
-  final int cols = 8;
-  late List<List<int>> grid;
-  int? selectedRow;
-  int? selectedCol;
-
-  GameState() {
-    _initializeGrid();
-  }
-
-  void _initializeGrid() {
-    grid = List.generate(
-        rows, (i) => List.generate(cols, (j) => _randomElement()));
-    _removeInitialMatches();
-  }
-
-  int _randomElement() {
-    return Random().nextInt(6) + 1;
-  }
-
-  void _removeInitialMatches() {
-    bool hasMatches;
-    do {
-      hasMatches = false;
-      for (int i = 0; i < rows; i++) {
-        for (int j = 0; j < cols; j++) {
-          if (_hasMatch(i, j)) {
-            grid[i][j] = _randomElement();
-            hasMatches = true;
-          }
-        }
-      }
-    } while (hasMatches);
-  }
-
-  void selectElement(int row, int col) {
-    if (selectedRow == null || selectedCol == null) {
-      selectedRow = row;
-      selectedCol = col;
-    } else {
-      if (_isAdjacent(selectedRow!, selectedCol!, row, col)) {
-        swapElements(selectedRow!, selectedCol!, row, col);
-        Future.delayed(const Duration(milliseconds: 300), () {
-          if (!_checkMatches()) {
-            swapElements(row, col, selectedRow!, selectedCol!);
-          }
-          selectedRow = null;
-          selectedCol = null;
-          notifyListeners();
-        });
-      } else {
-        selectedRow = row;
-        selectedCol = col;
-      }
-    }
-    notifyListeners();
-  }
-
-  bool _isAdjacent(int row1, int col1, int row2, int col2) {
-    return (row1 == row2 && (col1 - col2).abs() == 1) ||
-        (col1 == col2 && (row1 - row2).abs() == 1);
-  }
-
-  void swapElements(int row1, int col1, int row2, int col2) {
-    final temp = grid[row1][col1];
-    grid[row1][col1] = grid[row2][col2];
-    grid[row2][col2] = temp;
-    notifyListeners();
-  }
-
-  bool _checkMatches() {
-    final matches = <List<int>>[];
-    for (int i = 0; i < rows; i++) {
-      for (int j = 0; j < cols; j++) {
-        if (_hasMatch(i, j)) {
-          matches.add([i, j]);
-        }
-      }
-    }
-
-    if (matches.isNotEmpty) {
-      for (final match in matches) {
-        _removeMatchedElements(match[0], match[1]);
-      }
-      _applyGravity();
-      Future.delayed(const Duration(milliseconds: 300), () {
-        _fillEmptySpaces();
-        _checkMatches();
-      });
-      return true;
-    }
-    return false;
-  }
-
-  bool _hasMatch(int row, int col) {
-    final value = grid[row][col];
-    if (value == 0) return false;
-
-    int count = 1;
-    for (int i = col + 1; i < cols && grid[row][i] == value; i++) count++;
-    for (int i = col - 1; i >= 0 && grid[row][i] == value; i--) count++;
-    if (count >= 3) return true;
-
-    count = 1;
-    for (int i = row + 1; i < rows && grid[i][col] == value; i++) count++;
-    for (int i = row - 1; i >= 0 && grid[i][col] == value; i--) count++;
-    return count >= 3;
-  }
-
-  void _removeMatchedElements(int row, int col) {
-    final value = grid[row][col];
-
-    int left = col;
-    while (left > 0 && grid[row][left - 1] == value) left--;
-    int right = col;
-    while (right < cols - 1 && grid[row][right + 1] == value) right++;
-    if (right - left + 1 >= 3) {
-      for (int i = left; i <= right; i++) {
-        grid[row][i] = 0;
-      }
-    }
-
-    int top = row;
-    while (top > 0 && grid[top - 1][col] == value) top--;
-    int bottom = row;
-    while (bottom < rows - 1 && grid[bottom + 1][col] == value) bottom++;
-    if (bottom - top + 1 >= 3) {
-      for (int i = top; i <= bottom; i++) {
-        grid[i][col] = 0;
-      }
-    }
-  }
-
-  void _applyGravity() {
-    for (int col = 0; col < cols; col++) {
-      int emptyRow = rows - 1;
-      for (int row = rows - 1; row >= 0; row--) {
-        if (grid[row][col] != 0) {
-          if (row != emptyRow) {
-            grid[emptyRow][col] = grid[row][col];
-            grid[row][col] = 0;
-          }
-          emptyRow--;
-        }
-      }
-    }
-  }
-
-  void _fillEmptySpaces() {
-    for (int col = 0; col < cols; col++) {
-      for (int row = rows - 1; row >= 0; row--) {
-        if (grid[row][col] == 0) {
-          grid[row][col] = _randomElement();
-        }
-      }
-    }
-    notifyListeners();
-  }
-}
diff --git a/lib/screen/game_screen.dart b/lib/screen/game_screen.dart
deleted file mode 100644
index 21e8d25..0000000
--- a/lib/screen/game_screen.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-import 'package:flame/game.dart';
-import 'package:flutter/material.dart';
-import 'package:match_magic/models/game_state.dart';
-import 'package:match_magic/game/match_magic_game.dart';
-import 'package:provider/provider.dart';
-
-class GameScreen extends StatelessWidget {
-  const GameScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Consumer<GameState>(
-        builder: (context, gameState, child) {
-          return GameWidget<MatchMagicGame>(
-            game: MatchMagicGame(gameState),
-          );
-        },
-      ),
-    );
-  }
-}
diff --git a/pubspec.yaml b/pubspec.yaml
index 965ba1e..8c02ca0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -68,7 +68,7 @@ flutter:
     - assets/images/crystal4.png
     - assets/images/crystal5.png
     - assets/images/crystal6.png
-    - assets/images/crystal0.png
+    - assets/images/crystal7.png
 
   # An image asset can refer to one or more resolution-specific "variants", see
   # https://flutter.dev/assets-and-images/#resolution-aware