diff --git a/src/main/kotlin/GameApp.kt b/src/main/kotlin/GameApp.kt
index 704dc5349a562502d84a7f551cc07cb5a34b0462..c981df28697ef0e08a38f91bdc16b26d47b4bb0b 100644
--- a/src/main/kotlin/GameApp.kt
+++ b/src/main/kotlin/GameApp.kt
@@ -8,6 +8,7 @@ import javafx.scene.input.KeyCode
 import javafx.scene.paint.Color
 import builder.*
 import enums.EBehavior
+import enums.EDirection
 
 const val mapWidth : Int = 14
 const val mapHeight : Int = 10
@@ -48,29 +49,33 @@ class GameApp : GameApplication() {
     }
 
     override fun initInput() {
-        onKeyDown(KeyCode.RIGHT) {
+        onKeyDown(KeyCode.UP) {
             var movableObjects = currentLevel.map.cases.filter { obj -> obj != null && obj.behavior == EBehavior.MOVE }
             for (obj in movableObjects) {
-                currentLevel.map.moveRight(obj!!)
+                currentLevel.map.move(obj!!, EDirection.UP)
             }
+            currentLevel.map.checkForBehaviorChange()
         }
-        onKeyDown(KeyCode.LEFT) {
-            var movableObjects = currentLevel.map.cases.filter { obj -> obj != null && obj.behavior == EBehavior.MOVE}
+        onKeyDown(KeyCode.DOWN) {
+            var movableObjects = currentLevel.map.cases.filter { obj -> obj != null && obj.behavior == EBehavior.MOVE }
             for (obj in movableObjects) {
-                currentLevel.map.moveLeft(obj!!)
+                currentLevel.map.move(obj!!, EDirection.DOWN)
             }
+            currentLevel.map.checkForBehaviorChange()
         }
-        onKeyDown(KeyCode.UP) {
-            var movableObjects = currentLevel.map.cases.filter { obj -> obj != null && obj.behavior == EBehavior.MOVE }
+        onKeyDown(KeyCode.LEFT) {
+            var movableObjects = currentLevel.map.cases.filter { obj -> obj != null && obj.behavior == EBehavior.MOVE}
             for (obj in movableObjects) {
-                currentLevel.map.moveUp(obj!!)
+                currentLevel.map.move(obj!!, EDirection.LEFT)
             }
+            currentLevel.map.checkForBehaviorChange()
         }
-        onKeyDown(KeyCode.DOWN) {
+        onKeyDown(KeyCode.RIGHT) {
             var movableObjects = currentLevel.map.cases.filter { obj -> obj != null && obj.behavior == EBehavior.MOVE }
             for (obj in movableObjects) {
-                currentLevel.map.moveDown(obj!!)
+                currentLevel.map.move(obj!!, EDirection.RIGHT)
             }
+            currentLevel.map.checkForBehaviorChange()
         }
         onKeyDown(KeyCode.R) {
             reset()
diff --git a/src/main/kotlin/Map.kt b/src/main/kotlin/Map.kt
index 51731609b465ccc652bec32916ad2108b533cd75..554444218a91e517e8f93d39b5763427b785ffa7 100644
--- a/src/main/kotlin/Map.kt
+++ b/src/main/kotlin/Map.kt
@@ -1,27 +1,23 @@
 import enums.EBehavior
 import enums.EBlock
+import enums.EDirection
 import enums.ESprite
+import observer.ConcretSubject
+import observer.Sprite
 
-class Map() {
-    var width = 0
-    var height = 0
-    var scaleFactor = 0.0
-    lateinit var defaultCases : Array<GameObject?> // Emplacement par défaut utilisé pour le reset
-    lateinit var cases : Array<GameObject?>
-
-    var blockIs: ArrayList<GameObject> = ArrayList()  // IS Blocks
-
-    var subjects: HashMap<ESprite, ConcretSubject> = HashMap() // Subjects for observers (one for each type of sprite)
-
-    constructor(width: Int, height: Int, scaleFactor: Double) : this() {
-        this.width = width
-        this.height = height
-        this.scaleFactor = scaleFactor
-        defaultCases = Array(width*height){null}
-        cases = Array(width*height){null}
-
+class Map(
+    var width: Int = 0,
+    var height: Int = 0,
+    var scaleFactor: Double = 0.0, // Redimension des sprites
+    var defaultCases: Array<GameObject?> = Array(width * height) { null }, // Emplacement initial des cases utilisé par le reset
+    var cases: Array<GameObject?> = Array(width * height) { null },
+    var blockIs: ArrayList<GameObject> = ArrayList(), // Liste des blocks IS pour vérifier les mises à jour de comportement
+    var subjects: HashMap<ESprite, ConcretSubject> = HashMap() // Sujets des observers
+) {
+    init {
+        // Initialisation des observers pour chaque type de sprites
         for (spriteType in ESprite.values()) {
-            subjects.set(spriteType, ConcretSubject())
+            subjects[spriteType] = ConcretSubject()
         }
     }
 
@@ -35,160 +31,76 @@ class Map() {
 
         // Emplacement sur la map
         if (x<=width && y<=height) {
-            cases[y*width + x] = obj
             defaultCases[y*width + x] = obj
+            cases[y*width + x] = obj
         }
     }
 
-    fun moveLeft(obj: GameObject) : Boolean {
+    fun move(obj: GameObject, direction: EDirection) : Boolean {
         var i = cases.indexOf(obj)
-        if (i%width == 0) { // Si l'obj se situe sur la première colonne
-            return false
-        }
-        else if (cases[i-1] != null) { // Si la case de gauche est occupée
-            when (cases[i-1]!!.behavior) {
-                EBehavior.MOVE, EBehavior.PUSH -> {
-                    if (!moveLeft(cases[i-1]!!)) { // On pousse la case de gauche
-                        return false // Sinon
-                    }
-                }
-                EBehavior.STOP -> {
-                    return false
-                }
-                EBehavior.DEFEAT -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        reset()
-                    }
-                    return false
-                }
-                EBehavior.WIN -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        nextLevel()
-                    }
-                    return false
-                }
-            }
-        }
-        // Déplacement
-        cases[i-1] = obj
-        cases[i] = null
-        if (obj.behavior == EBehavior.MOVE) checkForBehaviorChange()
-        // Affichage
-        obj.gameEntity.translateX(-48.0*scaleFactor)
-        return true
-    }
 
-    fun moveRight(obj: GameObject) : Boolean {
-        var i = cases.indexOf(obj)
-        if (i%width == width-1) { // Si l'obj se situe sur la dernière colonne
-            return false
-        }
-        else if (cases[i+1] != null) { // Si la case de droite est occupée
-            when (cases[i+1]!!.behavior) {
-                EBehavior.MOVE, EBehavior.PUSH -> {
-                    if (!moveRight(cases[i + 1]!!)) { // On pousse la case de droite
-                        return false // Sinon
-                    }
-                }
-                EBehavior.STOP -> {
-                    return false
-                }
-                EBehavior.DEFEAT -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        reset()
-                    }
-                    return false
-                }
-                EBehavior.WIN -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        nextLevel()
-                    }
-                    return false
-                }
+        // Code dépendant de la direction
+        var adjacentCaseIndex: Int
+
+        when (direction) {
+            EDirection.UP -> {
+                if (i < width) return false // Si l'objet est sur la première ligne
+                adjacentCaseIndex = i-width
+            }
+            EDirection.DOWN -> {
+                if (i >= width*(height-1)) return false // Si l'objet est sur la dernière ligne
+                adjacentCaseIndex = i+width
+            }
+            EDirection.LEFT -> {
+                if (i%width == 0) return false // Si l'objet est sur la première colonne
+                adjacentCaseIndex = i-1
+            }
+            EDirection.RIGHT -> {
+                if (i%width == width-1) return false // Si l'objet est sur la dernière colonne
+                adjacentCaseIndex = i+1
             }
         }
-        // Déplacement
-        cases[i+1] = obj
-        cases[i] = null
-        if (obj.behavior == EBehavior.MOVE) checkForBehaviorChange()
-        // Affichage
-        obj.gameEntity.translateX(48.0*scaleFactor)
-        return true
-    }
 
-    fun moveUp(obj: GameObject) : Boolean {
-        var i = cases.indexOf(obj)
-        if (i < width) { // Si l'obj se situe sur la première ligne
-            return false
-        }
-        else if (cases[i-width] != null) { // Si la case du dessus est occupée
-            when (cases[i-width]!!.behavior) {
+        // Code commun
+        if (cases[adjacentCaseIndex] != null) { // Si la case de destination est occupée
+            var adjacentCase : GameObject = cases[adjacentCaseIndex]!!
+            when (adjacentCase.behavior) {
                 EBehavior.MOVE, EBehavior.PUSH -> {
-                    if (!moveUp(cases[i - width]!!)) { // On pousse la case du dessus
-                        return false // Sinon
+                    if (!move(adjacentCase, direction)) { // On pousse la case adjacente
+                        return false // Si ce n'est pas possible pas de déplacement
                     }
                 }
-                EBehavior.STOP -> {
-                    return false
-                }
                 EBehavior.DEFEAT -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        reset()
-                    }
+                    if(obj!!.behavior == EBehavior.MOVE) reset()
                     return false
                 }
                 EBehavior.WIN -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        nextLevel()
-                    }
+                    if(obj!!.behavior == EBehavior.MOVE) nextLevel()
                     return false
                 }
+                EBehavior.STOP -> return false
             }
         }
+
         // Déplacement
-        cases[i-width] = obj
+        cases[adjacentCaseIndex] = obj
         cases[i] = null
-        if (obj.behavior == EBehavior.MOVE) checkForBehaviorChange()
-        // Affichage
-        obj.gameEntity.translateY(-48.0*scaleFactor)
-        return true
-    }
 
-    fun moveDown(obj: GameObject) : Boolean {
-        var i = cases.indexOf(obj)
-        if (i >= width*(height-1)) { // Si l'obj se situe sur la dernière ligne
-            return false
-        }
-        else if (cases[i+width] != null) { // Si la case du dessous est occupée
-            when (cases[i+width]!!.behavior) {
-                EBehavior.MOVE, EBehavior.PUSH -> {
-                    if (!moveDown(cases[i + width]!!)) { // On pousse la case du dessous
-                        return false // Sinon
-                    }
-                }
-                EBehavior.STOP -> {
-                    return false
-                }
-                EBehavior.DEFEAT -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        reset()
-                    }
-                    return false
-                }
-                EBehavior.WIN -> {
-                    if(cases[i]!!.behavior == EBehavior.MOVE) {
-                        nextLevel()
-                    }
-                    return false
-                }
+        // Affichage
+        when (direction) {
+            EDirection.UP -> {
+                obj.gameEntity.translateY(-48.0*scaleFactor)
+            }
+            EDirection.DOWN -> {
+                obj.gameEntity.translateY(48.0*scaleFactor)
+            }
+            EDirection.LEFT -> {
+                obj.gameEntity.translateX(-48.0*scaleFactor)
+            }
+            EDirection.RIGHT -> {
+                obj.gameEntity.translateX(48.0*scaleFactor)
             }
         }
-        // Déplacement
-        cases[i+width] = obj
-        cases[i] = null
-        if (obj.behavior == EBehavior.MOVE) checkForBehaviorChange()
-        // Affichage
-        obj.gameEntity.translateY(48.0*scaleFactor)
         return true
     }
 
diff --git a/src/main/kotlin/builder/BuilderDemoLevel.kt b/src/main/kotlin/builder/BuilderDemoLevel.kt
index b8a2a9536ce1b925f3e39d0279b3e500d3dbdd50..478ab5ba582c36f4ad467b43073eb1b330f523cd 100644
--- a/src/main/kotlin/builder/BuilderDemoLevel.kt
+++ b/src/main/kotlin/builder/BuilderDemoLevel.kt
@@ -3,7 +3,7 @@ package builder
 import enums.*
 import Level
 import Map
-import Sprite
+import observer.Sprite
 import Block
 import mapHeight
 import mapWidth
diff --git a/src/main/kotlin/builder/BuilderFinalLevel.kt b/src/main/kotlin/builder/BuilderFinalLevel.kt
index f0026890293840dab18b40bf90067ac4955231a8..1843a9f5da6e4c9e8b8826cd588deeedd8bb2716 100644
--- a/src/main/kotlin/builder/BuilderFinalLevel.kt
+++ b/src/main/kotlin/builder/BuilderFinalLevel.kt
@@ -3,7 +3,7 @@ package builder
 import enums.*
 import Level
 import Map
-import Sprite
+import observer.Sprite
 import mapHeight
 import mapWidth
 import scaleFactor
diff --git a/src/main/kotlin/enums/EDirection.kt b/src/main/kotlin/enums/EDirection.kt
new file mode 100644
index 0000000000000000000000000000000000000000..273f2af147e0c95a548059626f34d79a2514dc50
--- /dev/null
+++ b/src/main/kotlin/enums/EDirection.kt
@@ -0,0 +1,5 @@
+package enums
+
+enum class EDirection {
+    UP, DOWN, LEFT, RIGHT
+}
\ No newline at end of file
diff --git a/src/main/kotlin/ConcretSubject.kt b/src/main/kotlin/observer/ConcretSubject.kt
similarity index 96%
rename from src/main/kotlin/ConcretSubject.kt
rename to src/main/kotlin/observer/ConcretSubject.kt
index fc2e31fec74ee726f19735c80446e00fba546a56..e96d150da69d294ed697e47a7f5dad7e9de55817 100644
--- a/src/main/kotlin/ConcretSubject.kt
+++ b/src/main/kotlin/observer/ConcretSubject.kt
@@ -1,3 +1,5 @@
+package observer
+
 import enums.EBehavior
 
 class ConcretSubject(): ISubject {
diff --git a/src/main/kotlin/IObserver.kt b/src/main/kotlin/observer/IObserver.kt
similarity index 83%
rename from src/main/kotlin/IObserver.kt
rename to src/main/kotlin/observer/IObserver.kt
index a0b71b8eacbcf918aa0073f4d2264d93b3ca76a9..622b63f95c4a7174bd4169de909a0df27ce75081 100644
--- a/src/main/kotlin/IObserver.kt
+++ b/src/main/kotlin/observer/IObserver.kt
@@ -1,3 +1,5 @@
+package observer
+
 import enums.EBehavior
 
 interface IObserver {
diff --git a/src/main/kotlin/ISubject.kt b/src/main/kotlin/observer/ISubject.kt
similarity index 88%
rename from src/main/kotlin/ISubject.kt
rename to src/main/kotlin/observer/ISubject.kt
index 1d5abd087b6b131c4a9f2b603883f6c496b1617c..807029dc74c831e9557c38b514095dce08871fad 100644
--- a/src/main/kotlin/ISubject.kt
+++ b/src/main/kotlin/observer/ISubject.kt
@@ -1,3 +1,5 @@
+package observer
+
 interface ISubject {
     fun addObserver(observer: IObserver) {}
     fun removeObserver(observer: IObserver) {}
diff --git a/src/main/kotlin/Sprite.kt b/src/main/kotlin/observer/Sprite.kt
similarity index 89%
rename from src/main/kotlin/Sprite.kt
rename to src/main/kotlin/observer/Sprite.kt
index 33a1298cc06823aa966ccdc6f18f1dadb79f61dc..8fe4422ee1e2a1854be41eb5ac9af386ea8750e2 100644
--- a/src/main/kotlin/Sprite.kt
+++ b/src/main/kotlin/observer/Sprite.kt
@@ -1,3 +1,6 @@
+package observer
+
+import GameObject
 import enums.EBehavior
 import enums.ESprite