diff --git a/PuzzlePlayer/Binary.cs b/PuzzlePlayer/Binary.cs
index d3ec27f873e4c69fac1931c59f7458f50eb800a8..f3c453a8e1fd9585b00329ba3dd09384f008986e 100644
--- a/PuzzlePlayer/Binary.cs
+++ b/PuzzlePlayer/Binary.cs
@@ -69,19 +69,7 @@ namespace PuzzlePlayer_Namespace
             }
         }
 
-        // static meathode for filling a int[,] with -1
-        public static int[,] GetClearBoard(int boardSize)
-        {
-            int[,] result = new int[boardSize, boardSize];
-            // fill the board with empty spaces (-1)
-            for (int i = 0; i < boardSize; i++)
-            {
-                for (int j = 0; j < boardSize; j++)
-                    result[i, j] = emptySpace;
-            }
-
-            return result;
-        }
+        
 
         // generates a random solvable board
         public override void Generate()
@@ -227,21 +215,8 @@ namespace PuzzlePlayer_Namespace
                 return null;
             }
 
-            ///*
-            // shuffle the choices in the list around to get different results every time
-            // First answer from: https://stackoverflow.com/questions/273313/randomize-a-listt
-            Random random = new Random();
-            int n = choices.Count;
-            while (n > 1)
-            {
-                n--;
-                int rand = random.Next(n + 1);
-                Move copy = choices[rand];
-                choices[rand] = choices[n];
-                choices[n] = copy;
-            }
-            //*/
-
+            choices.Shuffle(); //shuffle the choices around for random results everytime
+                               //(Shuffle methode from the extentions class in the Board.cs file
 
             // do the algorithm for every move
             foreach (Move m in choices)
diff --git a/PuzzlePlayer/Board.cs b/PuzzlePlayer/Board.cs
index 341c3d32c49de17a87885934456ed1bca93d50c9..766aae9d457971a2e6cf85c67ec86295298f9652 100644
--- a/PuzzlePlayer/Board.cs
+++ b/PuzzlePlayer/Board.cs
@@ -45,6 +45,19 @@ namespace PuzzlePlayer_Namespace
         public int[,] boardState;
         public int[,] lastGeneratedBoard;
 
+        // static meathode for filling a int[,] with -1
+        public static int[,] GetClearBoard(int boardSize)
+        {
+            int[,] result = new int[boardSize, boardSize];
+            // fill the board with empty spaces (-1)
+            for (int i = 0; i < boardSize; i++)
+            {
+                for (int j = 0; j < boardSize; j++)
+                    result[i, j] = emptySpace;
+            }
+
+            return result;
+        }
 
 
         // checks if the board is valid and solvable before setting the variable.
@@ -60,10 +73,11 @@ namespace PuzzlePlayer_Namespace
                 return false;
             }
         }
+
         public abstract void Draw(Graphics gr, Rectangle r);
         // a methode for solving the whole board. It uses the private SolveStep methode untill the whole board is solved
         // it has one parameter. setting this to true will only give a return value without changing the current boardState
-        public SOLUTIONS Solve(bool CheckOnly)
+        public virtual SOLUTIONS Solve(bool CheckOnly)
         {
             // two variables for storing the result and the next solveStep
             int[,] result = (int[,])boardState.Clone();
@@ -124,4 +138,26 @@ namespace PuzzlePlayer_Namespace
         // performs a left/right (X) click on tile P, changing its value
         public virtual void TileClick(Point p, int x) { }
     }
+
+
+    // static class for extentions
+    public static class Extensions
+    {
+        private static readonly Random rng = new Random();
+
+        // shuffle the elements in a list around to get different results every time from the generator algoritms
+        // First answer from: https://stackoverflow.com/questions/273313/randomize-a-listt
+        public static void Shuffle<T>(this IList<T> list)
+        {
+            int n = list.Count;
+            while (n > 1)
+            {
+                n--;
+                int k = rng.Next(n + 1);
+                T value = list[k];
+                list[k] = list[n];
+                list[n] = value;
+            }
+        }
+    }
 }
