// Sudoku Solver By TechKiwiGadgets May 2019
/*
* V1 - Final Product Version for First Instructables Release based off dev version 101
* - Solve now includes help test at end of solve to highlight any errors in red
* - Includes 5th Hard puzzle as a challenge!
*
*
*
*
*
*
*
*
*
* ARRAY POSITIONS & KEY VARIABLES BELOW *************************************************************
// Array with following locations: {0 , 1 , 2 3 4, 5, 6, 7, 8, 9,10,11,12, 13 }
// Array with following Structure: {Solved, value , X , Y , V1,V2,V3,V4,V5,V6,V7,V8,V9 panel# }
colcoord[9] = { 10, 34, 58, 90, 114, 138, 170, 194, 218 };
rowcoord[9] = { 8, 33, 58, 88, 113, 138, 170, 194, 218 };
int location = 1;
const int sudoku[81][12];
*/
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>
#define YP A3 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 9 // can be a digital pin
#define XP 8 // can be a digital pin
// Revised Touch Callibration numbers
#define TS_MINX 130
#define TS_MINY 88
#define TS_MAXX 915
//#define TS_MAXY 927
#define TS_MAXY 880
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4
// Assign human-readable names to some common 16-bit color values:
// I had to reverse these colors for my screen
int BLACK = 0x0000;
int RED = 0x001F;
int BLUE = 0xF800;
int GREEN = 0x07E0;
int YELLOW = 0x07FF;
int MAGENTA = 0xF81F;
int CYAN = 0xFFE0;
int WHITE = 0xFFFF;
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
#define BOX 78 // Block to clear screen
#define BOXSIZE 80
#define BUTTON 20
boolean debounce = false; // Used to debounce touch screen input
// Array with following Structure: {value , X , Y , Solved }
const byte colcoord[9] = { 10, 34, 58, 90, 114, 138, 170, 194, 218 };
const byte rowcoord[9] = { 8, 33, 58, 88, 113, 138, 170, 194, 218 };
byte location = 1;
byte puzzlenum = 1; // These identifier for 5 puzzles stored in memory
byte sudoku[82][14];
byte touchlocation = 0; // Used to track the array value that the stylis is closest to in the Sudoku 9x9 framework
int delay1 = 400; // Pause input into screen
byte tempreading = 0;
void setup(void) {
// Serial.begin(9600);
// Serial.println(F("Paint!"));
tft.reset();
uint16_t identifier = tft.readID();
identifier=0x9325;
tft.begin(identifier);
tft.setRotation(1);
tft.fillScreen(BLACK);
// **** Splash Screen
tft.drawRoundRect(0, 0, 320, 240, 20, BLUE);
tft.drawRoundRect(1, 1, 318, 238, 20, BLUE);
byte g = 70;
tft.drawCircle(46, g, 25, GREEN);
tft.fillCircle(46, g, 20, GREEN);
tft.setTextColor(BLACK); tft.setTextSize(3);
tft.setCursor(39, g-10); tft.println("S");
tft.drawCircle(91, g+30, 25, BLUE);
tft.fillCircle(91, g+30, 20, BLUE);
tft.setTextColor(BLACK); tft.setTextSize(3);
tft.setCursor(84, g+20); tft.println("U");
tft.drawCircle(137, g, 25, YELLOW);
tft.fillCircle(137, g, 20, YELLOW);
tft.setTextColor(BLACK); tft.setTextSize(3);
tft.setCursor(130, g-10); tft.println("D");
tft.drawCircle(183, g+30, 25, RED);
tft.fillCircle(183, g+30, 20, RED);
tft.setTextColor(BLACK); tft.setTextSize(3);
tft.setCursor(176, g+20); tft.println("O");
tft.drawCircle(229, g, 25, GREEN);
tft.fillCircle(229, g, 20, GREEN);
tft.setTextColor(BLACK); tft.setTextSize(3);
tft.setCursor(222, g-10); tft.println("K");
tft.drawCircle(274, g+30, 25, YELLOW);
tft.fillCircle(274, g+30, 20, YELLOW);
tft.setTextColor(BLACK); tft.setTextSize(3);
tft.setCursor(267, g+20); tft.println("U");
tft.setTextColor(WHITE); tft.setTextSize(2);
tft.setCursor(25, 170); tft.println("Play, Create, Solve");
tft.setTextColor(GREEN); tft.setTextSize(1);
tft.setCursor(25, 200); tft.println("By TechKiwiGadgets 2019");
delay(4000);
tft.fillScreen(BLACK);
drawscreen(); // Clearscreen and setup Sudoku matrix
resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero and loading in the coordinates for each touch location
loadpaneldata(); // Load specifc Panel identification Data into the Array for each of the 81 locations
solvealigndata(); // Sanitize test puzzle data with correct data format
// Test Display by showing all values in the puzzle - White are Solved , Blue are others
tft.setTextSize(2);
for (byte a = 1; a < 82; a++) {
//Test solve or set condition
if (sudoku[a][1] != 0) {
if (sudoku[a][0] != 0) {
tft.setTextColor(WHITE);
} else {
tft.setTextColor(GREEN); // Set this colour if not a genuine set clue
}
tft.setCursor( sudoku[a][3], sudoku[a][2]);
tft.println(sudoku[a][1]);
}
}
drawbuttons();
pinMode(13, OUTPUT);
// testText();
}
#define MINPRESSURE 5
#define MAXPRESSURE 1000
// tft.begin(identifier);
void loop()
{
// Read the Touch Screen Locations
digitalWrite(13, HIGH);
TSPoint p = ts.getPoint();
digitalWrite(13, LOW);
// if sharing pins, you'll need to fix the directions of the touchscreen pins
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
/*
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print("\tPressure = "); Serial.println(p.z);
*/
// scale from 0->1023 to tft.width
p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320); // Original Code
/*
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print("\tPressure = "); Serial.println(p.z);
*/
// Calculate the position of the screen touch based on the input values of p.x and p.y
if ((p.x > 0) && (p.x < 27)) { // Coloumn 1
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 1;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 2;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 3;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 4;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 5;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 6;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 7;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 8;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 9;
}
} else
if ((p.x > 28) && (p.x < 53)) { // Coloumn 2
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 10;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 11;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 12;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 13;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 14;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 15;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 16;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 17;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 18;
}
} else
if ((p.x > 54) && (p.x < 80)) { // Coloumn 3
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 19;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 20;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 21;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 22;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 23;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 24;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 25;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 26;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 27;
}
} else
if ((p.x > 81) && (p.x < 107)) { // Coloumn 4
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 28;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 29;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 30;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 31;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 32;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 33;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 34;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 35;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 36;
}
} else
if ((p.x > 108) && (p.x < 133)) { // Coloumn 5
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 37;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 38;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 39;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 40;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 41;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 42;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 43;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 44;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 45;
}
} else
if ((p.x > 134) && (p.x < 160)) { // Coloumn 6
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 46;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 47;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 48;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 49;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 50;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 51;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 52;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 53;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 54;
}
} else
if ((p.x > 161) && (p.x < 187)) { // Coloumn 7
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 55;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 56;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 57;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 58;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 59;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 60;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 61;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 62;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 63;
}
} else
if ((p.x > 188) && (p.x < 213)) { // Coloumn 8
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 64;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 65;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 66;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 67;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 68;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 69;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 70;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 71;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 72;
}
} else
if ((p.x > 214) && (p.x < 240)) { // Coloumn 9
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 73;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 74;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 75;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 76;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 77;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 78;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 79;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 80;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 81;
}
}
// debounce function to remove issue with first touch screen reading being spurious
if (debounce == false) {
touchlocation = 0;
debounce = true;
}
// This code only applies to stylis activity within the Sudokumatrix
if ( ((p.x < 235)&&(p.y < 230))&& (touchlocation != 0)) {
// tft.fillRect(250, 80, 15, 10, BLACK);
/*
Serial.print("Y = "); Serial.print(p.x);
Serial.print("\tX = "); Serial.print(p.y);
Serial.print("\tLocation = "); Serial.println(touchlocation);
*/
// Calculate the incremental changes to the data array
// Array Structure: {value , X , Y , Solved }
// Only increment if has not been solved, Debounce by checking if this is the second time the same range is selected
if ((tempreading == touchlocation)&&(sudoku[touchlocation][0]==0)||(tempreading == touchlocation)&&(sudoku[touchlocation][0]==2)) {
sudoku[touchlocation][1]++;
if (sudoku[touchlocation][1] > 9) {
sudoku[touchlocation][1] = 0;
}
// Test to see if changing an item can be classified as solved
if (sudoku[touchlocation][1]!=0) {
sudoku[touchlocation][0]=2; // Set to Solved if a manually changed number however flag as manual change with va,ue of 2
} else {
sudoku[touchlocation][0]=0; // Set to Not Solved if 0
}
// Finally reset all of the data values in this location that have been manually changed to unsolved
for (byte u = 1; u < 82; u++) {
// If preprogrammed from a game then leave values otherwise reset data to baseline
if (sudoku[u][0]!=1){
for (byte q = 4; q < 13; q++) {
sudoku[u][q]=q-3;
}
}
}
}
// tft.setTextColor(WHITE); tft.setTextSize(1);
// tft.setCursor(250, 80); tft.println(touchlocation);
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[touchlocation][3], sudoku[touchlocation][2], 15, 15, BLACK);
tft.setTextSize(2);
if (sudoku[touchlocation][0] != 0) { // Do not draw 0 just leave blank square
if (sudoku[touchlocation][0] == 1) {
tft.setTextColor(WHITE);
} else if (sudoku[touchlocation][0] == 2) {
tft.setTextColor(GREEN); // Set this colour if not a genuine set clue
}
tft.setCursor( sudoku[touchlocation][3], sudoku[touchlocation][2]);
tft.println(sudoku[touchlocation][1]);
}
if (tempreading == touchlocation) {
delay(delay1);
}
tempreading = touchlocation; // take a first sample then repeat and compare to debounce
}
// Inside touch sensor reading if statement
// HOME Button Pressed ************************************************
if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 10)&&(p.x < 40))) {
tft.fillCircle(280, 30, 20, WHITE);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(268, 27); tft.println("HOME");
delay(delay1/2);
drawscreen(); // Clearscreen and setup Sudoku matrix
resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero:
refreshdisplay();
drawbuttons();
}
// PLAY Button Pressed ************************************************
if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 80)&&(p.x < 110))) {
//PLAY Button pressed
//Button 2
tft.fillCircle(280, 90, 20, WHITE);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(268, 87); tft.println("PLAY");
delay(delay1/2);
drawscreen(); // Clearscreen and setup Sudoku matrix
resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero:
loadtestpuzzle1(); // Loads test puzzle into the location array
solvealigndata(); // Sanitize test puzzle data with correct data format
refreshdisplay(); // Only display testpuzzle data locations that are
drawbuttons(); // Redraw buttons togive push button effect
tft.setCursor(277, 97); tft.println(puzzlenum);
// Manage Puzzle Number
puzzlenum++; // increment puzzle number
if (puzzlenum > 5) {
puzzlenum = 1;
}
}
// HELP Button Pressed ************************************************
if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 140)&&(p.x < 160))) {
//Button 3
tft.fillCircle(280, 150, 20, WHITE);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(268, 147); tft.println("HELP");
delay(delay1/2);
// drawscreen(); // Clearscreen and setup Sudoku matrix
// solvehorizontal(); // Solve horiontal rule
// solvevertical(); // Solve vertical rule
// solvepanel(); // Solve Panel rule
helpbutton(); // Run algorythm and test for incorrect locations then highlight in red
// reversesolve();
delay(800);// Display the changes before reverting to original colors
refreshdisplay(); // Only display testpuzzle data locations that are
drawbuttons(); // Redraw buttons togive push button effect
}
// SOLVE Button Pressed ************************************************
if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 200)&&(p.x < 220))) {
//SOLVE Button Pressed
//Button 4
tft.fillCircle(280, 210, 20, WHITE);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(266, 207); tft.println("SOLVE");
delay(delay1/2);
solvepanel(); // Solve Panel rule
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
reversesolvecolor();
uniquecandidate(); // Test
solvealigndata();
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
solvepanel(); // Solve Panel rule
reversesolvecolor();
solvepanel(); // Solve Panel rule
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
reversesolvecolor();
uniquecandidate(); // Test
solvealigndata();
reversesolvecolor();
solvepanel(); // Solve Panel rule
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
reversesolvecolor();
uniquecandidate(); // Test
solvealigndata();
reversesolvecolor();
solvepanel(); // Solve Panel rule
solvehorizontal(); // Solve horiontal rule
solvevertical(); // Solve vertical rule
reversesolvecolor();
uniquecandidate(); // Test
solvealigndata();
reversesolvecolor();
drawscreen(); // Clearscreen and setup Sudoku matrix
refreshdisplay(); // Only display testpuzzle data locations that are
helpbutton(); // Run algorythm and test for incorrect locations then highlight in red
drawbuttons(); // Redraw buttons togive push button effect
}
/*
Serial.print("Y = "); Serial.print(p.x);
Serial.print("\tX = "); Serial.println(p.y);
*/
p.z = 0;// Force the sensor value below threshold to avoid ghost values
}
}
void loadtestpuzzle1(){
// Test Puzzle example 1 loaded into array
if (puzzlenum == 1 ){
// Load Numbers
sudoku[1][1] = 2; sudoku[3][1] = 9; sudoku[19][1] = 3; sudoku[21][1] = 5;
sudoku[5][1] = 6; sudoku[6][1] = 3; sudoku[14][1] = 2; sudoku[23][1] = 9;
sudoku[7][1] = 4; sudoku[9][1] = 8; sudoku[26][1] = 7;
sudoku[39][1] = 1; sudoku[46][1] = 9; sudoku[47][1] = 7; sudoku[48][1] = 2;
sudoku[31][1] = 9; sudoku[32][1] = 8; sudoku[50][1] = 1; sudoku[51][1] = 6;
sudoku[34][1] = 7; sudoku[35][1] = 1; sudoku[36][1] = 6; sudoku[43][1] = 2;
sudoku[56][1] = 3; sudoku[73][1] = 5; sudoku[75][1] = 6;
sudoku[59][1] = 7; sudoku[68][1] = 3; sudoku[76][1] = 1; sudoku[77][1] = 4;
sudoku[61][1] = 6; sudoku[63][1] = 1; sudoku[79][1] = 8; sudoku[81][1] = 7;
// Set the Solved Flag for each
sudoku[1][0] = 1; sudoku[3][0] = 1; sudoku[19][0] = 1; sudoku[21][0] = 1;
sudoku[5][0] = 1; sudoku[6][0] = 1; sudoku[14][0] = 1; sudoku[23][0] = 1;
sudoku[7][0] = 1; sudoku[9][0] = 1; sudoku[26][0] = 1;
sudoku[39][0] = 1; sudoku[46][0] = 1; sudoku[47][0] = 1; sudoku[48][0] = 1;
sudoku[31][0] = 1; sudoku[32][0] = 1; sudoku[50][0] = 1; sudoku[51][0] = 1;
sudoku[34][0] = 1; sudoku[35][0] = 1; sudoku[36][0] = 1; sudoku[43][0] = 1;
sudoku[56][0] = 1; sudoku[73][0] = 1; sudoku[75][0] = 1;
sudoku[59][0] = 1; sudoku[68][0] = 1; sudoku[76][0] = 1; sudoku[77][0] = 1;
sudoku[61][0] = 1; sudoku[63][0] = 1; sudoku[79][0] = 1; sudoku[81][0] = 1;
} else
if (puzzlenum == 2 ){
// Load Numbers
sudoku[1][1] = 4; sudoku[10][1] = 2; sudoku[19][1] = 1;
sudoku[5][1] = 2; sudoku[15][1] = 4; sudoku[24][1] = 5;
sudoku[25][1] = 2; sudoku[17][1] = 8; sudoku[18][1] = 6;
sudoku[29][1] = 3; sudoku[30][1] = 2; sudoku[37][1] = 9; sudoku[39][1] = 5; sudoku[46][1] = 7; sudoku[47][1] = 6;
sudoku[31][1] = 6; sudoku[40][1] = 4; sudoku[41][1] = 8; sudoku[42][1] = 3; sudoku[51][1] = 2;
sudoku[35][1] = 4; sudoku[36][1] = 1; sudoku[43][1] = 6; sudoku[45][1] = 2; sudoku[52][1] = 3; sudoku[53][1] = 5;
sudoku[57][1] = 1; sudoku[64][1] = 3; sudoku[65][1] = 8;
sudoku[58][1] = 7; sudoku[67][1] = 5; sudoku[77][1] = 9;
sudoku[63][1] = 9; sudoku[72][1] = 7; sudoku[81][1] = 5;
// Set the Solved Flag for each
sudoku[1][0] = 1; sudoku[10][0] = 1; sudoku[19][0] = 1;
sudoku[5][0] = 1; sudoku[15][0] = 1; sudoku[24][0] = 1;
sudoku[25][0] = 1; sudoku[17][0] = 1; sudoku[18][0] = 1;
sudoku[29][0] = 1; sudoku[30][0] = 1; sudoku[37][0] = 1; sudoku[39][0] = 1; sudoku[46][0] = 1; sudoku[47][0] = 1;
sudoku[31][0] = 1; sudoku[40][0] = 1; sudoku[41][0] = 1; sudoku[42][0] = 1; sudoku[51][0] = 1;
sudoku[35][0] = 1; sudoku[36][0] = 1; sudoku[43][0] = 1; sudoku[45][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1;
sudoku[57][0] = 1; sudoku[64][0] = 1; sudoku[65][0] = 1;
sudoku[58][0] = 1; sudoku[67][0] = 1; sudoku[77][0] = 1;
sudoku[63][0] = 1; sudoku[72][0] = 1; sudoku[81][0] = 1;
} else
if (puzzlenum == 3 ){
// Load Numbers
sudoku[12][1] = 8; sudoku[19][1] = 4;
sudoku[5][1] = 2; sudoku[13][1] = 9; sudoku[14][1] = 4; sudoku[22][1] = 7; sudoku[24][1] = 8;
sudoku[7][1] = 8; sudoku[9][1] = 7; sudoku[25][1] = 2; sudoku[27][1] = 9;
sudoku[28][1] = 1; sudoku[29][1] = 2; sudoku[38][1] = 4; sudoku[39][1] = 3; sudoku[30][1] = 7;
sudoku[31][1] = 5; sudoku[41][1] = 8; sudoku[51][1] = 7;
sudoku[43][1] = 5; sudoku[44][1] = 7; sudoku[52][1] = 9; sudoku[53][1] = 2; sudoku[54][1] = 4;
sudoku[55][1] = 8; sudoku[57][1] = 9; sudoku[73][1] = 6; sudoku[75][1] = 4;
sudoku[58][1] = 1; sudoku[60][1] = 2; sudoku[68][1] = 6; sudoku[69][1] = 9; sudoku[77][1] = 3;
sudoku[70][1] = 1; sudoku[63][1] = 3;
// Set the Solved Flag for each
sudoku[12][0] = 1; sudoku[19][0] = 1;
sudoku[5][0] = 1; sudoku[13][0] = 1; sudoku[14][0] = 1; sudoku[22][0] = 1; sudoku[24][0] = 1;
sudoku[7][0] = 1; sudoku[9][0] = 1; sudoku[25][0] = 1; sudoku[27][0] = 1;
sudoku[28][0] = 1; sudoku[29][0] = 1; sudoku[38][0] = 1; sudoku[39][0] = 1; sudoku[30][0] = 1;
sudoku[31][0] = 1; sudoku[41][0] = 1; sudoku[51][0] = 1;
sudoku[43][0] = 1; sudoku[44][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1; sudoku[54][0] = 1;
sudoku[55][0] = 1; sudoku[57][0] = 1; sudoku[73][0] = 1; sudoku[75][0] = 1;
sudoku[58][0] = 1; sudoku[60][0] = 1; sudoku[68][0] = 1; sudoku[69][0] = 1; sudoku[77][0] = 1;
sudoku[70][0] = 1; sudoku[63][0] = 1;
} else
if (puzzlenum == 4 ){
// Load Numbers
sudoku[3][1] = 6; sudoku[12][1] = 2;
sudoku[5][1] = 7; sudoku[6][1] = 9; sudoku[13][1] = 1;
sudoku[16][1] = 6; sudoku[17][1] = 5; sudoku[18][1] = 4; sudoku[25][1] = 7; sudoku[26][1] = 1;
sudoku[29][1] = 6; sudoku[30][1] = 5; sudoku[37][1] = 8; sudoku[46][1] = 1; sudoku[48][1] = 3;
sudoku[33][1] = 4; sudoku[40][1] = 7; sudoku[41][1] = 2; sudoku[42][1] = 5; sudoku[49][1] = 8;
sudoku[34][1] = 9; sudoku[36][1] = 8; sudoku[45][1] = 3; sudoku[52][1] = 4; sudoku[53][1] = 7;
sudoku[56][1] = 3; sudoku[57][1] = 7; sudoku[64][1] = 6; sudoku[65][1] = 4;sudoku[66][1] = 1;
sudoku[76][1] = 6; sudoku[77][1] = 4; sudoku[69][1] = 3;
sudoku[70][1] = 8; sudoku[79][1] = 5;
// Set the Solved Flag for each
sudoku[3][0] = 1; sudoku[12][0] = 1;
sudoku[5][0] = 1; sudoku[6][0] = 1; sudoku[13][0] = 1;
sudoku[16][0] = 1; sudoku[17][0] = 1; sudoku[18][0] = 1; sudoku[25][0] = 1; sudoku[26][0] = 1;
sudoku[29][0] = 1; sudoku[30][0] = 1; sudoku[37][0] = 1; sudoku[46][0] = 1; sudoku[48][0] = 1;
sudoku[33][0] = 1; sudoku[40][0] = 1; sudoku[41][0] = 1; sudoku[42][0] = 1; sudoku[49][0] = 1;
sudoku[34][0] = 1; sudoku[36][0] = 1; sudoku[45][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1;
sudoku[56][0] = 1; sudoku[57][0] = 1; sudoku[64][0] = 1; sudoku[65][0] = 1;sudoku[66][0] = 1;
sudoku[76][0] = 1; sudoku[77][0] = 1; sudoku[69][0] = 1;
sudoku[70][0] = 1; sudoku[79][0] = 1;
} else
if (puzzlenum == 5 ){
// Load Numbers
sudoku[2][1] = 3; sudoku[3][1] = 2; sudoku[12][1] = 6; sudoku[21][1] = 9;
sudoku[4][1] = 9; sudoku[5][1] = 8; sudoku[22][1] = 2;
sudoku[17][1] = 3; sudoku[27][1] = 7;
sudoku[30][1] = 7; sudoku[47][1] = 9;
sudoku[31][1] = 1; sudoku[40][1] = 3; sudoku[42][1] = 5; sudoku[51][1] = 4;
sudoku[35][1] = 5; sudoku[52][1] = 6;
sudoku[55][1] = 2; sudoku[65][1] = 6;
sudoku[60][1] = 9; sudoku[77][1] = 5; sudoku[78][1] = 3;
sudoku[61][1] = 3; sudoku[70][1] = 7; sudoku[79][1] = 2; sudoku[80][1] = 6;
// Set the Solved Flag for each
sudoku[2][0] = 1; sudoku[3][0] = 1; sudoku[12][0] = 1; sudoku[21][0] = 1;
sudoku[4][0] = 1; sudoku[5][0] = 1; sudoku[22][0] = 1;
sudoku[17][0] = 1; sudoku[27][0] = 1;
sudoku[30][0] = 1; sudoku[47][0] = 1;
sudoku[31][0] = 1; sudoku[40][0] = 1; sudoku[42][0] = 1; sudoku[51][0] = 1;
sudoku[35][0] = 1; sudoku[52][0] = 1;
sudoku[55][0] = 1; sudoku[65][0] = 1;
sudoku[60][0] = 1; sudoku[77][0] = 1; sudoku[78][0] = 1;
sudoku[61][0] = 1; sudoku[70][0] = 1; sudoku[79][0] = 1; sudoku[80][0] = 1;
}
}
void refreshdisplay() { //Refresh the display once a value has changed
tft.setTextSize(2);
for (byte a = 1; a < 82; a++) {
//Test solve or set condition
if (sudoku[a][1] != 0) {
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
if (sudoku[a][0] != 0) { // Do not draw 0 just leave blank square
if (sudoku[a][0] == 1) {
tft.setTextColor(WHITE);
} else if (sudoku[a][0] == 2) {
tft.setTextColor(GREEN); // Set this colour if not a genuine set clue
}
tft.setCursor( sudoku[a][3], sudoku[a][2]);
tft.println(sudoku[a][1]);
}
}
}
}
void drawscreen(){
// tft.fillScreen(BLACK);
// Setup Screen
GREEN = 0x07E0;
tft.fillRect(1, 1, 239, 239, BLACK);
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0+BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0+BOXSIZE+BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0+BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0+BOXSIZE+BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0+BOXSIZE, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0+BOXSIZE+BOXSIZE, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE);
}
void resetmatrix(){ // Initialize the sudoku matrix by setting all locations to zero and loading in the coordinates for each touch location
byte hole = 1;
for (byte a = 0; a < 9; a++) {
for (byte b = 0; b < 9; b++) {
sudoku[hole][0] = 0; // Solve Flag
sudoku[hole][1] = 0; // Display Value
sudoku[hole][2] = colcoord[a]; // Matrix Column coordinate
sudoku[hole][3] = rowcoord[b]; // Matrix Row coordinate
sudoku[hole][4] = 1; // V1
sudoku[hole][5] = 2; // V2
sudoku[hole][6] = 3; // V3
sudoku[hole][7] = 4; // V4
sudoku[hole][8] = 5; // V5
sudoku[hole][9] = 6; // V6
sudoku[hole][10] = 7; // V7
sudoku[hole][11] = 8; // V8
sudoku[hole][12] = 9; // V9
hole++;
}
}
}
void drawbuttons() {
// Setup Buttons
GREEN = 0x07E0;
//Button 1
tft.drawCircle(280, 30, 24, GREEN);
tft.fillCircle(280, 30, 20, GREEN);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(268, 27); tft.println("HOME");
//Button 2
tft.drawCircle(280, 90, 24, YELLOW);
tft.fillCircle(280, 90, 20, YELLOW);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(268, 87); tft.println("PLAY");
//Button 3
tft.drawCircle(280, 150, 24, MAGENTA);
tft.fillCircle(280, 150, 20, MAGENTA);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(268, 147); tft.println("HELP");
//Button 4
tft.drawCircle(280, 210, 24, BLUE);
tft.fillCircle(280, 210, 20, BLUE);
tft.setTextColor(BLACK); tft.setTextSize(1);
tft.setCursor(266, 207); tft.println("SOLVE");
}
void solvealigndata(){ // Once a location is marked as solved then all data in that location nees to be set to Zero
for (byte a = 1; a < 82; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // If location solved then zero out all data in array except correct value
/*
Serial.print(a); Serial.print(" ");
Serial.print(sudoku[a][1]); Serial.print(" ");
Serial.print(3+sudoku[a][1]); Serial.print(" ");
Serial.print(sudoku[a][4]);
Serial.print(sudoku[a][5]);
Serial.print(sudoku[a][6]);
Serial.print(sudoku[a][7]);
Serial.print(sudoku[a][8]);
Serial.print(sudoku[a][9]);
Serial.print(sudoku[a][10]);
Serial.print(sudoku[a][11]);
Serial.println(sudoku[a][12]);
*/
sudoku[a][4] = 0; // V1
sudoku[a][5] = 0; // V2
sudoku[a][6] = 0; // V3
sudoku[a][7] = 0; // V4
sudoku[a][8] = 0; // V5
sudoku[a][9] = 0; // V6
sudoku[a][10] = 0; // V7
sudoku[a][11] = 0; // V8
sudoku[a][12] = 0; // V9
// Now poke the answer into the correct location
sudoku[a][(sudoku[a][1]+3)] = sudoku[a][1]; // Load the solved value into the array
/*
Serial.print(a); Serial.print(" ");
Serial.print(sudoku[a][1]); Serial.print(" ");
Serial.print(3+sudoku[a][1]); Serial.print(" ");
Serial.print(sudoku[a][4]);
Serial.print(sudoku[a][5]);
Serial.print(sudoku[a][6]);
Serial.print(sudoku[a][7]);
Serial.print(sudoku[a][8]);
Serial.print(sudoku[a][9]);
Serial.print(sudoku[a][10]);
Serial.print(sudoku[a][11]);
Serial.println(sudoku[a][12]);
*/
}
}
}
void reversesolve(){ // subroutine to reverse engineer solved locations in the matrix and label themas solved
byte tempcount = 0;
for (byte a = 1; a < 82; a++) { // Cycle through all locations
/*
Serial.print(a); Serial.print(" ");
Serial.print(sudoku[a][0]); Serial.print(" ");
// Serial.print(3+sudoku[a][1]); Serial.print(" ");
Serial.print(sudoku[a][4]);
Serial.print(sudoku[a][5]);
Serial.print(sudoku[a][6]);
Serial.print(sudoku[a][7]);
Serial.print(sudoku[a][8]);
Serial.print(sudoku[a][9]);
Serial.print(sudoku[a][10]);
Serial.print(sudoku[a][11]);
Serial.println(sudoku[a][12]);
*/
if (sudoku[a][0] == 0) { // Ignore location if already solved
// Read each and count the number that have been elimated
tempcount = 0;
for (byte b = 4; b < 13; b++) {
if (sudoku[a][b] == 0) {// If equal to 0 then count
tempcount++;
}
}
if (tempcount == 8){ // If only one valid result then find again then mark location as solved
for (byte c = 4; c < 13; c++) { // Read each and identify the only solution
if (sudoku[a][c] > 0) {
sudoku[a][0] = 1; // Set Solved Location Flag
sudoku[a][1] = sudoku[a][c]; // Set value
}
}
}
}
/*
Serial.print(a); Serial.print(" ");
Serial.print(sudoku[a][0]); Serial.print(" ");
Serial.print(tempcount); Serial.print(" ");
Serial.print(sudoku[a][4]);
Serial.print(sudoku[a][5]);
Serial.print(sudoku[a][6]);
Serial.print(sudoku[a][7]);
Serial.print(sudoku[a][8]);
Serial.print(sudoku[a][9]);
Serial.print(sudoku[a][10]);
Serial.print(sudoku[a][11]);
Serial.println(sudoku[a][12]);
*/
}
}
void reversesolvecolor(){ // subroutine to reverse engineer solved locations in the matrix and label themas solved
byte tempcount = 0;
for (byte a = 1; a < 82; a++) { // Cycle through all locations
/*
Serial.print(a); Serial.print(" ");
Serial.print(sudoku[a][0]); Serial.print(" ");
// Serial.print(3+sudoku[a][1]); Serial.print(" ");
Serial.print(sudoku[a][4]);
Serial.print(sudoku[a][5]);
Serial.print(sudoku[a][6]);
Serial.print(sudoku[a][7]);
Serial.print(sudoku[a][8]);
Serial.print(sudoku[a][9]);
Serial.print(sudoku[a][10]);
Serial.print(sudoku[a][11]);
Serial.println(sudoku[a][12]);
*/
if (sudoku[a][0] == 0) { // Ignore location if already solved
// Read each and count the number that have been elimated
tempcount = 0;
for (byte b = 4; b < 13; b++) {
if (sudoku[a][b] == 0) {// If equal to 0 then count
tempcount++;
}
}
if (tempcount == 8){ // If only one valid result then find again then mark location as solved
for (byte c = 4; c < 13; c++) { // Read each and identify the only solution
if (sudoku[a][c] > 0) {
sudoku[a][0] = 2; // Set Solved Location Flag
sudoku[a][1] = sudoku[a][c]; // Set value
}
}
}
}
/*
Serial.print(a); Serial.print(" ");
Serial.print(sudoku[a][0]); Serial.print(" ");
Serial.print(tempcount); Serial.print(" ");
Serial.print(sudoku[a][4]);
Serial.print(sudoku[a][5]);
Serial.print(sudoku[a][6]);
Serial.print(sudoku[a][7]);
Serial.print(sudoku[a][8]);
Serial.print(sudoku[a][9]);
Serial.print(sudoku[a][10]);
Serial.print(sudoku[a][11]);
Serial.println(sudoku[a][12]);
*/
}
}
void solvehorizontal(){ // Take Solved locations and apply horizontal rule
// Cycle through all locations and using solved flag remove all associate horizontal possibilities
/*
for (byte d = 1; d < 82; d++) { // Cycle through all locations
Serial.print(d); Serial.print(" ");
Serial.print(sudoku[d][0]); Serial.print(" ");
Serial.print(sudoku[d][4]);
Serial.print(sudoku[d][5]);
Serial.print(sudoku[d][6]);
Serial.print(sudoku[d][7]);
Serial.print(sudoku[d][8]);
Serial.print(sudoku[d][9]);
Serial.print(sudoku[d][10]);
Serial.print(sudoku[d][11]);
Serial.println(sudoku[d][12]);
}
*/
// ROW 1 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 1; a < 10; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 1; r < 10; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 2 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 10; a < 19; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 10; r < 19; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 3 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 19; a < 28; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 19; r < 28; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 4 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 28; a < 37; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 28; r < 37; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 5 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 37; a < 46; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 37; r < 46; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 6 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 46; a < 55; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 46; r < 55; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 7 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 55; a < 64; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 55; r < 64; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 8 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 64; a < 73; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 64; r < 73; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// ROW 9 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 73; a < 82; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 73; r < 82; r++) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
/*
for (byte e = 1; e < 82; e++) { // Cycle through all locations
Serial.print(e); Serial.print(" ");
Serial.print(sudoku[e][0]); Serial.print(" ");
Serial.print(sudoku[e][4]);
Serial.print(sudoku[e][5]);
Serial.print(sudoku[e][6]);
Serial.print(sudoku[e][7]);
Serial.print(sudoku[e][8]);
Serial.print(sudoku[e][9]);
Serial.print(sudoku[e][10]);
Serial.print(sudoku[e][11]);
Serial.println(sudoku[e][12]);
}
*/
}
void solvevertical(){ // Take Solved locations and apply horizontal rule
// Cycle through all locations and using solved flag remove all associate vertical possibilities
/*
for (byte d = 1; d < 82; d++) { // Cycle through all locations
Serial.print(d); Serial.print(" ");
Serial.print(sudoku[d][0]); Serial.print(" ");
Serial.print(sudoku[d][4]);
Serial.print(sudoku[d][5]);
Serial.print(sudoku[d][6]);
Serial.print(sudoku[d][7]);
Serial.print(sudoku[d][8]);
Serial.print(sudoku[d][9]);
Serial.print(sudoku[d][10]);
Serial.print(sudoku[d][11]);
Serial.println(sudoku[d][12]);
}
*/
// COL 1 ************************
// Step through each of Col locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 1; a < 74; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 1; r < 74; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 2 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 2; a < 75; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 2; r < 75; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 3 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 3; a < 76; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 3; r < 76; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 4 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 4; a < 77; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 4; r < 77; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 5 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 5; a < 78; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 5; r < 78; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 6 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 6; a < 79; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 6; r < 79; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 7 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 7; a < 80; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 7; r < 80; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 8 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 8; a < 81; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 8; r < 81; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
// COL 9 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 9; a < 82; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 9; r < 83; r=r+9) {
if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
/*
for (byte e = 1; e < 82; e++) { // Cycle through all locations
Serial.print(e); Serial.print(" ");
Serial.print(sudoku[e][0]); Serial.print(" ");
Serial.print(sudoku[e][4]);
Serial.print(sudoku[e][5]);
Serial.print(sudoku[e][6]);
Serial.print(sudoku[e][7]);
Serial.print(sudoku[e][8]);
Serial.print(sudoku[e][9]);
Serial.print(sudoku[e][10]);
Serial.print(sudoku[e][11]);
Serial.println(sudoku[e][12]);
}
*/
}
void solvepanel(){ // Take Solved locations and apply horizontal rule
// Cycle through all locations and using solved flag remove all associate panel possibilities
/*
for (byte d = 1; d < 82; d++) { // Cycle through all locations
Serial.print(d); Serial.print(" ");
Serial.print(sudoku[d][0]); Serial.print(" ");
Serial.print(sudoku[d][4]);
Serial.print(sudoku[d][5]);
Serial.print(sudoku[d][6]);
Serial.print(sudoku[d][7]);
Serial.print(sudoku[d][8]);
Serial.print(sudoku[d][9]);
Serial.print(sudoku[d][10]);
Serial.print(sudoku[d][11]);
Serial.println(sudoku[d][12]);
}
*/
// PANEL Algorythm ************************
// Step through each of locations and delete duplicates of the Solved location using the panel formulae. Ignore the current location you are solving for
for (byte a = 1; a < 82; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 1; r < 82; r++) { // Step through all locations
if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { // Identify the locations on the Same Panel
if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) {
sudoku[r][sudoku[a][1]+3] = 0;
}
}
}
}
}
/*
for (byte e = 1; e < 82; e++) { // Cycle through all locations
Serial.print(e); Serial.print(" ");
Serial.print(sudoku[e][0]); Serial.print(" ");
Serial.print(sudoku[e][4]);
Serial.print(sudoku[e][5]);
Serial.print(sudoku[e][6]);
Serial.print(sudoku[e][7]);
Serial.print(sudoku[e][8]);
Serial.print(sudoku[e][9]);
Serial.print(sudoku[e][10]);
Serial.print(sudoku[e][11]);
Serial.println(sudoku[e][12]);
*/
}
void loadpaneldata(){ // Load specifc Panel identification Data into the Array for each of the 81 locations
// Load Numbers
// Panel 1
sudoku[1][13] = 1; sudoku[2][13] = 1; sudoku[3][13] = 1;
sudoku[10][13] = 1; sudoku[11][13] = 1; sudoku[12][13] = 1;
sudoku[19][13] = 1; sudoku[20][13] = 1; sudoku[21][13] = 1;
// Panel 2
sudoku[4][13] = 2; sudoku[5][13] = 2; sudoku[6][13] = 2;
sudoku[13][13] = 2; sudoku[14][13] = 2; sudoku[15][13] = 2;
sudoku[22][13] = 2; sudoku[23][13] = 2; sudoku[24][13] = 2;
// Panel 3
sudoku[7][13] = 3; sudoku[8][13] = 3; sudoku[9][13] = 3;
sudoku[16][13] = 3; sudoku[17][13] = 3; sudoku[18][13] = 3;
sudoku[25][13] = 3; sudoku[26][13] = 3; sudoku[27][13] = 3;
// Panel 4
sudoku[28][13] = 4; sudoku[29][13] = 4; sudoku[30][13] = 4;
sudoku[37][13] = 4; sudoku[38][13] = 4; sudoku[39][13] = 4;
sudoku[46][13] = 4; sudoku[47][13] = 4; sudoku[48][13] = 4;
// Panel 5
sudoku[31][13] = 5; sudoku[32][13] = 5; sudoku[33][13] = 5;
sudoku[40][13] = 5; sudoku[41][13] = 5; sudoku[42][13] = 5;
sudoku[49][13] = 5; sudoku[50][13] = 5; sudoku[51][13] = 5;
// Panel 6
sudoku[34][13] = 6; sudoku[35][13] = 6; sudoku[36][13] = 6;
sudoku[43][13] = 6; sudoku[44][13] = 6; sudoku[45][13] = 6;
sudoku[52][13] = 6; sudoku[53][13] = 6; sudoku[54][13] = 6;
// Panel 7
sudoku[55][13] = 7; sudoku[56][13] = 7; sudoku[57][13] = 7;
sudoku[64][13] = 7; sudoku[65][13] = 7; sudoku[66][13] = 7;
sudoku[73][13] = 7; sudoku[74][13] = 7; sudoku[75][13] = 7;
// Panel 8
sudoku[58][13] = 8; sudoku[59][13] = 8; sudoku[60][13] = 8;
sudoku[67][13] = 8; sudoku[68][13] = 8; sudoku[69][13] = 8;
sudoku[76][13] = 8; sudoku[77][13] = 8; sudoku[78][13] = 8;
// Panel 9
sudoku[61][13] = 9; sudoku[62][13] = 9; sudoku[63][13] = 9;
sudoku[70][13] = 9; sudoku[71][13] = 9; sudoku[72][13] = 9;
sudoku[79][13] = 9; sudoku[80][13] = 9; sudoku[81][13] = 9;
}
// Used to identify and highlight errors in a current matrix - use solve method however instead of solving outcome just highlight conflicts in red
void helpbutton(){
// Horizontal *********************
// ROW 1 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 1; a < 10; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 1; r < 10; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 2 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 10; a < 19; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 10; r < 19; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 3 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 19; a < 28; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 19; r < 28; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 4 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 28; a < 37; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 28; r < 37; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 5 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 37; a < 46; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 37; r < 46; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 6 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 46; a < 55; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 46; r < 55; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 7 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 55; a < 64; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 55; r < 64; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 8 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 64; a < 73; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 64; r < 73; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// ROW 9 ************************
// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 73; a < 82; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 73; r < 82; r++) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// Vertical ****************
// COL 1 ************************
// Step through each of Col locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 1; a < 74; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 1; r < 74; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 2 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 2; a < 75; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 2; r < 75; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 3 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 3; a < 76; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 3; r < 76; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 4 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 4; a < 77; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 4; r < 77; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 5 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 5; a < 78; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 5; r < 78; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 6 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 6; a < 79; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 6; r < 79; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 7 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 7; a < 80; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 7; r < 80; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 8 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 8; a < 81; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 8; r < 81; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// COL 9 ************************
// Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for
for (byte a = 9; a < 82; a=a+9) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 9; r < 83; r=r+9) {
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
// Panels *******************
// PANEL Algorythm ************************
// Step through each of locations and delete duplicates of the Solved location using the Oanel formulae. Ignore the current location you are solving for
for (byte a = 1; a < 82; a++) { // Cycle through all locations
if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry
for (byte r = 1; r < 82; r++) { // Step through all locations
if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { // Identify the locations on the Same Panel
if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED
// Refresh only the location concerned with new value and show colour coded
//First Clear Location
tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]);
}
}
}
}
}
// Horizontal conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE
// Vertical conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE
// Panel conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE
}
void uniquecandidate() { // Each panel, row and column on a Sudoku board must contain every number between 1 and 9.
// Therefore, if a number, say 4, can only be put in a single cell within a block/column/row, then that number is guaranteed to fit there.
/*
for (byte d = 1; d < 82; d++) { // Cycle through all locations
Serial.print(d); Serial.print(" ");
Serial.print(sudoku[d][0]); Serial.print(" ");
Serial.print(sudoku[d][1]); Serial.print(" ");
Serial.print(sudoku[d][4]);
Serial.print(sudoku[d][5]);
Serial.print(sudoku[d][6]);
Serial.print(sudoku[d][7]);
Serial.print(sudoku[d][8]);
Serial.print(sudoku[d][9]);
Serial.print(sudoku[d][10]);
Serial.print(sudoku[d][11]);
Serial.println(sudoku[d][12]);
}
*/
byte tempcount = 0;
for (byte p = 1; p < 10; p++) { // Cycle through all panels 1 to 9
for (byte v = 1; v < 10; v++) { // Step through all possible unique location values in each panel
for (byte r = 1; r < 82; r++) { // Step through all locations
if (sudoku[r][13] == p) { //Only operate on those locations that are in this panel
if (sudoku[r][v+3] == v) {// Count this if value is what we are looking for
tempcount++;
}
}
}
// Check if unique
if ( tempcount == 1) { // This is a unique value so reset the location with this being a solved location
// Repeat process to locate unique location
for (byte r = 1; r < 82; r++) { // Step through all locations and then mark as solved
if (sudoku[r][13] == p) { //Only operate on those locations that are in this panel
if (sudoku[r][v+3] == v) {// Count this if value is what we are looking for
// Now poke the answer into the correct location
if (sudoku[r][0] == 0) { // Change to solved but remain green
sudoku[r][0] = 2;
}
sudoku[r][1] = v;
}
}
}
}
// Reset temp counter
tempcount = 0;
}
}
/*
for (byte d = 1; d < 82; d++) { // Cycle through all locations
Serial.print(d); Serial.print(" ");
Serial.print(sudoku[d][0]); Serial.print(" ");
Serial.print(sudoku[d][1]); Serial.print(" ");
Serial.print(sudoku[d][4]);
Serial.print(sudoku[d][5]);
Serial.print(sudoku[d][6]);
Serial.print(sudoku[d][7]);
Serial.print(sudoku[d][8]);
Serial.print(sudoku[d][9]);
Serial.print(sudoku[d][10]);
Serial.print(sudoku[d][11]);
Serial.println(sudoku[d][12]);
}
*/
}
Comments