diff --git a/bin/coursework/Cage.class b/bin/coursework/Cage.class
index 4e07610a39165c13072741687aa69b631c7d6493..c6c3ed15e75955038dd209362021099653822e4f 100644
Binary files a/bin/coursework/Cage.class and b/bin/coursework/Cage.class differ
diff --git a/bin/coursework/GameState.class b/bin/coursework/GameState.class
index f2191bde75af2628511e506635f2c9a30ca52de6..23910ba3317c7a6b95925d3dac5eff34796fc869 100644
Binary files a/bin/coursework/GameState.class and b/bin/coursework/GameState.class differ
diff --git a/bin/coursework/Main.class b/bin/coursework/Main.class
index 91322a5f64f24da6b9668f57097e6994f74b2337..e11864fcd4a0c4e5737bfec1dfeeafb4b2b6f0e2 100644
Binary files a/bin/coursework/Main.class and b/bin/coursework/Main.class differ
diff --git a/bin/coursework/RandomGenerator.class b/bin/coursework/RandomGenerator.class
index 3ffd12084d130765e78aa78c13730b35777c3487..1f537e186719638b1e5d09d50f44faca09f7c2df 100644
Binary files a/bin/coursework/RandomGenerator.class and b/bin/coursework/RandomGenerator.class differ
diff --git a/src/coursework/Cage.java b/src/coursework/Cage.java
index 6d7ed6a16ebf18626d946d85d35315f73ac5774d..190e102c0b1b9f41cd65ba272f37565021b3ecbb 100644
--- a/src/coursework/Cage.java
+++ b/src/coursework/Cage.java
@@ -80,13 +80,12 @@ public class Cage {
 			}
 		}
 		Collections.sort(sortedCageValues, Collections.reverseOrder());
+
 		int cageVal = sortedCageValues.get(0);
-		
-		for (int value : sortedCageValues) {
-			if (value != cageVal) {
-				cageVal -= value;
-			}
+		for (int i = 1; i < sortedCageValues.size(); i++) {
+			cageVal -= sortedCageValues.get(i);
 		}
+		
 		if (cageVal == value) {
 			return false;
 		}
@@ -107,12 +106,10 @@ public class Cage {
 			}
 		}
 		Collections.sort(sortedCageValues, Collections.reverseOrder());
-		int cageVal = sortedCageValues.get(0);
 		
