diff --git a/android/gradle.properties b/android/gradle.properties
index 818e87b23b224ced309ae5c147e5ed827826e237..db7a1ee2908d6e94aeb319e1c1b548a8bb245891 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.2
-app.versionCode=2
+app.versionName=0.0.3
+app.versionCode=3
diff --git a/fastlane/metadata/android/en-US/changelogs/3.txt b/fastlane/metadata/android/en-US/changelogs/3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0b66218ab5b5439847f39fbda7b65eaa975e4460
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/3.txt
@@ -0,0 +1 @@
+Add minimal 2 players game
diff --git a/fastlane/metadata/android/fr-FR/changelogs/3.txt b/fastlane/metadata/android/fr-FR/changelogs/3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2785db161132e1dddf3b87dca6b6d7748c29a391
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/3.txt
@@ -0,0 +1 @@
+Ajout du mode 2 joueurs (minimal)
diff --git a/lib/entity/player.dart b/lib/entity/player.dart
new file mode 100644
index 0000000000000000000000000000000000000000..227ab9f9b1b9a10afae27aef719fbb22f499699a
--- /dev/null
+++ b/lib/entity/player.dart
@@ -0,0 +1,65 @@
+import 'dart:math';
+
+import 'package:flutter/cupertino.dart';
+import 'package:tetrisdual/layout/board_painter.dart';
+import 'package:tetrisdual/provider/data.dart';
+
+class Player {
+  int _currentTetrimino = 0;
+
+  Widget buildTetriminoWidget(Data myProvider, double width) {
+    return Container(
+      child: GestureDetector(
+        onTapUp: (details) {
+          pickRandomTetrimino();
+          myProvider.redraw();
+        },
+        child: Container(
+          child: CustomPaint(
+            size: Size(width, width),
+            willChange: false,
+            painter: BoardPainter(_currentTetrimino),
+            isComplex: true,
+            key: Key(_currentTetrimino.toString()),
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget buildManagerWidget() {
+    return Container(
+      margin: EdgeInsets.all(5),
+      child: Column(
+        children: [
+          Text(''),
+        ],
+      ),
+    );
+  }
+
+  Widget buildPlayerBoard(Data myProvider, double boardWidth) {
+    double tetriminoBlockWidth = boardWidth / 2;
+
+    return Row(
+      children: [
+        buildTetriminoWidget(myProvider, tetriminoBlockWidth),
+        buildManagerWidget(),
+      ],
+    );
+  }
+
+  void pickRandomTetrimino() {
+    // ensure new tetrimino is not same as current one
+    int newTetrimino = _currentTetrimino;
+    while (newTetrimino == _currentTetrimino) {
+      newTetrimino = Random().nextInt(5) + 1;
+    }
+
+    _currentTetrimino = newTetrimino;
+  }
+
+  void resetTetrimino() {
+    _currentTetrimino = 0;
+  }
+}
diff --git a/lib/layout/board.dart b/lib/layout/board.dart
index 009bd5fabbb9d49901007c6e4475586c1da51629..06686669b7dd5a6467703196b6c54307ac664282 100644
--- a/lib/layout/board.dart
+++ b/lib/layout/board.dart
@@ -1,32 +1,49 @@
 import 'package:flutter/material.dart';
-import 'package:tetrisdual/layout/board_painter.dart';
 import 'package:tetrisdual/provider/data.dart';
-import 'package:tetrisdual/utils/game_utils.dart';
 
 class Board {
+  static Container activePlayer(Widget playerBoard, bool active) {
+    Color borderColor = active ? Colors.greenAccent : Colors.blueGrey;
+
+    return Container(
+      decoration: BoxDecoration(
+        border: Border.all(
+          color: borderColor,
+          width: 15,
+        ),
+      ),
+      child: playerBoard,
+    );
+  }
+
   static Container buildGameBoard(Data myProvider, double boardWidth) {
+    Widget player1 = new RotatedBox(
+      quarterTurns: 2,
+      child: myProvider.getPlayer(1).buildPlayerBoard(myProvider, boardWidth),
+    );
+    Widget player2 = myProvider.getPlayer(2).buildPlayerBoard(myProvider, boardWidth);
+
+    Widget togglePlayerWidget = GestureDetector(
+      onTapUp: (details) {
+        myProvider.toggleCurrentPlayer();
+        myProvider.getPlayer(myProvider.currentPlayer).pickRandomTetrimino();
+      },
+      child: Text(
+        '🔄',
+        style: TextStyle(
+          fontSize: 50,
+        ),
+      ),
+    );
+
     return Container(
-      margin: EdgeInsets.all(4),
-      padding: EdgeInsets.all(4),
       child: Column(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          Container(
-            child: Center(
-              child: GestureDetector(
-                onTapUp: (details) {
-                  GameUtils.pickRandomTetrimino(myProvider);
-                },
-                child: Container(
-                  child: CustomPaint(
-                    size: Size(boardWidth, boardWidth),
-                    willChange: false,
-                    painter: BoardPainter(myProvider),
-                    isComplex: true,
-                  ),
-                ),
-              ),
-            ),
-          )
+          activePlayer(player1, myProvider.currentPlayer == 1),
+          togglePlayerWidget,
+          activePlayer(player2, myProvider.currentPlayer == 2),
         ],
       ),
     );
diff --git a/lib/layout/board_painter.dart b/lib/layout/board_painter.dart
index 620de7c5c2c4f803a0d593b2467ff3401c382952..47c4d30b8348cdb04366b076d4fa57fb556ca493 100644
--- a/lib/layout/board_painter.dart
+++ b/lib/layout/board_painter.dart
@@ -1,12 +1,11 @@
 import 'dart:math';
 
 import 'package:flutter/material.dart';
-import 'package:tetrisdual/provider/data.dart';
 
 class BoardPainter extends CustomPainter {
-  const BoardPainter(this.myProvider);
+  const BoardPainter(this.currentTetrimino);
 
-  final Data myProvider;
+  final int currentTetrimino;
 
   void drawPixels(List<List<int>> pixels, Canvas canvas, double drawSize, Color pixelColor) {
     int blockWidth = 1;
@@ -69,7 +68,7 @@ class BoardPainter extends CustomPainter {
     canvas.drawRect(rectBackground, paintBackground);
 
     // Add tetrimino
-    switch (myProvider.currentTetrimino) {
+    switch (currentTetrimino) {
       // empty
       case 0:
         break;
diff --git a/lib/layout/game.dart b/lib/layout/game.dart
index d46557140943a7742594cb5b708f278d55fbae12..a12eddeb986da596402a86d4988e38a3e260a562 100644
--- a/lib/layout/game.dart
+++ b/lib/layout/game.dart
@@ -5,42 +5,10 @@ import 'package:tetrisdual/utils/game_utils.dart';
 
 class Game {
   static Container buildGameWidget(Data myProvider, double boardWidth) {
-    bool gameIsFinished = myProvider.isGameFinished;
-
     return Container(
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.center,
-        children: [
-          SizedBox(height: 8),
-          Game.buildTopIndicatorWidget(myProvider),
-          SizedBox(height: 2),
-          Expanded(
-            child: Board.buildGameBoard(myProvider, boardWidth),
-          ),
-          SizedBox(height: 2),
-          Container(
-            child: gameIsFinished ? Game.buildEndGameMessage(myProvider) : SizedBox(height: 2),
-          ),
-        ],
-      ),
-    );
-  }
-
-  static Widget buildTopIndicatorWidget(Data myProvider) {
-    return Table(
-      children: [
-        TableRow(
-          children: [
-            Column(
-              children: [],
-            ),
-            Column(
-              children: [],
-            ),
-          ],
-        ),
-      ],
+      child: !myProvider.isGameFinished
+          ? Board.buildGameBoard(myProvider, boardWidth)
+          : Game.buildEndGameMessage(myProvider),
     );
   }
 
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
index 8d0d68858bf76d56e7617584f96b95ff0e1cf78a..63c76e329b5ff22c9fe7255a0017e447e2abc428 100644
--- a/lib/provider/data.dart
+++ b/lib/provider/data.dart
@@ -1,5 +1,8 @@
+import 'dart:math';
+
 import 'package:flutter/foundation.dart';
 import 'package:shared_preferences/shared_preferences.dart';
+import 'package:tetrisdual/entity/player.dart';
 
 class Data extends ChangeNotifier {
   // Configuration available parameters
@@ -32,7 +35,8 @@ class Data extends ChangeNotifier {
   // Game data
   bool _gameIsRunning = false;
   bool _gameIsFinished = false;
-  int _currentTetrimino = 0;
+  int _currentPlayer = 0;
+  List<Player?> _players = [null, null];
 
   bool get isGameRunning => _gameIsRunning;
   void updateGameIsRunning(bool gameIsRunning) {
@@ -46,15 +50,50 @@ class Data extends ChangeNotifier {
     notifyListeners();
   }
 
-  int get currentTetrimino => _currentTetrimino;
-  void updateCurrentTetrimino(int currentTetrimino) {
-    _currentTetrimino = currentTetrimino;
+  int get currentPlayer => _currentPlayer;
+  void toggleCurrentPlayer() {
+    if (_currentPlayer == 0) {
+      // start game
+      _currentPlayer = 1;
+    } else {
+      // Reset current player tetrimino
+      getCurrentPlayer().resetTetrimino();
+
+      // 1 -> 2 ; 2 -> 1
+      _currentPlayer = 3 - _currentPlayer;
+    }
+    notifyListeners();
+  }
+
+  void enableRandomPlayer() {
+    _currentPlayer = Random().nextInt(2) + 1;
+  }
+
+  Player getPlayer(int playerId) {
+    int playerIndex = playerId - 1;
+    Player? player = _players[playerIndex];
+
+    // Create new player if none
+    if (null == player) {
+      player = new Player();
+      _players[playerIndex] = player;
+    }
+
+    return player;
+  }
+
+  Player getCurrentPlayer() {
+    return getPlayer(currentPlayer);
+  }
+
+  void redraw() {
     notifyListeners();
   }
 
   void resetGame() {
     _gameIsRunning = false;
     _gameIsFinished = false;
+    _players = [new Player(), new Player()];
     notifyListeners();
   }
 }
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index 32d196c5dc9fe498b08c61355cbb83508a9b640d..952fb7ca99c5cc0a9e2458dca70b9c561030f4ad 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -53,11 +53,9 @@ class _HomeState extends State<Home> {
         actions: menuActions,
       ),
       body: SafeArea(
-        child: Center(
-          child: myProvider.isGameRunning
-              ? Game.buildGameWidget(myProvider, boardWidth)
-              : Parameters.buildParametersSelector(myProvider),
-        ),
+        child: myProvider.isGameRunning
+            ? Game.buildGameWidget(myProvider, boardWidth)
+            : Parameters.buildParametersSelector(myProvider),
       ),
     );
   }
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
index 86fcd8ae35cfde461553599f94466ff58462d055..5bd436ba68ef0e2c9943efce9b629e8e90326049 100644
--- a/lib/utils/game_utils.dart
+++ b/lib/utils/game_utils.dart
@@ -1,5 +1,3 @@
-import 'dart:math';
-
 import 'package:tetrisdual/provider/data.dart';
 
 class GameUtils {
@@ -11,14 +9,8 @@ class GameUtils {
     print('Starting game');
 
     myProvider.resetGame();
+    myProvider.enableRandomPlayer();
+    myProvider.getCurrentPlayer().pickRandomTetrimino();
     myProvider.updateGameIsRunning(true);
   }
-
-  static void pickRandomTetrimino(Data myProvider) {
-    int newTetrimino = myProvider.currentTetrimino;
-    while (newTetrimino == myProvider.currentTetrimino) {
-      newTetrimino = Random().nextInt(5) + 1;
-    }
-    myProvider.updateCurrentTetrimino(newTetrimino);
-  }
 }