diff --git a/android/gradle.properties b/android/gradle.properties
index 663881258a10822c0b4abc064b6e0bc0ccf48833..81949dfd2077495aaea8a6bc81ad9c75442f9ebb 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.13
-app.versionCode=13
+app.versionName=0.0.14
+app.versionCode=14
diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart
index 369a5f7f9030cee73c12fd6a4e07d88c68f47077..e4d2cf5e93e0b9b57e9cfb5d4f9010b74579456f 100644
--- a/lib/entities/cell.dart
+++ b/lib/entities/cell.dart
@@ -1,23 +1,23 @@
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 
 import '../provider/data.dart';
 
 class Cell {
   int value;
-  final int col;
-  final int row;
   bool isFixed;
   int conflictsCount = 0;
 
   Cell(
     @required this.value,
-    @required this.col,
-    @required this.row,
     @required this.isFixed,
   );
 
-  Container widget(Data myProvider) {
+  static double cellBorderWidth = 3;
+  static Color cellBorderDarkColor = Colors.black;
+  static Color cellBorderLightColor = Colors.grey;
+  static Color cellBorderSelectedColor = Colors.red;
+
+  Container widget(Data myProvider, Border borders, int row, int col) {
     String imageAsset = 'assets/skins/empty.png';
     if (this.value > 0) {
       imageAsset = 'assets/skins/' + myProvider.skin + '_' + this.value.toString() + '.png';
@@ -25,29 +25,9 @@ class Cell {
 
     int size = myProvider.size;
 
-    double borderWidth = 3;
-    Color borderDarkColor = Colors.black;
-    Color borderLightColor = Colors.grey;
-    Color borderSelectedColor = Colors.red;
-    Color backgroundColor = this.getBackgroundColor(myProvider);
-
-    Border borders = Border(
-      top: BorderSide(width: borderWidth, color: ((this.row % size) == 0) ? borderDarkColor : borderLightColor),
-      left: BorderSide(width: borderWidth, color: ((this.col % size) == 0) ? borderDarkColor : borderLightColor),
-      right: BorderSide(width: borderWidth, color: (((this.col + 1) % size) == 0) ? borderDarkColor : borderLightColor),
-      bottom: BorderSide(width: borderWidth, color: (((this.row + 1) % size) == 0) ? borderDarkColor : borderLightColor),
-    );
-
-    if (this.col == myProvider.currentCellCol && this.row == myProvider.currentCellRow) {
-      borders = Border.all(
-        color: borderSelectedColor,
-        width: borderWidth,
-      );
-    }
-
     return Container(
       decoration: BoxDecoration(
-        color: backgroundColor,
+        color: this.getBackgroundColor(myProvider),
         border: borders,
       ),
       child: GestureDetector(
@@ -56,9 +36,9 @@ class Cell {
           fit: BoxFit.fill
         ),
         onTap: () {
-          if (this.col != null && this.row != null) {
-            if (!this.isFixed && (this.col != myProvider.currentCellCol || this.row != myProvider.currentCellRow)) {
-              myProvider.selectCell(this.col, this.row);
+          if (col != null && row != null) {
+            if (!this.isFixed && (col != myProvider.currentCellCol || row != myProvider.currentCellRow)) {
+              myProvider.selectCell(col, row);
             } else {
               myProvider.selectCell(null, null);
             }
@@ -111,12 +91,33 @@ class Cell {
           fit: BoxFit.fill
         ),
         onTap: () {
-          if (this.col != null && this.row != null) {
-            myProvider.updateCellValue(this.col, this.row, this.value);
+          if (myProvider.currentCellCol != null && myProvider.currentCellRow != null) {
+            myProvider.updateCellValue(myProvider.currentCellCol, myProvider.currentCellRow, this.value);
           }
           myProvider.selectCell(null, null);
         },
       )
     );
   }
+
+  static Border getCellBorders(Data myProvider, int row, int col) {
+    int size = myProvider.size;
+
+    Border borders = Border.all(
+      color: cellBorderSelectedColor,
+      width: cellBorderWidth,
+    );
+
+    if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) {
+      borders = Border(
+        top: BorderSide(width: cellBorderWidth, color: ((row % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
+        left: BorderSide(width: cellBorderWidth, color: ((col % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
+        right: BorderSide(width: cellBorderWidth, color: (((col + 1) % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
+        bottom: BorderSide(width: cellBorderWidth, color: (((row + 1) % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
+      );
+    }
+
+    return borders;
+  }
+
 }
diff --git a/lib/layout/board.dart b/lib/layout/board.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cd4905eebcc311c65a44d58f0fe5c507210457cc
--- /dev/null
+++ b/lib/layout/board.dart
@@ -0,0 +1,53 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import '../entities/cell.dart';
+import '../provider/data.dart';
+import '../utils/board_utils.dart';
+
+class Board {
+
+  static Container buildGameBoard(Data myProvider) {
+    Color borderColor = BoardUtils.checkBoardIsSolved(myProvider) ? Colors.green : Colors.orange;
+
+    return Container(
+      margin: EdgeInsets.all(2),
+      padding: EdgeInsets.all(2),
+      decoration: BoxDecoration(
+        color: borderColor,
+        borderRadius: BorderRadius.circular(2),
+        border: Border.all(
+          color: borderColor,
+          width: 2,
+        ),
+      ),
+
+      child: buildGameTileset(myProvider),
+    );
+  }
+
+  static Table buildGameTileset(Data myProvider) {
+    int size = myProvider.size;
+    List cells = myProvider.cells;
+
+    return Table(
+      defaultColumnWidth: IntrinsicColumnWidth(),
+      children: [
+        for (var row = 0; row < pow(size, 2); row++)
+          TableRow(children: [
+            for (var col = 0; col < pow(size, 2); col++)
+              Column(children: [
+                cells[row][col].widget(
+                  myProvider,
+                  Cell.getCellBorders(myProvider, row, col),
+                  row,
+                  col
+                )
+              ]),
+          ]),
+      ]
+    );
+  }
+
+}
diff --git a/lib/layout/game.dart b/lib/layout/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bda08eb0cc9725813dde59daa799e28da34b8974
--- /dev/null
+++ b/lib/layout/game.dart
@@ -0,0 +1,61 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import '../entities/cell.dart';
+import '../layout/board.dart';
+import '../provider/data.dart';
+import '../utils/board_utils.dart';
+
+class Game {
+
+  static Container buildGameWidget(Data myProvider) {
+    return Container(
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Board.buildGameBoard(myProvider),
+          SizedBox(height: 2),
+          Game.buildSelectCellValueBar(myProvider)
+        ],
+      ),
+    );
+  }
+
+
+  static Container buildSelectCellValueBar(Data myProvider) {
+    List cells = myProvider.cells;
+    int size = myProvider.size;
+
+    Color borderColor = Colors.blue;
+
+    bool isCellSelected = (myProvider.currentCellCol != null && myProvider.currentCellRow != null);
+    int maxValue = pow(size, 2) + 1;
+
+    return Container(
+      margin: EdgeInsets.all(2),
+      padding: EdgeInsets.all(2),
+
+      child: Table(
+        defaultColumnWidth: IntrinsicColumnWidth(),
+        children: [
+          TableRow(
+            children: [
+              for (var value = 0; value < maxValue; value++)
+                Column(
+                  children: [
+                    Cell(
+                      isCellSelected ? value : 0,
+                      false
+                    ).widgetUpdateValue(myProvider)
+                  ]
+                ),
+            ]
+          ),
+        ]
+      ),
+    );
+  }
+
+}
diff --git a/lib/layout/parameters.dart b/lib/layout/parameters.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b4bb302380b2f77ad5baedf5a5c40422f3ee2e59
--- /dev/null
+++ b/lib/layout/parameters.dart
@@ -0,0 +1,101 @@
+import 'package:flutter/material.dart';
+
+import '../provider/data.dart';
+import '../utils/game_utils.dart';
+
+class Parameters {
+
+  static const double _parameterButtonSize = 70;
+  static const double _startButtonSize = 150;
+
+  static Container buildParametersSelector(Data myProvider) {
+    return Container(
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          Parameters.buildParameterSelector(myProvider, 'difficulty'),
+          Parameters.buildParameterSelector(myProvider, 'size'),
+          Parameters.buildParameterSelector(myProvider, 'skin'),
+
+          Parameters.buildStartGameButton(myProvider),
+        ],
+      ),
+    );
+  }
+
+
+  static Column buildStartGameButton(Data myProvider) {
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        FlatButton(
+          child: Image(
+            image: AssetImage('assets/icons/button_start.png'),
+            width: _startButtonSize,
+            height: _startButtonSize,
+            fit: BoxFit.fill
+          ),
+          onPressed: () => GameUtils.startGame(myProvider),
+        )
+      ],
+    );
+  }
+
+
+  static Column buildParameterSelector(Data myProvider, String parameterCode) {
+    List availableValues = myProvider.getParameterAvailableValues(parameterCode);
+
+    return Column(
+      children: [
+        Table(
+          defaultColumnWidth: IntrinsicColumnWidth(),
+          children: [
+            TableRow(
+              children: [
+                for (var index = 0; index < availableValues.length; index++)
+                  Column(
+                    children: [
+                      _buildParameterButton(myProvider, parameterCode, availableValues[index])
+                    ]
+                  ),
+              ],
+            ),
+          ],
+        ),
+        SizedBox(height: 20),
+      ]
+    );
+  }
+
+
+  static FlatButton _buildParameterButton(Data myProvider, String parameterCode, var parameterValue) {
+    String currentValue = myProvider.getParameterValue(parameterCode).toString();
+
+    bool isActive = (parameterValue.toString() == currentValue);
+    String imageAsset = 'assets/icons/' + parameterCode + '_' + parameterValue.toString() + '.png';
+
+    return FlatButton(
+      child: Container(
+        decoration: BoxDecoration(
+          color: Colors.white,
+          borderRadius: BorderRadius.circular(10),
+          border: Border.all(
+            color: isActive ? Colors.blue : Colors.white,
+            width: 10,
+          ),
+        ),
+        child: Image(
+          image: AssetImage(imageAsset),
+          width: _parameterButtonSize,
+          height: _parameterButtonSize,
+          fit: BoxFit.fill
+        ),
+      ),
+      onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
+    );
+  }
+
+
+}
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index ce7543317a7ebe0e2fe312e842ef1a6b2a35d5e1..7b5b549216bebe778c83bbd47726e3cf36916fe2 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -1,422 +1,14 @@
-import 'dart:math';
-
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
-import '../entities/cell.dart';
+import '../layout/game.dart';
+import '../layout/parameters.dart';
 import '../provider/data.dart';
-import '../utils/random_pick_grid.dart';
+import '../utils/game_utils.dart';
 
 class Home extends StatelessWidget {
   static const String id = 'home';
 
-  static const double _parameterButtonSize = 70;
-  static const double _startButtonSize = 150;
-
-  Future<void> resetGame(Data myProvider) async {
-    myProvider.updateStateRunning = false;
-  }
-
-  Future<void> startGame(Data myProvider) async {
-    myProvider.updateStateRunning = true;
-    myProvider.updateCells = createEmptyBoard(myProvider.size);
-    pickGrid(myProvider);
-  }
-
-  printGrid(List cells) {
-    print('');
-    print('-------');
-    for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
-      String row = '';
-      for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
-        row += cells[rowIndex][colIndex].value.toString();
-      }
-      print(row);
-    }
-    print('-------');
-    print('');
-  }
-
-  Future<void> pickGrid(Data myProvider) async {
-    int size = myProvider.size;
-
-    String grid;
-    RandomPickGrid randomPickGrid;
-
-    randomPickGrid = RandomPickGrid();
-    await randomPickGrid.init(myProvider.level, size);
-
-    if (randomPickGrid.grid != null) {
-      grid = randomPickGrid.grid;
-    }
-
-    if (grid.length == pow(size, 4)) {
-      myProvider.updateCells = createBoardFromTemplate(grid);
-    }
-  }
-
-  List createBoardFromTemplate(String grid) {
-    List cells = [];
-    int size = int.parse(pow(grid.length, 1/4).toStringAsFixed(0));
-    int sideLength = pow(size, 2);
-
-    int index = 0;
-    for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
-      List row = [];
-      for (var colIndex = 0; colIndex < sideLength; colIndex++) {
-        int value = int.parse(grid[index++]);
-        row.add(Cell(value, colIndex, rowIndex, (value != 0)));
-      }
-      cells.add(row);
-    }
-
-    List<String> allowedFlip = ['', 'horizontal', 'vertical'];
-    List<String> allowedRotate = ['', 'left', 'right'];
-
-    var rand = new Random();
-    String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
-    String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
-
-    switch(flip) {
-      case 'horizontal': {
-        List transformedBoard = createEmptyBoard(size);
-        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
-          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
-            transformedBoard[rowIndex][colIndex].value = cells[sideLength - rowIndex - 1][colIndex].value;
-          }
-        }
-        cells = transformedBoard;
-      }
-      break;
-      case 'vertical': {
-        List transformedBoard = createEmptyBoard(size);
-        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
-          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
-            transformedBoard[rowIndex][colIndex].value = cells[rowIndex][sideLength - colIndex - 1].value;
-          }
-        }
-        cells = transformedBoard;
-      }
-      break;
-    }
-
-    switch(rotate) {
-      case 'left': {
-        List transformedBoard = createEmptyBoard(size);
-        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
-          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
-            transformedBoard[rowIndex][colIndex].value = cells[colIndex][sideLength - rowIndex - 1].value;
-          }
-        }
-        cells = transformedBoard;
-      }
-      break;
-      case 'right': {
-        List transformedBoard = createEmptyBoard(size);
-        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
-          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
-            transformedBoard[rowIndex][colIndex].value = cells[sideLength - colIndex - 1][rowIndex].value;
-          }
-        }
-        cells = transformedBoard;
-      }
-      break;
-    }
-
-    // Fix cells fixed states
-    for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
-      for (var colIndex = 0; colIndex < sideLength; colIndex++) {
-        cells[rowIndex][colIndex].isFixed = (cells[rowIndex][colIndex].value != 0) ? true : false;
-      }
-    }
-
-    return cells;
-  }
-
-  List createEmptyBoard(int size) {
-    int index = 0;
-    List cells = [];
-    for (var rowIndex = 0; rowIndex < pow(size, 2); rowIndex++) {
-      List row = [];
-      for (var colIndex = 0; colIndex < pow(size, 2); colIndex++) {
-        row.add(Cell(0, colIndex, rowIndex, false));
-      }
-      cells.add(row);
-    }
-
-    return cells;
-  }
-
-  Container _buildParametersSelector(Data myProvider) {
-    return Container(
-      child: Column(
-        mainAxisSize: MainAxisSize.min,
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          _buildParameterSelector(myProvider, 'difficulty'),
-          _buildParameterSelector(myProvider, 'size'),
-          _buildParameterSelector(myProvider, 'skin'),
-
-          _buildStartGameButton(myProvider),
-        ],
-      ),
-    );
-  }
-
-  Column _buildStartGameButton(Data myProvider) {
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        FlatButton(
-          child: Image(
-            image: AssetImage('assets/icons/button_start.png'),
-            width: _startButtonSize,
-            height: _startButtonSize,
-            fit: BoxFit.fill
-          ),
-          onPressed: () => startGame(myProvider),
-        )
-      ],
-    );
-  }
-
-  Column _buildParameterSelector(Data myProvider, String parameterCode) {
-    List availableValues = myProvider.getParameterAvailableValues(parameterCode);
-
-    return Column(
-      children: [
-        Table(
-          defaultColumnWidth: IntrinsicColumnWidth(),
-          children: [
-            TableRow(
-              children: [
-                for (var index = 0; index < availableValues.length; index++)
-                  Column(
-                    children: [
-                      _buildParameterButton(myProvider, parameterCode, availableValues[index])
-                    ]
-                  ),
-              ],
-            ),
-          ],
-        ),
-        SizedBox(height: 20),
-      ]
-    );
-  }
-
-  FlatButton _buildParameterButton(Data myProvider, String parameterCode, var parameterValue) {
-    String currentValue = myProvider.getParameterValue(parameterCode).toString();
-
-    bool isActive = (parameterValue.toString() == currentValue);
-    String imageAsset = 'assets/icons/' + parameterCode + '_' + parameterValue.toString() + '.png';
-
-    return FlatButton(
-      child: Container(
-        decoration: BoxDecoration(
-          color: Colors.white,
-          borderRadius: BorderRadius.circular(10),
-          border: Border.all(
-            color: isActive ? Colors.blue : Colors.white,
-            width: 10,
-          ),
-        ),
-        child: Image(
-          image: AssetImage(imageAsset),
-          width: _parameterButtonSize,
-          height: _parameterButtonSize,
-          fit: BoxFit.fill
-        ),
-      ),
-      onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
-    );
-  }
-
-  Container _buildGameWidget(Data myProvider) {
-    return Container(
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          _buildGameBoard(myProvider),
-          SizedBox(height: 2),
-          _buildSelectCellValueBar(myProvider)
-        ],
-      ),
-    );
-  }
-
-  Container _buildGameBoard(Data myProvider) {
-    List cells = myProvider.cells;
-    int size = myProvider.size;
-
-    Color borderColor = _checkBoardIsSolved(myProvider) ? Colors.green : Colors.orange;
-
-    return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
-      decoration: BoxDecoration(
-        color: borderColor,
-        borderRadius: BorderRadius.circular(2),
-        border: Border.all(
-          color: borderColor,
-          width: 2,
-        ),
-      ),
-
-      child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
-        children: [
-          for (var row = 0; row < pow(size, 2); row++)
-            TableRow(children: [
-              for (var col = 0; col < pow(size, 2); col++)
-                Column(children: [
-                  cells[row][col].widget(myProvider)
-                ]),
-            ]),
-        ]
-      ),
-    );
-  }
-
-  Container _buildSelectCellValueBar(Data myProvider) {
-    List cells = myProvider.cells;
-    int size = myProvider.size;
-
-    Color borderColor = Colors.blue;
-
-    bool isCellSelected = (myProvider.currentCellCol != null && myProvider.currentCellRow != null);
-
-    return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
-
-      child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              for (var value = 0; value < (pow(size, 2) + 1); value++)
-                Column(
-                  children: [
-                    Cell(
-                      isCellSelected ? value : 0,
-                      isCellSelected ? myProvider.currentCellCol : null,
-                      isCellSelected ? myProvider.currentCellRow : null,
-                      false
-                    ).widgetUpdateValue(myProvider)
-                  ]
-                ),
-            ]
-          ),
-        ]
-      ),
-    );
-  }
-
-  bool _checkBoardIsSolved(Data myProvider) {
-    List cells = myProvider.cells;
-    int size = myProvider.size;
-    int sideLength = pow(size, 2);
-
-    bool isSolved = true;
-
-    // reset conflict states
-    for (var row = 0; row < sideLength; row++) {
-      for (var col = 0; col < sideLength; col++) {
-        cells[row][col].conflictsCount = 0;
-      }
-    }
-
-    // check grid is fully completed
-    for (var row = 0; row < sideLength; row++) {
-      for (var col = 0; col < sideLength; col++) {
-        if (cells[row][col].value == 0) {
-          isSolved = false;
-        }
-      }
-    }
-
-    // check lines does not contains a value twice
-    for (var row = 0; row < sideLength; row++) {
-      List values = [];
-      for (var col = 0; col < sideLength; col++) {
-        int value = cells[row][col].value;
-        if (value != 0) {
-          values.add(value);
-        }
-      }
-      List distinctValues = values.toSet().toList();
-      if (values.length != distinctValues.length) {
-        print('line ' + row.toString() + ' contains duplicates');
-        // Add line to cells in conflict
-        for (var col = 0; col < sideLength; col++) {
-          cells[row][col].conflictsCount++;
-        }
-        isSolved = false;
-      }
-    }
-
-    // check columns does not contains a value twice
-    for (var col = 0; col < sideLength; col++) {
-      List values = [];
-      for (var row = 0; row < sideLength; row++) {
-        int value = cells[row][col].value;
-        if (value != 0) {
-          values.add(value);
-        }
-      }
-      List distinctValues = values.toSet().toList();
-      if (values.length != distinctValues.length) {
-        print('column ' + col.toString() + ' contains duplicates');
-        // Add column to cells in conflict
-        for (var row = 0; row < sideLength; row++) {
-          cells[row][col].conflictsCount++;
-        }
-        isSolved = false;
-      }
-    }
-
-    // check blocks does not contains a value twice
-    for (var blockRow = 0; blockRow < size; blockRow++) {
-      for (var blockCol = 0; blockCol < size; blockCol++) {
-        List values = [];
-
-        for (var rowInBlock = 0; rowInBlock < size; rowInBlock++) {
-          for (var colInBlock = 0; colInBlock < size; colInBlock++) {
-            int row = (blockRow * size) + rowInBlock;
-            int col = (blockCol * size) + colInBlock;
-            int value = cells[row][col].value;
-            if (value != 0) {
-              values.add(value);
-            }
-          }
-        }
-
-        List distinctValues = values.toSet().toList();
-        if (values.length != distinctValues.length) {
-          print('block [' + blockCol.toString() + ',' + blockRow.toString() + '] contains duplicates');
-          // Add blocks to cells in conflict
-          for (var rowInBlock = 0; rowInBlock < size; rowInBlock++) {
-            for (var colInBlock = 0; colInBlock < size; colInBlock++) {
-              int row = (blockRow * size) + rowInBlock;
-              int col = (blockCol * size) + colInBlock;
-              cells[row][col].conflictsCount++;
-            }
-          }
-          isSolved = false;
-        }
-      }
-    }
-
-    if (isSolved) {
-      print('-> ok sudoku solved!');
-    }
-
-    return isSolved;
-  }
-
   @override
   Widget build(BuildContext context) {
     Data myProvider = Provider.of<Data>(context);
@@ -424,7 +16,7 @@ class Home extends StatelessWidget {
     List<Widget> menuActions = [];
 
     if (myProvider.stateRunning) {
-      menuActions.add(
+      menuActions = [
         FlatButton(
           child: Container(
             decoration: BoxDecoration(
@@ -440,19 +32,18 @@ class Home extends StatelessWidget {
               fit: BoxFit.fill
             ),
           ),
-          onPressed: () { myProvider.updateShowConflicts = !myProvider.showConflicts; },
-        )
-      );
-
-      menuActions.add(
+          onPressed: () {
+            myProvider.updateShowConflicts = !myProvider.showConflicts;
+          },
+        ),
         FlatButton(
           child: Image(
             image: AssetImage('assets/icons/button_back.png'),
             fit: BoxFit.fill
           ),
-          onPressed: () => resetGame(myProvider),
+          onPressed: () => GameUtils.resetGame(myProvider),
         ),
-      );
+      ];
     }
 
     return Scaffold(
@@ -462,7 +53,9 @@ class Home extends StatelessWidget {
       ),
       body: SafeArea(
         child: Center(
-          child: myProvider.stateRunning ? _buildGameWidget(myProvider) : _buildParametersSelector(myProvider)
+          child: myProvider.stateRunning
+            ? Game.buildGameWidget(myProvider)
+            : Parameters.buildParametersSelector(myProvider)
         ),
       )
     );
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
new file mode 100644
index 0000000000000000000000000000000000000000..539bf4da6314131c07774df64324da05e77ecbd8
--- /dev/null
+++ b/lib/utils/board_utils.dart
@@ -0,0 +1,241 @@
+import 'dart:math';
+
+import '../entities/cell.dart';
+import '../utils/random_pick_grid.dart';
+import '../provider/data.dart';
+
+class BoardUtils {
+
+  static printGrid(List cells) {
+    print('');
+    print('-------');
+    for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+      String row = '';
+      for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+        row += cells[rowIndex][colIndex].value.toString();
+      }
+      print(row);
+    }
+    print('-------');
+    print('');
+  }
+
+
+  static Future<void> pickGrid(Data myProvider) async {
+    int size = myProvider.size;
+
+    String grid;
+    RandomPickGrid randomPickGrid;
+
+    randomPickGrid = RandomPickGrid();
+    await randomPickGrid.init(myProvider.level, size);
+
+    if (randomPickGrid.grid != null) {
+      grid = randomPickGrid.grid;
+    }
+
+    if (grid.length == pow(size, 4)) {
+      myProvider.updateCells = BoardUtils.createBoardFromTemplate(grid);
+    }
+  }
+
+
+  static List createEmptyBoard(int size) {
+    int index = 0;
+    List cells = [];
+    for (var rowIndex = 0; rowIndex < pow(size, 2); rowIndex++) {
+      List row = [];
+      for (var colIndex = 0; colIndex < pow(size, 2); colIndex++) {
+        row.add(Cell(0, false));
+      }
+      cells.add(row);
+    }
+
+    return cells;
+  }
+
+
+  static List createBoardFromTemplate(String grid) {
+    List cells = [];
+    int size = int.parse(pow(grid.length, 1/4).toStringAsFixed(0));
+    int sideLength = pow(size, 2);
+
+    int index = 0;
+    for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
+      List row = [];
+      for (var colIndex = 0; colIndex < sideLength; colIndex++) {
+        int value = int.parse(grid[index++]);
+        row.add(Cell(value, (value != 0)));
+      }
+      cells.add(row);
+    }
+
+    List<String> allowedFlip = ['', 'horizontal', 'vertical'];
+    List<String> allowedRotate = ['', 'left', 'right'];
+
+    var rand = new Random();
+    String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
+    String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
+
+    switch(flip) {
+      case 'horizontal': {
+        List transformedBoard = createEmptyBoard(size);
+        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
+          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
+            transformedBoard[rowIndex][colIndex].value = cells[sideLength - rowIndex - 1][colIndex].value;
+          }
+        }
+        cells = transformedBoard;
+      }
+      break;
+      case 'vertical': {
+        List transformedBoard = createEmptyBoard(size);
+        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
+          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
+            transformedBoard[rowIndex][colIndex].value = cells[rowIndex][sideLength - colIndex - 1].value;
+          }
+        }
+        cells = transformedBoard;
+      }
+      break;
+    }
+
+    switch(rotate) {
+      case 'left': {
+        List transformedBoard = createEmptyBoard(size);
+        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
+          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
+            transformedBoard[rowIndex][colIndex].value = cells[colIndex][sideLength - rowIndex - 1].value;
+          }
+        }
+        cells = transformedBoard;
+      }
+      break;
+      case 'right': {
+        List transformedBoard = createEmptyBoard(size);
+        for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
+          for (var colIndex = 0; colIndex < sideLength; colIndex++) {
+            transformedBoard[rowIndex][colIndex].value = cells[sideLength - colIndex - 1][rowIndex].value;
+          }
+        }
+        cells = transformedBoard;
+      }
+      break;
+    }
+
+    // Fix cells fixed states
+    for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
+      for (var colIndex = 0; colIndex < sideLength; colIndex++) {
+        cells[rowIndex][colIndex].isFixed = (cells[rowIndex][colIndex].value != 0) ? true : false;
+      }
+    }
+
+    printGrid(cells);
+
+    return cells;
+  }
+
+
+  static bool checkBoardIsSolved(Data myProvider) {
+    List cells = myProvider.cells;
+    int size = myProvider.size;
+    int sideLength = pow(size, 2);
+
+    bool isSolved = true;
+
+    // reset conflict states
+    for (var row = 0; row < sideLength; row++) {
+      for (var col = 0; col < sideLength; col++) {
+        cells[row][col].conflictsCount = 0;
+      }
+    }
+
+    // check grid is fully completed
+    for (var row = 0; row < sideLength; row++) {
+      for (var col = 0; col < sideLength; col++) {
+        if (cells[row][col].value == 0) {
+          isSolved = false;
+        }
+      }
+    }
+
+    // check lines does not contains a value twice
+    for (var row = 0; row < sideLength; row++) {
+      List values = [];
+      for (var col = 0; col < sideLength; col++) {
+        int value = cells[row][col].value;
+        if (value != 0) {
+          values.add(value);
+        }
+      }
+      List distinctValues = values.toSet().toList();
+      if (values.length != distinctValues.length) {
+        print('line ' + row.toString() + ' contains duplicates');
+        // Add line to cells in conflict
+        for (var col = 0; col < sideLength; col++) {
+          cells[row][col].conflictsCount++;
+        }
+        isSolved = false;
+      }
+    }
+
+    // check columns does not contains a value twice
+    for (var col = 0; col < sideLength; col++) {
+      List values = [];
+      for (var row = 0; row < sideLength; row++) {
+        int value = cells[row][col].value;
+        if (value != 0) {
+          values.add(value);
+        }
+      }
+      List distinctValues = values.toSet().toList();
+      if (values.length != distinctValues.length) {
+        print('column ' + col.toString() + ' contains duplicates');
+        // Add column to cells in conflict
+        for (var row = 0; row < sideLength; row++) {
+          cells[row][col].conflictsCount++;
+        }
+        isSolved = false;
+      }
+    }
+
+    // check blocks does not contains a value twice
+    for (var blockRow = 0; blockRow < size; blockRow++) {
+      for (var blockCol = 0; blockCol < size; blockCol++) {
+        List values = [];
+
+        for (var rowInBlock = 0; rowInBlock < size; rowInBlock++) {
+          for (var colInBlock = 0; colInBlock < size; colInBlock++) {
+            int row = (blockRow * size) + rowInBlock;
+            int col = (blockCol * size) + colInBlock;
+            int value = cells[row][col].value;
+            if (value != 0) {
+              values.add(value);
+            }
+          }
+        }
+
+        List distinctValues = values.toSet().toList();
+        if (values.length != distinctValues.length) {
+          print('block [' + blockCol.toString() + ',' + blockRow.toString() + '] contains duplicates');
+          // Add blocks to cells in conflict
+          for (var rowInBlock = 0; rowInBlock < size; rowInBlock++) {
+            for (var colInBlock = 0; colInBlock < size; colInBlock++) {
+              int row = (blockRow * size) + rowInBlock;
+              int col = (blockCol * size) + colInBlock;
+              cells[row][col].conflictsCount++;
+            }
+          }
+          isSolved = false;
+        }
+      }
+    }
+
+    if (isSolved) {
+      print('-> ok sudoku solved!');
+    }
+
+    return isSolved;
+  }
+
+}
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
new file mode 100644
index 0000000000000000000000000000000000000000..dd9d43a09f0296a1207398a708c503c2855e558d
--- /dev/null
+++ b/lib/utils/game_utils.dart
@@ -0,0 +1,15 @@
+import '../provider/data.dart';
+import '../utils/board_utils.dart';
+
+class GameUtils {
+
+  static Future<void> resetGame(Data myProvider) async {
+    myProvider.updateStateRunning = false;
+  }
+
+  static Future<void> startGame(Data myProvider) async {
+    myProvider.updateStateRunning = true;
+    myProvider.updateCells = BoardUtils.createEmptyBoard(myProvider.size);
+    BoardUtils.pickGrid(myProvider);
+  }
+}
diff --git a/lib/utils/random_pick_grid.dart b/lib/utils/random_pick_grid.dart
index aa08feb3b9f389156b938ec0a9ba54c60abef75c..5348f2747aa601da0fa65529413df9443e1ee65d 100644
--- a/lib/utils/random_pick_grid.dart
+++ b/lib/utils/random_pick_grid.dart
@@ -1,4 +1,3 @@
-import 'dart:async';
 import 'dart:convert';
 import 'package:flutter/services.dart';