diff --git a/bin/coursework/Main.class b/bin/coursework/Main.class
index d732c086f0f50b0b91218527463bd8a5593b2706..ae468b9521fc5d9f39ff9b1a989129e7ce984656 100644
Binary files a/bin/coursework/Main.class and b/bin/coursework/Main.class differ
diff --git a/src/coursework/Main.java b/src/coursework/Main.java
index 417ce75c94aaefee20e8f1ccc113827571e366e3..09e4417febc640fbc39d1e558bd925292c41d6c0 100644
--- a/src/coursework/Main.java
+++ b/src/coursework/Main.java
@@ -5,6 +5,7 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Stack;
 import java.util.Vector;
@@ -20,6 +21,7 @@ import javafx.scene.control.Alert;
 import javafx.scene.control.Alert.AlertType;
 import javafx.scene.control.Button;
 import javafx.scene.control.ButtonType;
+import javafx.scene.control.CheckBox;
 import javafx.scene.control.Label;
 import javafx.scene.control.TextField;
 import javafx.scene.image.Image;
@@ -44,18 +46,25 @@ import javafx.stage.Stage;
 public class Main extends Application {
 	
 	final static public int N = 6;
+	final private double GRID_PERCENTAGE = 0.75;
 	
 	private Scene scene;
 	private Stage stage;
 	
-	final private double GRID_PERCENTAGE = 0.75;
+	
 	private static Square[] gridSquares = new Square[N*N];
 	private TextField[] gridNumbers = new TextField[N*N];
 	private static Label[][] cageLabels = new Label[N*N][2];
+	private boolean[][] highlightedError = new boolean[N*N][3];
+	private HBox[] gridHBoxes = new HBox[N*N];
+	private List<Cage> gridCages = new ArrayList<Cage>();
+	
 	private boolean isWider;
 	private HBox previousHBox = null;
 	private Square previousSquare = null;
 	private boolean clearing = false;
+	private boolean undoing = false;
+	private boolean showMistakes = false;
 	
 	private Stack<GameState> undoStack = new Stack<GameState>();
 	private Stack<GameState> redoStack = new Stack<GameState>();
@@ -89,18 +98,86 @@ public class Main extends Application {
 		gridPane.add(hbox, j, i);
 		
 		textField.textProperty().addListener((observable, oldValue, newValue) -> {
-			if (!clearing) {
+			if (!clearing && !undoing) {
 				undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers)));
 				if (undoButton.isDisabled()) {
 					undoButton.setDisable(false);
 				}
 			}
+			checkConstraints(textField, j, i);
 		});
 		
 		square.getRectangle().toFront();
 		return gridPane;
 	}
 	
