diff --git a/bin/coursework/RandomGenerator.class b/bin/coursework/RandomGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ffd12084d130765e78aa78c13730b35777c3487
Binary files /dev/null and b/bin/coursework/RandomGenerator.class differ
diff --git a/src/coursework/RandomGenerator.java b/src/coursework/RandomGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0d26ac4cef6414c796c5c2599f317d2be61d41b
--- /dev/null
+++ b/src/coursework/RandomGenerator.java
@@ -0,0 +1,317 @@
+package coursework;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+
+public class RandomGenerator {
+
+	private static int N = 6;
+	private static int[][] grid = new int[N][N];
+	
+	private static List<Integer> uncagedGrids = new ArrayList<Integer>();
+	private static List<Integer> possibleMoves;
+	
+	public static void main(String[] args) {
+		generate();
+	}
+	
+	private static void generate() {		
+		generateGridValues();
+		shuffleGridValues();
+		generateCages();
+	}
+	
+	private static void generateCages() {
+		Random random = new Random();
+		addAllGrids();
+		while (uncagedGrids.size() > 0) {
+			int cageProbability = random.nextInt(100);
+			int cageSize;
+	
+			if (cageProbability < 50) {
+				cageSize = 2;
+			}
+			else if (cageProbability < 85) {
+				cageSize = 3;
+			}
+			else {
+				cageSize = 4;
+			}
+			
+			if (uncagedGrids.size() <= cageSize) {
+				cageSize = uncagedGrids.size();
+			}
+			if (cageSize == 0) {
+				break;
+			}
+			
+			int[] cageIds = new int[cageSize];
+			int id = uncagedGrids.get(0);
+			cageIds[0] = id;
+			uncagedGrids.remove(0);
+			for (int i = 0; i < cageSize - 1; i++) {
+				int cornerGrid = isCornerGrid(id);
+				int edgeGrid = isEdgeGrid(id);
+				
+				possibleMoves = new ArrayList<Integer>();
+				possibleMoves.add(id + 1);
+				possibleMoves.add(id - 1);
+				possibleMoves.add(id + N);
+				possibleMoves.add(id - N);
+				
+				if (cornerGrid != -1) {
+					if (cornerGrid == 0) {
+						topLeftCorner(id);
+					}
+					else if (cornerGrid == 1) {
+						topRightCorner(id);
+					}
+					else if (cornerGrid == 2) {
+						bottomRightCorner(id);
+					}
+					else if (cornerGrid == 3) {
+						bottomLeftCorner(id);
+					}
+				}
+				else if (edgeGrid != -1) {
+					if (edgeGrid == 0) {
+						leftEdge(id);
+					}
+					else if (edgeGrid == 1) {
+						rightEdge(id);
+					}
+					else if (edgeGrid == 2) {
+						topEdge(id);
+					}
+					else if (edgeGrid == 3) {
+						bottomEdge(id);
+					}
+				}
+				else {
+					centre(id);
+				}
+				
+
+				if (possibleMoves.size() >= 1) {
+					id = possibleMoves.get(random.nextInt(possibleMoves.size()));
+				}			
+				cageIds[i + 1] = id;
+				if (uncagedGrids.contains(id)) {
+					uncagedGrids.remove(uncagedGrids.indexOf(id));
+				}
+			}
+			
+			String operator = "+";
+			int value = 0;
+			
+			//Cage cage = new Cage(cageIds, value, operator);
+		}
+	}
+
+	
+	private static void centre(int id) {
+		if (!uncagedGrids.contains(id + N))
+			possibleMoves.remove(possibleMoves.indexOf(id + N));
+		if (!uncagedGrids.contains(id - N))
+			possibleMoves.remove(possibleMoves.indexOf(id - N));
+		if (!uncagedGrids.contains(id + 1))
+			possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id - 1))
+			possibleMoves.remove(possibleMoves.indexOf(id - 1));
+	}
+	
+	private static void topLeftCorner(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id - 1));
+		possibleMoves.remove(possibleMoves.indexOf(id - N));
+		if (!uncagedGrids.contains(id + 1))
+			possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id + N))
+			possibleMoves.remove(possibleMoves.indexOf(id + N));
+	}
+	
+	private static void topRightCorner(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id - N));
+		possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id - 1))
+			possibleMoves.remove(possibleMoves.indexOf(id - 1));
+		if (!uncagedGrids.contains(id + N))
+			possibleMoves.remove(possibleMoves.indexOf(id + N));
+	}
+	
+	private static void bottomRightCorner(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id + N));
+		possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id - 1))
+			possibleMoves.remove(possibleMoves.indexOf(id - 1));
+		if (!uncagedGrids.contains(id - N))
+			possibleMoves.remove(possibleMoves.indexOf(id - N));
+	}
+	
+	private static void bottomLeftCorner(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id + N));
+		possibleMoves.remove(possibleMoves.indexOf(id - 1));
+		if (!uncagedGrids.contains(id + 1))
+			possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id - N))
+			possibleMoves.remove(possibleMoves.indexOf(id - N));
+	}
+	
+	private static void leftEdge(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id - 1));
+		if (!uncagedGrids.contains(id + N))
+			possibleMoves.remove(possibleMoves.indexOf(id + N));
+		if (!uncagedGrids.contains(id - N))
+			possibleMoves.remove(possibleMoves.indexOf(id - N));
+		if (!uncagedGrids.contains(id + 1))
+			possibleMoves.remove(possibleMoves.indexOf(id + 1));
+	}
+	
+	private static void topEdge(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id - N));
+		if (!uncagedGrids.contains(id + N))
+			possibleMoves.remove(possibleMoves.indexOf(id + N));
+		if (!uncagedGrids.contains(id + 1))
+			possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id - 1))
+			possibleMoves.remove(possibleMoves.indexOf(id - 1));
+	}
+	
+	private static void rightEdge(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id + 1));
+		if (!uncagedGrids.contains(id - N))
+			possibleMoves.remove(possibleMoves.indexOf(id - N));
+		if (!uncagedGrids.contains(id + N))
+			possibleMoves.remove(possibleMoves.indexOf(id + N));
+		if (!uncagedGrids.contains(id - 1))
+			possibleMoves.remove(possibleMoves.indexOf(id - 1));
+	}
+	
+	private static void bottomEdge(int id) {
+		possibleMoves.remove(possibleMoves.indexOf(id + N));
+		if (!uncagedGrids.contains(id - N))
+			possibleMoves.remove(possibleMoves.indexOf(id - N));
+		if (!uncagedGrids.contains(id - 1))
+			possibleMoves.remove(possibleMoves.indexOf(id - 1));
+		if (!uncagedGrids.contains(id + 1))
+			possibleMoves.remove(possibleMoves.indexOf(id + 1));
+	}
+	
+	private static void addAllGrids() {
+		for (int i = 0; i < N*N; i++) {
+			uncagedGrids.add(i);
+		}
+	}
+	
+	private static int isEdgeGrid(int gridId) {
+		if (gridId % N == 0)			// left edge
+			return 0;
+		if (gridId % N == N - 1)		// right edge
+			return 1;
+		if ((int) gridId / N == 0)		// top edge
+			return 2;
+		if ((int) gridId / N == N - 1) 	// bottom edge
+			return 3;
+		return -1;		// not an edge grid
+	}
+	
+	private static int isCornerGrid(int gridId) {
+		if ((int) gridId / N == 0     && gridId % N == 0) 		// top left corner
+			return 0;
+		if ((int) gridId / N == N - 1 && gridId % N == N - 1)	// bottom right corner
+			return 2;
+		if ((int) gridId / N == 0     && gridId % N == N - 1)	// top right corner
+			return 1;
+		if ((int) gridId / N == N - 1 && gridId % N == 0)		// bottom left corner
+			return 3;
+		return -1;		// not a corner
+	}
+	
+	private static void generateGridValues() {
+		int counter = 1;
+		for (int i = 0; i < N; i++) {
+			for (int j = 0; j < N; j++) {
+				grid[i][j] = counter;
+				counter++;
+				if (counter == N + 1) {
+					counter = 1;
+				}
+			}
+			counter--;
+			if (counter == 0) {
+				counter = N;
+			}
+		}
+	}
+	
+	private static void shuffleGridValues() {
+		Random random = new Random();
+		for (int i = 0; i < 15; i++) {
+			int[] colsSwap = new int[2];
+			int[] rowsSwap = new int[2];
+			if (colsSwap[0] == colsSwap[1]) {
+				colsSwap = generateValues(random);
+			}
+			if (rowsSwap[0] == rowsSwap[1]) {
+				rowsSwap = generateValues(random);
+			}
+			
+			swapColumns(colsSwap[0], colsSwap[1]);
+			swapRows(rowsSwap[0], rowsSwap[1]);
+			
+			if (i == 7) {
+				transpose();
+			}
+		}
+	}
+	
+	private static int[] generateValues(Random random) {
+		return new int[] { random.nextInt(N), random.nextInt(N) };
+	}
+	
+	private static void swapColumns(int colA, int colB) {
+		int[][] columns = new int[N][2];
+		for (int i = 0; i < N; i++) {
+			columns[i][0] = grid[i][colA];
+			columns[i][1] = grid[i][colB];
+		}
+		for (int i = 0; i < N; i++) {
+			grid[i][colA] = columns[i][1];
+			grid[i][colB] = columns[i][0];
+		}
+	}
+	
+	private static void swapRows(int rowA, int rowB) {
+		int[][] rows = new int[N][2];
+		for (int i = 0; i < N; i++) {
+			rows[i][0] = grid[rowA][i];
+			rows[i][1] = grid[rowB][i];
+		}
+		for (int i = 0; i < N; i++) {
+			grid[rowA][i] = rows[i][1];
+			grid[rowB][i] = rows[i][0];
+		}
+	}
+	
+	private static void transpose() {
+		int[][] temp = new int[N][N];
+		for (int i = 0; i < N; i++) {
+			for (int j = 0; j < N; j++) {
+				temp[j][i] = grid[i][j];
+			}
+		}
+		grid = temp;
+	}
+
+	private static void output() {
+		for (int i = 0; i < N; i++) {
+			for (int j = 0; j < N; j++) {
+				System.out.print(grid[i][j] + " ");
+			}
+			System.out.print("\n");
+		}
+		System.out.print("\n");
+	}
+
+}
\ No newline at end of file