-		for (int value : sortedCageValues) {
-			if (value != cageVal) {
-				cageVal /= value;
-			}
+		int cageVal = sortedCageValues.get(0);
+		for (int i = 1; i < sortedCageValues.size(); i++) {
+			cageVal /= sortedCageValues.get(i);
 		}
 		
 		if (cageVal == value) {
diff --git a/src/coursework/GameState.java b/src/coursework/GameState.java
index e38448c177c9beece8c2c7915bb61879c36f5913..c86ae4625b78ba7faa197861af37896e58ff943a 100644
--- a/src/coursework/GameState.java
+++ b/src/coursework/GameState.java
@@ -17,6 +17,7 @@ public class GameState {
 	}
 	
 	public static String[] getCurrentGameState(TextField[] gridNumbers) {
+		N = Main.getN();
 		String[] gridValues = new String[N*N];
 		for (int k = 0; k < gridValues.length; k++) {
 			gridValues[k] = gridNumbers[k].getText();
diff --git a/src/coursework/Main.java b/src/coursework/Main.java
index bc3a1da1ee868a31a3a5a37cadec6093a9d206d6..39d33515271a439637387e6578f1b70a0c0e7395 100644
--- a/src/coursework/Main.java
+++ b/src/coursework/Main.java
@@ -19,8 +19,11 @@ import javafx.scene.control.Button;
 import javafx.scene.control.ButtonType;
 import javafx.scene.control.CheckBox;
 import javafx.scene.control.Label;
+import javafx.scene.control.RadioButton;
+import javafx.scene.control.Slider;
 import javafx.scene.control.TextArea;
 import javafx.scene.control.TextField;
+import javafx.scene.control.ToggleGroup;
 import javafx.scene.image.Image;
 import javafx.scene.image.ImageView;
 import javafx.scene.input.MouseEvent;
@@ -49,10 +52,10 @@ public class Main extends Application {
 	private static boolean[][] gridErrors;
 	
 	private static boolean showMistakes = false;
-	private Pane previousPane = null;
-	private Square previousSquare = null;
-	private boolean clearing = false;
-	private boolean undoing = false;
+	private static Pane previousPane = null;
+	private static Square previousSquare = null;
+	private static boolean clearing = false;
+	private static boolean undoing = false;
 	private int fontSize;
 	private ConstraintsHandler constraints = new ConstraintsHandler();
 	
@@ -173,11 +176,27 @@ public class Main extends Application {
 		
 		Button loadGameFileButton = new Button("Load game - file");
 		CheckBox showMistakesCheck = new CheckBox("Show mistakes");
+		if (showMistakes) {
+			showMistakesCheck.setSelected(true);
+		}
 		Button loadGameTextInputButton = new Button("Load game - text input");
 		loadGameFileButton.setPrefWidth(200);
 		loadGameTextInputButton.setPrefWidth(loadGameFileButton.getPrefWidth());
 		
-		topHBox.getChildren().addAll(loadGameFileButton, showMistakesCheck, loadGameTextInputButton);
+		Button generateRandomGameButton = new Button("Generate Random Game");
+		generateRandomGameButton.setPrefWidth(loadGameFileButton.getPrefWidth());
+		Button solveGridButton = new Button("Solve Current Grid");
+		solveGridButton.setPrefWidth(loadGameFileButton.getPrefWidth());
+		
+		VBox leftVBox = new VBox();
+		leftVBox.setSpacing(5);
+		leftVBox.getChildren().addAll(loadGameFileButton, loadGameTextInputButton);
+		
+		VBox rightVBox = new VBox();
+		rightVBox.setSpacing(5);
+		rightVBox.getChildren().addAll(generateRandomGameButton, solveGridButton);
+		
+		topHBox.getChildren().addAll(leftVBox, showMistakesCheck, rightVBox);
 		
 		showMistakesCheck.selectedProperty().addListener((obs, oldVal, newVal) -> {
 			showMistakesCheckEvent(showMistakesCheck);
@@ -191,6 +210,10 @@ public class Main extends Application {
 			loadTextButtonClickEvent();
 		});
 		
+		generateRandomGameButton.setOnAction(e -> {
+			generateRandomGameEvent();
+		});
+		
 		return topHBox;
 	}
 	
@@ -326,6 +349,77 @@ public class Main extends Application {
 	}
 	
 	///////////////////////////////////////////////////////////
+	private void generateRandomGameEvent() {
+		// new popup selecting difficultly and n
+		Stage popupStage = new Stage();
+		popupStage.initModality(Modality.APPLICATION_MODAL);
+		popupStage.initOwner(stage);
+		
+		VBox vbox = new VBox();
+		vbox.setSpacing(5);
+		vbox.setAlignment(Pos.TOP_CENTER);
+		
+		HBox hboxBottom = new HBox();
+		hboxBottom.setSpacing(86);
+		hboxBottom.setPadding(new Insets(10));
+		
+		Slider slider = new Slider(2,8,1);
+		slider.setPrefWidth(150);
+		slider.setMaxWidth(150);
+		slider.setShowTickLabels(true);
+		slider.setShowTickMarks(true);
+		slider.setMinorTickCount(0);
+		slider.setMajorTickUnit(1);
+		slider.setBlockIncrement(1);
+		slider.setSnapToTicks(true);
+		slider.setValue(N);
+		slider.setPadding(new Insets(10, 0, 0, 0));
+		
+		HBox hboxMiddle = new HBox();
+		ToggleGroup tg = new ToggleGroup();
+		RadioButton easy = new RadioButton("Easy");
+		easy.setToggleGroup(tg);
+		RadioButton medium = new RadioButton("Medium");
+		medium.setToggleGroup(tg);
+		RadioButton hard = new RadioButton("Hard");
+		hard.setToggleGroup(tg);
+		hboxMiddle.setAlignment(Pos.CENTER);
+		hboxMiddle.setSpacing(10);
+		VBox radioVBox = new VBox(easy, medium, hard);
+		radioVBox.setSpacing(5);
+		hboxMiddle.getChildren().addAll(new Label("Difficulty:"), radioVBox);
+		
+		Button generateButton = new Button("Generate");
+		generateButton.setAlignment(Pos.TOP_RIGHT);
+		generateButton.setOnAction(e -> {
+			popupStage.close();
+			if ((int) slider.getValue() != N) {
+				N = (int) slider.getValue();
+				resetGrid();
+			}
+			RandomGenerator rg = new RandomGenerator(N);
+			gridCages = rg.generate();			
+		});
+		
+		Button cancelButton = new Button("Cancel");
+		cancelButton.setAlignment(Pos.TOP_LEFT);
+		cancelButton.setOnAction(e -> {
+			popupStage.hide();
+		});
+		
+		HBox hboxTop = new HBox(new Label("Size (NxN):"), slider);
+		hboxTop.setSpacing(3);
+		hboxTop.setAlignment(Pos.CENTER);
+		
+		
+		
+		hboxBottom.getChildren().addAll(cancelButton, generateButton);
+		vbox.getChildren().addAll(hboxTop, hboxMiddle, hboxBottom);
+		
+		popupStage.setScene(new Scene(vbox, 250, 250));
+		popupStage.show();
+	}
+	
 	private void loadFileButtonClickEvent() {
 		try {
 			FileChooser fileChooser = new FileChooser();
@@ -541,7 +635,8 @@ public class Main extends Application {
 	////////////////////////////////////////////////////////
 	
 	@Override
-	public void start(Stage stage) throws Exception {
+	public void start(Stage primaryStage) throws Exception {
+		stage = primaryStage;
 		VBox vBox = new VBox();
 		int width = 400 + 80 * N;
 		int height = 275 + 80 * N;
@@ -549,11 +644,11 @@ public class Main extends Application {
 		scene = new Scene(vBox, width, height);
 		stage.setWidth(width);
 		stage.setHeight(height);
-		vBox.setSpacing(10);
+		vBox.setSpacing(5);
 		vBox.setPadding(new Insets(20));
 		vBox.setAlignment(Pos.CENTER);
 		
-		GridPane gridPane = setupGrid(width - 200, height - 150);
+		GridPane gridPane = setupGrid(width - 200, height - 175);
 		undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers)));
 		
 		fontSize = 18;
@@ -564,7 +659,7 @@ public class Main extends Application {
 		VBox numbersVBox = setupNumbersVBox();
 		HBox gridHBox = new HBox();
 		gridHBox.getChildren().addAll(fontSizeVBox, gridPane, numbersVBox);
-		gridHBox.setSpacing(20);
+		gridHBox.setSpacing(10);
 		gridHBox.setAlignment(Pos.CENTER);
 		
 		HBox bottomHBox = setupBottomHBox();
@@ -609,6 +704,53 @@ public class Main extends Application {
 		stage.setScene(scene);
 		stage.setTitle("Mathdoku");
 		stage.show();
+		
+	}
+	
+	private void resetGrid() {
+		stage.close();
+		initialiseVariables();
+		VBox vBox = new VBox();
+		int width = 300 + 80 * N;
+		int height = 300 + 80 * N;
+		
+		Stage stage = new Stage();
+		Scene newScene = new Scene(vBox, width, height);
+		stage.setWidth(width);
+		stage.setHeight(height);
+		vBox.setSpacing(5);
+		vBox.setPadding(new Insets(20));
+		vBox.setAlignment(Pos.CENTER);
+		
+		GridPane gridPane = setupGrid(width - 200, height - 120);
+		undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers)));
+		
+		fontSize = 18;
+		changeFontSizeEvent(fontSize);
+		HBox topHBox = setupTopHBox();
+		
+		VBox fontSizeVBox = setupFontSizeHBox();
+		VBox numbersVBox = setupNumbersVBox();
+		HBox gridHBox = new HBox();
+		gridHBox.getChildren().addAll(fontSizeVBox, gridPane, numbersVBox);
+		gridHBox.setSpacing(10);
+		gridHBox.setAlignment(Pos.CENTER);
+		
+		HBox bottomHBox = setupBottomHBox();
+		
+		vBox.getChildren().addAll(topHBox, gridHBox, bottomHBox);
+		
+		stageWidthResizeEvent(stage, gridPane);
+		stageHeightResizeEvent(stage, gridPane);
+		
+		stage.setMinWidth(width + 50);
+		stage.setMinHeight(height + 50);
+		stage.setScene(newScene);
+		stage.setTitle("Mathdoku");
+		stage.show();
+		scene = newScene;
+		this.stage = stage;
+
 	}
 	
 	private static void initialiseVariables() {
@@ -618,10 +760,14 @@ public class Main extends Application {
 		gridBoxes = new VBox[N*N];
 		gridCages = new ArrayList<Cage>();
 		gridErrors = new boolean[N*N][3];
+		previousPane = null;
+		previousSquare = null;
+		clearing = false;
+		undoing = false;
 	}
 	
 	public static void main(String[] args) {
-		N = Integer.parseInt(args[0]);
+		N = 4;
 		initialiseVariables();
 		launch(args);
 	}
diff --git a/src/coursework/RandomGenerator.java b/src/coursework/RandomGenerator.java
index d0d26ac4cef6414c796c5c2599f317d2be61d41b..fcd6a00ca20bb175efa835724c5c90afed50c58b 100644
--- a/src/coursework/RandomGenerator.java
+++ b/src/coursework/RandomGenerator.java
@@ -1,29 +1,35 @@
 package coursework;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 
 public class RandomGenerator {
 
-	private static int N = 6;
-	private static int[][] grid = new int[N][N];
+	private int N;
+	private int[][] grid;
 	
-	private static List<Integer> uncagedGrids = new ArrayList<Integer>();
-	private static List<Integer> possibleMoves;
+	private List<Integer> uncagedGrids = new ArrayList<Integer>();
+	private List<Integer> possibleMoves = new ArrayList<Integer>();
+	private List<Cage> gridCages = new ArrayList<Cage>();
 	
-	public static void main(String[] args) {
-		generate();
+	public RandomGenerator(int N) {
+		this.N = N;
+		grid = new int[N][N];
 	}
 	
-	private static void generate() {		
+	public List<Cage> generate() {		
 		generateGridValues();
 		shuffleGridValues();
 		generateCages();
+		return gridCages;
 	}
 	
-	private static void generateCages() {
+	private void generateCages() {
 		Random random = new Random();
 		addAllGrids();
 		while (uncagedGrids.size() > 0) {
@@ -102,16 +108,78 @@ public class RandomGenerator {
 					uncagedGrids.remove(uncagedGrids.indexOf(id));
 				}
 			}
+						
+			int cageValue;
+			String cageOperator;
+			List<Integer> cageValues = new ArrayList<Integer>();
+			HashSet<Integer> hashSetIds = new HashSet<Integer>();
+			for (int cageId : cageIds) {
+				hashSetIds.add(cageId);
+			}
+			
+			if (hashSetIds.size() > 1) {
+				for (int cageId : hashSetIds) {
+					int row = cageId / N;
+					int col = cageId % N;
+					cageValues.add(grid[row][col]);
+				}
+				Collections.sort(cageValues, Collections.reverseOrder());
+				
+				Map<String, Integer> possibleValues = new HashMap<String, Integer>();
+				
+				int additionResult = 0;
+				for (int value : cageValues) {
+					additionResult += value;
+				}
+				possibleValues.put("+", additionResult);
+				
+				int subtractionResult = cageValues.get(0);
+				for (int i = 1; i < cageValues.size(); i++) {
+					subtractionResult -= cageValues.get(i);
+				}
+				if (subtractionResult > 0) {
+					possibleValues.put("-", subtractionResult);
+				}
+				
+				int multiplicationResult = 1;
+				for (int value : cageValues) {
+					multiplicationResult *= value;
+				}
+				possibleValues.put("x", multiplicationResult);
+				
+				float divisionResult = cageValues.get(0);
+				for (int i = 1; i < cageValues.size(); i++) {
+					divisionResult /= cageValues.get(i);
+				}
+				if (divisionResult == (int) divisionResult) {
+					possibleValues.put("�", (int) divisionResult);
+				}
+				
+				
+				List<String> keySet = new ArrayList<String>(possibleValues.keySet());
+				cageOperator = keySet.get(random.nextInt(keySet.size()));
+				cageValue = possibleValues.get(cageOperator);
+			}
+			else {;
+				int row = cageIds[0] / N;
+				int col = cageIds[0] % N;
+				cageValue = grid[row][col];
+				cageOperator = "";
+			}
 			
-			String operator = "+";
-			int value = 0;
+			int[] finalCageIds = new int[hashSetIds.size()];
+			int counter = 0;
+			for (int cageId : hashSetIds) {
+				finalCageIds[counter] = cageId;
+				counter++;
+			}
 			
-			//Cage cage = new Cage(cageIds, value, operator);
+			gridCages.add(new Cage(cageIds, cageValue, cageOperator));
 		}
 	}
 
 	
-	private static void centre(int id) {
+	private void centre(int id) {
 		if (!uncagedGrids.contains(id + N))
 			possibleMoves.remove(possibleMoves.indexOf(id + N));
 		if (!uncagedGrids.contains(id - N))
@@ -122,7 +190,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id - 1));
 	}
 	
-	private static void topLeftCorner(int id) {
+	private void topLeftCorner(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id - 1));
 		possibleMoves.remove(possibleMoves.indexOf(id - N));
 		if (!uncagedGrids.contains(id + 1))
@@ -131,7 +199,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id + N));
 	}
 	
-	private static void topRightCorner(int id) {
+	private void topRightCorner(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id - N));
 		possibleMoves.remove(possibleMoves.indexOf(id + 1));
 		if (!uncagedGrids.contains(id - 1))
@@ -140,7 +208,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id + N));
 	}
 	
-	private static void bottomRightCorner(int id) {
+	private void bottomRightCorner(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id + N));
 		possibleMoves.remove(possibleMoves.indexOf(id + 1));
 		if (!uncagedGrids.contains(id - 1))
@@ -149,7 +217,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id - N));
 	}
 	
-	private static void bottomLeftCorner(int id) {
+	private void bottomLeftCorner(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id + N));
 		possibleMoves.remove(possibleMoves.indexOf(id - 1));
 		if (!uncagedGrids.contains(id + 1))
@@ -158,7 +226,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id - N));
 	}
 	