+	private void checkConstraints(TextField textField, int col, int row) {
+		String value = textField.getText();
+		boolean found = false;
+		for (int i = 0; i < N; i++) {
+			if (!gridNumbers[row*N + i].getText().equals("")) {
+				if (gridNumbers[row*N + i].getText().equals(value) && i != col) {
+					highlightRow(row);
+					found = true;
+					break;
+				}
+			}
+		}
+		if (!found) {
+			clearRow(row);
+		}
+		
+		found = false;
+		for (int i = 0; i < N; i++) {
+			if (!gridNumbers[i*N + col].getText().equals("")) {
+				if (gridNumbers[i*N + col].getText().equals(value) && i != row) {
+					highlightColumn(col);
+					found = true;
+					break;
+				}
+			}
+		}
+		if (!found) {
+			clearColumn(col);
+		}
+		highlightCells();
+	}
+	
+	private void clearRow(int row) {
+		for (int i = 0; i < N; i++) {
+			highlightedError[row*N + i][0] = false;		
+		}
+	}
+	
+	private void clearColumn(int col) {
+		for (int i = 0; i < N; i++) {
+			highlightedError[i*N + col][1] = false;
+		}
+	}
+	
+	private void highlightRow(int row) {
+		for (int i = 0; i < N; i++) {
+			highlightedError[row*N + i][0] = true;
+		}
+	}
+	
+	private void highlightColumn(int col) {
+		for (int i = 0; i < N; i++) {
+			highlightedError[i*N + col][1] = true;
+		}
+	}
+	
+	private void highlightCells() {
+		for (int i = 0; i < N*N; i++) {
+			if ((highlightedError[i][0] || highlightedError[i][1] || highlightedError[i][2]) && showMistakes) {
+				gridHBoxes[i].setStyle("-fx-background-color: rgba(255,0,20,0.4);");
+			}
+			else {
+				gridHBoxes[i].setStyle("-fx-background-color: rgba(255,0,20,0);");
+			}
+		}
+	}
+	
 	private HBox setupGridHBox(Square square, TextField textField, int i, int j) {
 		HBox hbox = new HBox();
 		VBox vbox = new VBox();
@@ -114,7 +191,8 @@ public class Main extends Application {
 		vbox.setAlignment(Pos.CENTER);
 		hbox.getChildren().add(vbox);
 		hbox.setAlignment(Pos.CENTER);
-		hboxClickSquareEvent(hbox, square);
+		gridHBoxes[i*N + j] = hbox;
+		hboxClickSquareEvent(i, j, square);
 
 		return hbox;
 	}
@@ -130,9 +208,10 @@ public class Main extends Application {
 	}
 	
 	private TextField setupGridTextField(double size) {
+		final double PERCENT = 0.7;
 		TextField textField = new TextField();
 		textField.setMinWidth(size/4);
-		textField.setPrefSize(size*0.5, size*0.5);
+		textField.setPrefSize(size*PERCENT, size*PERCENT);
 		textField.setAlignment(Pos.CENTER);
 		textField.setStyle("-fx-focus-color: transparent;");
 		textField.setStyle("-fx-text-box-border: transparent;");
@@ -145,12 +224,18 @@ public class Main extends Application {
 		topHBox.setSpacing(10);
 		
 		Button loadGameFileButton = new Button("Load game - file");
-		Button showMistakesButton = new Button("Show mistakes");
+		CheckBox showMistakesCheck = new CheckBox("Show mistakes");
 		Button loadGameTextInputButton = new Button("Load game - text input");
 		loadGameFileButton.setPrefWidth(200);
 		loadGameTextInputButton.setPrefWidth(loadGameFileButton.getPrefWidth());
 		
-		topHBox.getChildren().addAll(loadGameFileButton, showMistakesButton, loadGameTextInputButton);
+		topHBox.getChildren().addAll(loadGameFileButton, showMistakesCheck, loadGameTextInputButton);
+		
+		showMistakesCheck.selectedProperty().addListener((obs, oldVal, newVal) -> {
+			showMistakes = showMistakesCheck.isSelected();
+			System.out.println(showMistakes + ", " + showMistakesCheck.isSelected());
+			highlightCells();
+		});
 		
 		loadGameFileButton.setOnAction(e -> {
 			try {
@@ -196,8 +281,6 @@ public class Main extends Application {
 	private void updateGameState(GameState gameState) {
 		String[] gameValues = gameState.getGameState();
 		for (int i = 0; i < gridNumbers.length; i++) {
-//			if (!gridNumbers[i].getText().equals("") && gameValues.equals(""))
-//				System.out.println("Current: " + gridNumbers[i].getText() + ", Previous: " + textFields[i].getText());
 			gridNumbers[i].setText(gameValues[i]);
 		}
 	}
@@ -211,24 +294,22 @@ public class Main extends Application {
 		redoButton = new Button("", new ImageView(new Image("file:Images/redo_icon.png")));
 		Button clearButton = new Button("Clear");
 		undoButton.setOnAction(e -> {
-			// undoStack.pop() is the current GameState
-						
+			undoing = true;			
+			
 			redoStack.push(undoStack.pop());
 			updateGameState(undoStack.peek());
 			
-			// 
 			if (!redoStack.empty()) {
 				redoButton.setDisable(false);
 			}
 			if (undoStack.size() == 1) {
 				undoButton.setDisable(true);
 			}
+			undoing = false;
 		});
 		redoButton.setOnAction(e -> {
 			GameState gameState = redoStack.pop();
 			updateGameState(gameState);
-		
-			undoStack.push(gameState);
 			
 			if (!undoStack.empty()) {
 				undoButton.setDisable(false);
@@ -248,13 +329,27 @@ public class Main extends Application {
 		return bottomHBox;
 	}
 	
-	private void hboxClickSquareEvent(HBox hbox, Square square) {
-		hbox.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
+	private void hboxClickSquareEvent(int i, int j, Square square) {
+		gridHBoxes[i*N + j].addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
 			if (previousHBox != null) {
-				previousHBox.setStyle("-fx-border-width:0px;");
+				int previousIndex = getIndexOf(previousHBox);
+				if (highlightedError[previousIndex][0] || highlightedError[previousIndex][1] || highlightedError[previousIndex][2]) {
+					previousHBox.setStyle("-fx-background-color: rgba(255,0,20,0.4); -fx-border-width:0px;");
+				}
+				else {
+					previousHBox.setStyle("-fx-border-width:0px;");
+				}
+			}
+			
+			if (highlightedError[i*N + j][0] || highlightedError[i*N + j][1] || highlightedError[i*N + j][2]) {
+				gridHBoxes[i*N + j].setStyle("-fx-background-color: rgba(255,0,20,0.4); -fx-border-color: #0016CD; -fx-border-width:3px;");
+			}
+			else {
+				gridHBoxes[i*N + j].setStyle("-fx-border-color: #0016CD; -fx-border-width:3px;");
 			}
-			hbox.setStyle("-fx-border-color:red; -fx-border-width:2px;");
-			previousHBox = hbox;
+			
+			
+			previousHBox = gridHBoxes[i*N + j];
 			previousSquare = square;
 			for (TextField textField : gridNumbers) {
 				textField.deselect();
@@ -262,23 +357,52 @@ public class Main extends Application {
 		});
 	}
 	
+	private int getIndexOf(HBox hbox) {
+		for (int i = 0; i < N*N; i++) {
+			if (hbox.equals(gridHBoxes[i])) {
+				return i;
+			}
+		}
+		return -1;
+	}
+	
 	private void clearButtonClickEvent(Button clearButton) {		
 		clearButton.setOnAction(e -> {
-			clearing = true;
-			undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers)));
-			Alert alert = new Alert(AlertType.CONFIRMATION);
-			alert.setContentText("Are you sure you wish to clear the board?");
-			alert.showAndWait().ifPresent(type -> {
-				if (type == ButtonType.OK) {
-					for (TextField textField : gridNumbers) {
-						textField.setText("");
+			if (!lastOperationClear()) {
+				clearing = true;
+				Alert alert = new Alert(AlertType.CONFIRMATION);
+				alert.setContentText("Are you sure you wish to clear the board?");
+				alert.setTitle("Clearing Board.");
+				alert.showAndWait().ifPresent(type -> {
+					if (type == ButtonType.OK) {
+						for (TextField textField : gridNumbers) {
+							textField.setText("");
+						}
+						undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers)));
 					}
-				}
-			});;
-			clearing = false;
+				});;
+				clearing = false;
+			}
+			else {
+				Alert alert = new Alert(AlertType.WARNING);
+				alert.setContentText("Nothing to clear on the board.");
+				alert.setTitle("Empty Board");
+				alert.showAndWait();
+			}
 		});
 	}
 	
+	private boolean lastOperationClear() {
+		GameState gameState = undoStack.peek();
+		boolean emptyGrid = true;
+		for (String textFieldValue : gameState.getGameState()) {
+			if (textFieldValue.length() > 0) {
+				emptyGrid = false;
+			}
+		}
+		return emptyGrid;
+	}
+	
 	private void stageWidthResizeEvent(Stage stage, GridPane gridPane) {
 		stage.widthProperty().addListener((obs, oldVal, newVal) -> {
 			if (newVal.doubleValue() < stage.getHeight())  {