diff --git a/PuzzlePlayer/Maze.cs b/PuzzlePlayer/Maze.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0f44895bab1f926ccc5c84857a27507e469aa218
--- /dev/null
+++ b/PuzzlePlayer/Maze.cs
@@ -0,0 +1,406 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Threading;
+using System.Windows.Forms;
+
+
+namespace PuzzlePlayer_Namespace
+{
+    /*
+     * all the info about where the walls in the maze are is stored in the mazeState int[,]
+     * the info of wich cells are already visited by the generator methode are stored in the visitedCells
+     * the boardState is used to keep track of the spaces that the player has visited while solving the maze
+     * 
+     * if the player/generator has not yet visited a space then it is equal to the emptyspace constant
+     * if the player/generator did visit the space then it is equal to 1 
+     * 
+     * The maze board consists of cells with a number between 1 and 15
+     * the number represents where the walls are
+     * 1111 is 15 in binary the first bit is the top wall, second bit the right wall, etc. continuing clockwise
+     *  _
+     * | | fully surounded is 15, so 1111 in binary
+     *  -
+     *  _
+     * |   right side open is 11, so 1011 in binary
+     *  -
+     * 
+     * -1 means that the cell is empty so there are no walls anywhere
+     * 
+     * the topleft corner is always the starting point (left wall), and the bottom right corner is always the end point (right wall)
+     *  
+     */
+
+    class Maze : Board
+    {
+        int[,] mazeState;
+        int[,] visitedCells;
+
+        Point playerPos;
+        List<Point> shortestPath;
+
+        public Maze(int size = 20)
+        {
+            //drawFactor = 1;
+            // init all 2D array's
+            Reset(size);
+        }
+
+        private void Reset(int size)
+        {
+            boardState = GetClearBoard(size);
+            mazeState = GetClearBoard(size);
+            visitedCells = GetClearBoard(size);
+        }
+
+        // two funcions to go from number to walls and back
+        private int getNumberFromWalls((bool top, bool right, bool bottom, bool left) cell)
+        {
+            int result = 0;
+
+            if (cell.top)
+                result++;
+            if (cell.right)
+                result += 2;
+            if (cell.bottom)
+                result += 4;
+            if (cell.left)
+                result += 8;
+
+            //if (result == 0)
+                //return emptySpace; //if there are no walls then the space is empty
+
+            return result;
+        }
+
+        private (bool,bool,bool,bool) getWallsFromNumber(int number)
+        {
+            //if(number == emptySpace)
+            //    return (true,true,true,true); //if the place is empty then it is completly walled in,
+                                              //so that the walls can be removed when generating the maze
+
+            // bitwise and opperations to check each bit
+            bool top = (number & 1) != 0;
+            bool right = (number & 2) != 0;
+            bool bottom = (number & 4) != 0;
+            bool left = (number & 8) != 0;
+
+            return (top, right, bottom, left);
+        }
+
+        public override void Draw(Graphics gr, Rectangle r)
+        {
+            // clear screen
+            gr.FillRectangle(Brushes.Wheat, r);
+
+            Size tilesize = new Size(r.Width / boardState.GetLength(0), r.Height / boardState.GetLength(1));
+            Pen wall = new Pen(Color.Black, tilesize.Width / 5);
+
+            //debug colors
+            //Pen wall1 = new Pen(Color.Black, tilesize.Width / 5);
+            //Pen wall2 = new Pen(Color.Blue, tilesize.Width / 5);
+            //Pen wall3 = new Pen(Color.Green, tilesize.Width / 5);
+            //Pen wall4 = new Pen(Color.Purple, tilesize.Width / 5);
+
+            for (int i = 0; i < boardState.GetLength(0); i++)
+                for(int j = 0; j < boardState.GetLength(1); j++)
+                {
+                    Rectangle currentRect =
+                        new Rectangle(r.X + i * tilesize.Width, r.Y + j * tilesize.Height, tilesize.Width, tilesize.Height);
+
+                    // draw the space blue if the player has visited it
+                    if (boardState[i, j] == 1)
+                        gr.FillRectangle(Brushes.Blue, currentRect);
+
+                    // draw board outline
+                    gr.DrawRectangle(Pens.LightGray,currentRect);
+
+                    // drawing walls
+                    (bool top,bool right,bool bottom,bool left) = getWallsFromNumber(mazeState[i,j]);
+
+                    if (top)
+                        gr.DrawLine(wall, currentRect.Left, currentRect.Top, currentRect.Right, currentRect.Top);
+                    if (right)
+                        gr.DrawLine(wall, currentRect.Right, currentRect.Top, currentRect.Right, currentRect.Bottom);
+                    if (bottom)
+                        gr.DrawLine(wall, currentRect.Left, currentRect.Bottom, currentRect.Right, currentRect.Bottom);
+                    if (left)
+                        gr.DrawLine(wall, currentRect.Left, currentRect.Bottom, currentRect.Left, currentRect.Top);
+                    
+                }
+
+            // draw an indication of where the start and end from the maze are
+
+            gr.FillRectangle(Brushes.Blue, r.X, r.Y, tilesize.Width, tilesize.Height);
+            gr.FillRectangle(Brushes.Red, r.X + tilesize.Width*(boardState.GetLength(0)-1), r.Y + tilesize.Height * (boardState.GetLength(1)-1), tilesize.Width, tilesize.Height);
+
+            //gr.DrawString("START", SettingForm.mainFont, Brushes.Red, r.Left, r.Top + tilesize.Height/2);
+            //gr.DrawString("END", SettingForm.mainFont, Brushes.Red, r.Right - tilesize.Width / 4, r.Bottom - tilesize.Height / 2);
+        }
+
+        // this methode generates a Maze starting with an empty board
+        // it uses the randomized depth first search algoritm as described on this wiki page: 
+        // https://en.wikipedia.org/wiki/Maze_generation_algorithm#Randomized_depth-first_search
+        public override void Generate()
+        {
+            //clear the board and all 2D array's
+            Reset(mazeState.GetLength(0));
+
+            Random rnd = new Random();
+            int x = rnd.Next(mazeState.GetLength(0));
+            int y = rnd.Next(mazeState.GetLength(0));
+
+            if (Recursive_DepthFirstSearchMazeGenerator(x, y))
+                Debug.WriteLine("Maze succesfully generated");
+            else
+                Debug.WriteLine("nope");
+            
+        }
+
+        private bool Recursive_DepthFirstSearchMazeGenerator(int x, int y)
+        {
+            visitedCells[x, y] = 1; // mark current cell as visited (this is needed for the first cell)
+
+            // get a list of all the unvisited neigbour cells
+            List<(int, int)> validNeigbours = getNeigbours(x, y, emptySpace);
+            if (validNeigbours.Count == 0)
+                return false; // backtrack
+
+            validNeigbours.Shuffle(); //shuffle the neigbours around for random results everytime
+                                      //(Shuffle methode from the extentions class in the Board.cs file
+
+            foreach ((int nx,int ny) neighbour in validNeigbours)
+            {
+                if (visitedCells[neighbour.nx, neighbour.ny] == 1)
+                    continue;
+                visitedCells[neighbour.nx,neighbour.ny] = 1; // mark as visited and update all the walls that are effected
+                UpdateWalls(x,y, neighbour.nx,neighbour.ny);
+
+                if(BoardComplete())
+                    return true;
+
+                if(Recursive_DepthFirstSearchMazeGenerator(neighbour.nx,neighbour.ny)) //recursion
+                    return true; // if true then the maze is finished and this cell should return true too
+            }
+
+            return false; // backtrack if all the neighbours are already visited
+        }
+
+        private bool BoardComplete()
+        {
+            for(int i = 0;i<visitedCells.GetLength(0);i++)
+                for(int j = 0;j<visitedCells.GetLength(1);j++)
+                {
+                    if (visitedCells[i, j] == emptySpace)
+                        return false;
+                }
+            return true;
+        }
+
+        // update the walls between two cells
+        private void UpdateWalls(int x, int y, int x2, int y2)
+        {
+            // get the walls from the two cells
+            (bool top, bool right, bool bottom, bool left) first = getWallsFromNumber(mazeState[x, y]);
+            (bool top, bool right, bool bottom, bool left) second = getWallsFromNumber(mazeState[x2, y2]);
+
+            int dx = x - x2;
+            int dy = y - y2;
+
+            if(dx == -1)
+            {
+                first.right = false;
+                second.left = false;
+            }
+            else if (dx == 1)
+            {
+                first.left = false;
+                second.right = false;
+            }
+            else if (dy == -1)
+            {
+                first.bottom = false;
+                second.top = false;
+            }
+            else if (dy == 1)
+            {
+                first.top = false;
+                second.bottom = false;
+            }
+
+            // update the walls
+            mazeState[x, y] = getNumberFromWalls(first);
+            mazeState[x2, y2] = getNumberFromWalls(second);
+        }
+
+        // checks all the neighbours for the checkFor param (this is used to get either the visited or the unvisited neighbours)
+        private List<(int,int)> getNeigbours(int x, int y, int checkFor)
+        {
+            List<(int,int)> result = new List<(int,int)> ();
+
+            if(x-1 >= 0)
+                if(visitedCells[x-1,y] == checkFor)
+                    result.Add((x-1,y));
+            if (y - 1 >= 0)
+                if (visitedCells[x, y - 1] == checkFor)
+                    result.Add((x, y - 1));
+
+            if (x + 1 < visitedCells.GetLength(0))
+                if (visitedCells[x + 1, y] == checkFor)
+                    result.Add((x + 1, y));
+            if (y + 1 < visitedCells.GetLength(1))
+                if (visitedCells[x, y + 1] == checkFor)
+                    result.Add((x, y + 1));
+            /*
+            for (int checkX = x-1;checkX <= x+1; checkX++)
+                for(int checkY = y-1;checkY <= y+1;checkY++)
+                {
+                    // check if checkX/Y are within bounds
+                    if(checkX >= 0 && checkY >=0 && checkX < visitedCells.GetLength(0) && checkY < visitedCells.GetLength(1))
+                        if(visitedCells[checkX,checkY] == checkFor)
+                            result.Add((checkX,checkY));
+                }
+            */
+            return result;
+        }
+
+        // overrite the Solve methode because a maze and an ordinary board puzzle like a sudoku or binary puzzle
+        // don't have much in common in regards to solving. So most of the code in the abstract Board class is to no use for us here
+        public override SOLUTIONS Solve(bool CheckOnly)
+        {
+            visitedCells = GetClearBoard(mazeState.GetLength(0));
+            boardState = GetClearBoard(mazeState.GetLength(0));
+            shortestPath = new List<Point>();
+
+            shortestPath.Add(new Point(0,0)); // starting point
+            bool foundSolution = Recursive_DepthFirstSearchMazeSolve(0, 0);
+            if(CheckOnly && foundSolution)
+                return SOLUTIONS.UNIQUE;
+            else if(!CheckOnly && foundSolution)
+            {
+                foreach(Point p in shortestPath)
+                {
+                    boardState[p.X, p.Y] = 1;
+                }
+            }
+
+            return SOLUTIONS.NONE;
+        }
+
+        // we solve the maze in almost the same way as we generated the maze
+        private bool Recursive_DepthFirstSearchMazeSolve(int x, int y)
+        {
+            visitedCells[x, y] = 1; // mark current cell as visited (this is needed for the first cell)
+
+            // get a list of all the unvisited neigbour cells
+            List<(int, int)> validNeigbours = getNeigbours(x, y, emptySpace);
+            if (validNeigbours.Count == 0)
+            {
+                shortestPath.RemoveAt(shortestPath.Count-1); // remove path if we backtrack
+                return false; // backtrack
+            }
+
+            validNeigbours.Shuffle(); //shuffle the neigbours around for random results everytime
+                                      //(Shuffle methode from the extentions class in the Board.cs file
+
+            foreach ((int nx, int ny) neighbour in validNeigbours)
+            {
+                // if the neighbour is already visited or it is a invalid neighbour then continue to the next
+                if (visitedCells[neighbour.nx, neighbour.ny] == 1 || !isValidNeighbour(x,y,neighbour.nx,neighbour.ny))
+                    continue;
+
+                visitedCells[neighbour.nx, neighbour.ny] = 1; // mark as visited
+                shortestPath.Add(new Point(neighbour.nx, neighbour.ny)); // mark as correct path
+
+                // if the bottom right space is reached then we found a solution
+                if (neighbour.nx == (mazeState.GetLength(0)-1) && neighbour.ny == (mazeState.GetLength(1)-1))
+                    return true;
+
+                if (Recursive_DepthFirstSearchMazeSolve(neighbour.nx, neighbour.ny)) //recursion
+                    return true; // if true then the maze is finished and this cell should return true too
+            }
+
+            shortestPath.RemoveAt(shortestPath.Count - 1); // remove path if we backtrack
+            return false; // backtrack if all the neighbours are already visited
+        }
+
+        private bool isValidNeighbour(int x, int y, int nx, int ny)
+        {
+            // get the walls from the two cells
+            (bool top, bool right, bool bottom, bool left) first = getWallsFromNumber(mazeState[x, y]);
+            (bool top, bool right, bool bottom, bool left) second = getWallsFromNumber(mazeState[nx, ny]);
+
+            int dx = x - nx;
+            int dy = y - ny;
+
+            if (dx == -1)
+            {
+                if (!(first.right && second.left))
+                    return true;
+            }
+            else if (dx == 1)
+            {
+                if (!(first.left && second.right))
+                    return true;
+            }
+            else if (dy == -1)
+            {
+                if (!(first.bottom && second.top))
+                    return true;
+            }
+            else if (dy == 1)
+            {
+                if (!(first.top && second.bottom))
+                    return true;
+            }
+
+
+            return false;
+        }
+
+        // this methode is not needed because we write our own Solve methode
+        protected override List<Move> GetSolveList(int[,] boardToSolve)
+        {
+            return null;
+        }
+
+        /* Add later
+        public override void TileInput(Point p, Keys key)
+        {
+            (bool top, bool right, bool bottom, bool left) = getWallsFromNumber(mazeState[p.X,p.Y]);
+
+            switch (key)
+            {
+                case Keys.Up | Keys.W:
+                    if (!top)
+                        playerPos.Y++;
+                    break;
+                case Keys.Down | Keys.S:
+                    if (!bottom)
+                        playerPos.Y--;
+                    break;
+                case Keys.Right | Keys.D:
+                    if (!right)
+                        playerPos.X++;
+                    break;
+                case Keys.Left | Keys.A:
+                    if (!left)
+                        playerPos.X--;
+                    break;
+            }
+
+            // upadte the spaces where the player has walked
+            boardState[playerPos.X, playerPos.Y] = 1;
+        }
+        */
+        public override void TileInput(Point p, int x)
+        {
+            throw new NotImplementedException();
+        }
+        public override void TileClick(Point p, int x)
+        {
+            //MessageBox.Show($"{mazeState[p.X, p.Y]}");
+        }
+    }
+}
diff --git a/PuzzlePlayer/PuzzleForm.cs b/PuzzlePlayer/PuzzleForm.cs
index 8bda5037b633a7ccdd64e6b2c277957d04d570b7..de33cd932d769657583bd58074a2d9801c1293bf 100644
--- a/PuzzlePlayer/PuzzleForm.cs
+++ b/PuzzlePlayer/PuzzleForm.cs
@@ -97,9 +97,6 @@ namespace PuzzlePlayer_Namespace
 
             Board = b;
             CreateUI();
-
-            Board.boardState[1, 1] = 1;
-            Board.boardState[2, 2] = 0;
         }
         private void CreateUI() //sets up ui elements
         {
diff --git a/PuzzlePlayer/PuzzlePlayer.cs b/PuzzlePlayer/PuzzlePlayer.cs
index f64b7945fc5cc78fe50b64fe3d9cef31b4f28572..de329eb6114bb1522374a58146332d2be4cc075e 100644
--- a/PuzzlePlayer/PuzzlePlayer.cs
+++ b/PuzzlePlayer/PuzzlePlayer.cs
@@ -10,7 +10,7 @@ namespace PuzzlePlayer_Namespace
     {
         internal static void Main(string[] args)
         {
-            Application.Run(new MainForm());
+            Application.Run(new PuzzleForm(new Maze()));
         }
     }