-	private static void leftEdge(int id) {
+	private void leftEdge(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id - 1));
 		if (!uncagedGrids.contains(id + N))
 			possibleMoves.remove(possibleMoves.indexOf(id + N));
@@ -168,7 +236,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id + 1));
 	}
 	
-	private static void topEdge(int id) {
+	private void topEdge(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id - N));
 		if (!uncagedGrids.contains(id + N))
 			possibleMoves.remove(possibleMoves.indexOf(id + N));
@@ -178,7 +246,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id - 1));
 	}
 	
-	private static void rightEdge(int id) {
+	private void rightEdge(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id + 1));
 		if (!uncagedGrids.contains(id - N))
 			possibleMoves.remove(possibleMoves.indexOf(id - N));
@@ -188,7 +256,7 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id - 1));
 	}
 	
-	private static void bottomEdge(int id) {
+	private void bottomEdge(int id) {
 		possibleMoves.remove(possibleMoves.indexOf(id + N));
 		if (!uncagedGrids.contains(id - N))
 			possibleMoves.remove(possibleMoves.indexOf(id - N));
@@ -198,13 +266,13 @@ public class RandomGenerator {
 			possibleMoves.remove(possibleMoves.indexOf(id + 1));
 	}
 	
-	private static void addAllGrids() {
+	private void addAllGrids() {
 		for (int i = 0; i < N*N; i++) {
 			uncagedGrids.add(i);
 		}
 	}
 	
-	private static int isEdgeGrid(int gridId) {
+	private int isEdgeGrid(int gridId) {
 		if (gridId % N == 0)			// left edge
 			return 0;
 		if (gridId % N == N - 1)		// right edge
@@ -216,7 +284,7 @@ public class RandomGenerator {
 		return -1;		// not an edge grid
 	}
 	
-	private static int isCornerGrid(int gridId) {
+	private 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
@@ -228,7 +296,7 @@ public class RandomGenerator {
 		return -1;		// not a corner
 	}
 	
-	private static void generateGridValues() {
+	private void generateGridValues() {
 		int counter = 1;
 		for (int i = 0; i < N; i++) {
 			for (int j = 0; j < N; j++) {
@@ -245,7 +313,7 @@ public class RandomGenerator {
 		}
 	}
 	
-	private static void shuffleGridValues() {
+	private void shuffleGridValues() {
 		Random random = new Random();
 		for (int i = 0; i < 15; i++) {
 			int[] colsSwap = new int[2];
@@ -266,11 +334,11 @@ public class RandomGenerator {
 		}
 	}
 	
-	private static int[] generateValues(Random random) {
+	private int[] generateValues(Random random) {
 		return new int[] { random.nextInt(N), random.nextInt(N) };
 	}
 	
-	private static void swapColumns(int colA, int colB) {
+	private 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];
@@ -282,7 +350,7 @@ public class RandomGenerator {
 		}
 	}
 	
-	private static void swapRows(int rowA, int rowB) {
+	private 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];
@@ -294,7 +362,7 @@ public class RandomGenerator {
 		}
 	}
 	
-	private static void transpose() {
+	private void transpose() {
 		int[][] temp = new int[N][N];
 		for (int i = 0; i < N; i++) {
 			for (int j = 0; j < N; j++) {
@@ -304,7 +372,7 @@ public class RandomGenerator {
 		grid = temp;
 	}
 
-	private static void output() {
+	private void output() {
 		for (int i = 0; i < N; i++) {
 			for (int j = 0; j < N; j++) {
 				System.out.print(grid[i][j] + " ");