Components and supplies
TP4056 Lithium Battery Charger Board Micro USB
Li-Po Rechargeable Battery 600mAh 3.7v (30mm x 50mm x 6mm maximum physical dimensions)
Arduino UNO
2.8 inch TFT Touch LCD screen
Tools and machines
3D printer with a minimum 160mm x 70mm x 30mm build capacity
Project description
Code
Portable Electronic Sudoku Game Code
arduino
Used with latest Arduino IDE
1 // Sudoku Solver By TechKiwiGadgets May 2019 2 3/* 4* V1 - Final Product Version for First Instructables Release based off dev version 101 5* - Solve now includes help test at end of solve to highlight any errors in red 6* - Includes 5th Hard puzzle as a challenge! 7* 8* 9* 10* 11* 12* 13* 14* 15* 16* ARRAY POSITIONS & KEY VARIABLES BELOW ************************************************************* 17// Array with following locations: {0 , 1 , 2 3 4, 5, 6, 7, 8, 9,10,11,12, 13 } 18// Array with following Structure: {Solved, value , X , Y , V1,V2,V3,V4,V5,V6,V7,V8,V9 panel# } 19 20colcoord[9] = { 10, 34, 58, 90, 114, 138, 170, 194, 218 }; 21rowcoord[9] = { 8, 33, 58, 88, 113, 138, 170, 194, 218 }; 22 23int location = 1; 24 25const int sudoku[81][12]; 26 27 */ 28 29#include <Adafruit_GFX.h> // Core graphics library 30#include <Adafruit_TFTLCD.h> // Hardware-specific library 31#include <TouchScreen.h> 32 33 34#define YP A3 // must be an analog pin, use "An" notation! 35#define XM A2 // must be an analog pin, use "An" notation! 36#define YM 9 // can be a digital pin 37#define XP 8 // can be a digital pin 38 39// Revised Touch Callibration numbers 40#define TS_MINX 130 41#define TS_MINY 88 42#define TS_MAXX 915 43//#define TS_MAXY 927 44#define TS_MAXY 880 45 46// For better pressure precision, we need to know the resistance 47// between X+ and X- Use any multimeter to read it 48// For the one we're using, its 300 ohms across the X plate 49TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); 50 51#define LCD_CS A3 52#define LCD_CD A2 53#define LCD_WR A1 54#define LCD_RD A0 55// optional 56#define LCD_RESET A4 57 58// Assign human-readable names to some common 16-bit color values: 59// I had to reverse these colors for my screen 60int BLACK = 0x0000; 61int RED = 0x001F; 62int BLUE = 0xF800; 63int GREEN = 0x07E0; 64int YELLOW = 0x07FF; 65int MAGENTA = 0xF81F; 66int CYAN = 0xFFE0; 67int WHITE = 0xFFFF; 68 69 70Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); 71 72#define BOX 78 // Block to clear screen 73#define BOXSIZE 80 74#define BUTTON 20 75 76boolean debounce = false; // Used to debounce touch screen input 77 78// Array with following Structure: {value , X , Y , Solved } 79 80const byte colcoord[9] = { 10, 34, 58, 90, 114, 138, 170, 194, 218 }; 81const byte rowcoord[9] = { 8, 33, 58, 88, 113, 138, 170, 194, 218 }; 82 83byte location = 1; 84 85byte puzzlenum = 1; // These identifier for 5 puzzles stored in memory 86 87byte sudoku[82][14]; 88 89byte touchlocation = 0; // Used to track the array value that the stylis is closest to in the Sudoku 9x9 framework 90 91int delay1 = 400; // Pause input into screen 92 93byte tempreading = 0; 94 95void setup(void) { 96// Serial.begin(9600); 97// Serial.println(F("Paint!")); 98 99 tft.reset(); 100 101 uint16_t identifier = tft.readID(); 102 identifier=0x9325; 103 104 tft.begin(identifier); 105 tft.setRotation(1); 106 tft.fillScreen(BLACK); 107 108// **** Splash Screen 109 110 111 tft.drawRoundRect(0, 0, 320, 240, 20, BLUE); 112 tft.drawRoundRect(1, 1, 318, 238, 20, BLUE); 113 114 byte g = 70; 115 116 tft.drawCircle(46, g, 25, GREEN); 117 tft.fillCircle(46, g, 20, GREEN); 118 tft.setTextColor(BLACK); tft.setTextSize(3); 119 tft.setCursor(39, g-10); tft.println("S"); 120 121 tft.drawCircle(91, g+30, 25, BLUE); 122 tft.fillCircle(91, g+30, 20, BLUE); 123 tft.setTextColor(BLACK); tft.setTextSize(3); 124 tft.setCursor(84, g+20); tft.println("U"); 125 126 tft.drawCircle(137, g, 25, YELLOW); 127 tft.fillCircle(137, g, 20, YELLOW); 128 tft.setTextColor(BLACK); tft.setTextSize(3); 129 tft.setCursor(130, g-10); tft.println("D"); 130 131 tft.drawCircle(183, g+30, 25, RED); 132 tft.fillCircle(183, g+30, 20, RED); 133 tft.setTextColor(BLACK); tft.setTextSize(3); 134 tft.setCursor(176, g+20); tft.println("O"); 135 136 tft.drawCircle(229, g, 25, GREEN); 137 tft.fillCircle(229, g, 20, GREEN); 138 tft.setTextColor(BLACK); tft.setTextSize(3); 139 tft.setCursor(222, g-10); tft.println("K"); 140 141 tft.drawCircle(274, g+30, 25, YELLOW); 142 tft.fillCircle(274, g+30, 20, YELLOW); 143 tft.setTextColor(BLACK); tft.setTextSize(3); 144 tft.setCursor(267, g+20); tft.println("U"); 145 146 tft.setTextColor(WHITE); tft.setTextSize(2); 147 tft.setCursor(25, 170); tft.println("Play, Create, Solve"); 148 149 tft.setTextColor(GREEN); tft.setTextSize(1); 150 tft.setCursor(25, 200); tft.println("By TechKiwiGadgets 2019"); 151 152 153 154 delay(4000); 155 156 tft.fillScreen(BLACK); 157 158 drawscreen(); // Clearscreen and setup Sudoku matrix 159 resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero and loading in the coordinates for each touch location 160 loadpaneldata(); // Load specifc Panel identification Data into the Array for each of the 81 locations 161 solvealigndata(); // Sanitize test puzzle data with correct data format 162 163// Test Display by showing all values in the puzzle - White are Solved , Blue are others 164 165 tft.setTextSize(2); 166 167 for (byte a = 1; a < 82; a++) { 168 169 //Test solve or set condition 170 if (sudoku[a][1] != 0) { 171 if (sudoku[a][0] != 0) { 172 tft.setTextColor(WHITE); 173 } else { 174 tft.setTextColor(GREEN); // Set this colour if not a genuine set clue 175 } 176 tft.setCursor( sudoku[a][3], sudoku[a][2]); 177 tft.println(sudoku[a][1]); 178 } 179 } 180 181 182drawbuttons(); 183 184 pinMode(13, OUTPUT); 185 186 // testText(); 187 188 189 190 191} 192 193#define MINPRESSURE 5 194#define MAXPRESSURE 1000 195 196 197 198// tft.begin(identifier); 199 200void loop() 201{ 202 203// Read the Touch Screen Locations 204 digitalWrite(13, HIGH); 205 TSPoint p = ts.getPoint(); 206 digitalWrite(13, LOW); 207 208 // if sharing pins, you'll need to fix the directions of the touchscreen pins 209 pinMode(XM, OUTPUT); 210 pinMode(YP, OUTPUT); 211 212 213 // we have some minimum pressure we consider 'valid' 214 // pressure of 0 means no pressing! 215 216 if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { 217 218/* 219 Serial.print("X = "); Serial.print(p.x); 220 Serial.print("\ Y = "); Serial.print(p.y); 221 Serial.print("\ Pressure = "); Serial.println(p.z); 222 223 */ 224 // scale from 0->1023 to tft.width 225 p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240); 226 p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320); // Original Code 227 228 /* 229 Serial.print("X = "); Serial.print(p.x); 230 Serial.print("\ Y = "); Serial.print(p.y); 231 Serial.print("\ Pressure = "); Serial.println(p.z); 232 */ 233 234 // Calculate the position of the screen touch based on the input values of p.x and p.y 235 236 if ((p.x > 0) && (p.x < 27)) { // Coloumn 1 237 238 if ((p.y > 0) && (p.y < 27)) { // Row 1 239 touchlocation = 1; 240 } 241 if ((p.y > 28) && (p.y < 53)) { // Row 2 242 touchlocation = 2; 243 } 244 if ((p.y > 54) && (p.y < 80)) { // Row 3 245 touchlocation = 3; 246 } 247 if ((p.y > 81) && (p.y < 107)) { // Row 4 248 touchlocation = 4; 249 } 250 if ((p.y > 108) && (p.y < 133)) { // Row 5 251 touchlocation = 5; 252 } 253 if ((p.y > 134) && (p.y < 160)) { // Row 6 254 touchlocation = 6; 255 } 256 if ((p.y > 161) && (p.y < 187)) { // Row 7 257 touchlocation = 7; 258 } 259 if ((p.y > 188) && (p.y < 213)) { // Row 8 260 touchlocation = 8; 261 } 262 if ((p.y > 214) && (p.y < 240)) { // Row 9 263 touchlocation = 9; 264 } 265 } else 266 if ((p.x > 28) && (p.x < 53)) { // Coloumn 2 267 268 if ((p.y > 0) && (p.y < 27)) { // Row 1 269 touchlocation = 10; 270 } 271 if ((p.y > 28) && (p.y < 53)) { // Row 2 272 touchlocation = 11; 273 } 274 if ((p.y > 54) && (p.y < 80)) { // Row 3 275 touchlocation = 12; 276 } 277 if ((p.y > 81) && (p.y < 107)) { // Row 4 278 touchlocation = 13; 279 } 280 if ((p.y > 108) && (p.y < 133)) { // Row 5 281 touchlocation = 14; 282 } 283 if ((p.y > 134) && (p.y < 160)) { // Row 6 284 touchlocation = 15; 285 } 286 if ((p.y > 161) && (p.y < 187)) { // Row 7 287 touchlocation = 16; 288 } 289 if ((p.y > 188) && (p.y < 213)) { // Row 8 290 touchlocation = 17; 291 } 292 if ((p.y > 214) && (p.y < 240)) { // Row 9 293 touchlocation = 18; 294 } 295 296 297 298 } else 299 if ((p.x > 54) && (p.x < 80)) { // Coloumn 3 300 301 if ((p.y > 0) && (p.y < 27)) { // Row 1 302 touchlocation = 19; 303 } 304 if ((p.y > 28) && (p.y < 53)) { // Row 2 305 touchlocation = 20; 306 } 307 if ((p.y > 54) && (p.y < 80)) { // Row 3 308 touchlocation = 21; 309 } 310 if ((p.y > 81) && (p.y < 107)) { // Row 4 311 touchlocation = 22; 312 } 313 if ((p.y > 108) && (p.y < 133)) { // Row 5 314 touchlocation = 23; 315 } 316 if ((p.y > 134) && (p.y < 160)) { // Row 6 317 touchlocation = 24; 318 } 319 if ((p.y > 161) && (p.y < 187)) { // Row 7 320 touchlocation = 25; 321 } 322 if ((p.y > 188) && (p.y < 213)) { // Row 8 323 touchlocation = 26; 324 } 325 if ((p.y > 214) && (p.y < 240)) { // Row 9 326 touchlocation = 27; 327 } 328 329 330 } else 331 if ((p.x > 81) && (p.x < 107)) { // Coloumn 4 332 333 if ((p.y > 0) && (p.y < 27)) { // Row 1 334 touchlocation = 28; 335 } 336 if ((p.y > 28) && (p.y < 53)) { // Row 2 337 touchlocation = 29; 338 } 339 if ((p.y > 54) && (p.y < 80)) { // Row 3 340 touchlocation = 30; 341 } 342 if ((p.y > 81) && (p.y < 107)) { // Row 4 343 touchlocation = 31; 344 } 345 if ((p.y > 108) && (p.y < 133)) { // Row 5 346 touchlocation = 32; 347 } 348 if ((p.y > 134) && (p.y < 160)) { // Row 6 349 touchlocation = 33; 350 } 351 if ((p.y > 161) && (p.y < 187)) { // Row 7 352 touchlocation = 34; 353 } 354 if ((p.y > 188) && (p.y < 213)) { // Row 8 355 touchlocation = 35; 356 } 357 if ((p.y > 214) && (p.y < 240)) { // Row 9 358 touchlocation = 36; 359 } 360 361 } else 362 if ((p.x > 108) && (p.x < 133)) { // Coloumn 5 363 364 if ((p.y > 0) && (p.y < 27)) { // Row 1 365 touchlocation = 37; 366 } 367 if ((p.y > 28) && (p.y < 53)) { // Row 2 368 touchlocation = 38; 369 } 370 if ((p.y > 54) && (p.y < 80)) { // Row 3 371 touchlocation = 39; 372 } 373 if ((p.y > 81) && (p.y < 107)) { // Row 4 374 touchlocation = 40; 375 } 376 if ((p.y > 108) && (p.y < 133)) { // Row 5 377 touchlocation = 41; 378 } 379 if ((p.y > 134) && (p.y < 160)) { // Row 6 380 touchlocation = 42; 381 } 382 if ((p.y > 161) && (p.y < 187)) { // Row 7 383 touchlocation = 43; 384 } 385 if ((p.y > 188) && (p.y < 213)) { // Row 8 386 touchlocation = 44; 387 } 388 if ((p.y > 214) && (p.y < 240)) { // Row 9 389 touchlocation = 45; 390 } 391 392 } else 393 if ((p.x > 134) && (p.x < 160)) { // Coloumn 6 394 395 if ((p.y > 0) && (p.y < 27)) { // Row 1 396 touchlocation = 46; 397 } 398 if ((p.y > 28) && (p.y < 53)) { // Row 2 399 touchlocation = 47; 400 } 401 if ((p.y > 54) && (p.y < 80)) { // Row 3 402 touchlocation = 48; 403 } 404 if ((p.y > 81) && (p.y < 107)) { // Row 4 405 touchlocation = 49; 406 } 407 if ((p.y > 108) && (p.y < 133)) { // Row 5 408 touchlocation = 50; 409 } 410 if ((p.y > 134) && (p.y < 160)) { // Row 6 411 touchlocation = 51; 412 } 413 if ((p.y > 161) && (p.y < 187)) { // Row 7 414 touchlocation = 52; 415 } 416 if ((p.y > 188) && (p.y < 213)) { // Row 8 417 touchlocation = 53; 418 } 419 if ((p.y > 214) && (p.y < 240)) { // Row 9 420 touchlocation = 54; 421 } 422 423 424 425 } else 426 if ((p.x > 161) && (p.x < 187)) { // Coloumn 7 427 428 if ((p.y > 0) && (p.y < 27)) { // Row 1 429 touchlocation = 55; 430 } 431 if ((p.y > 28) && (p.y < 53)) { // Row 2 432 touchlocation = 56; 433 } 434 if ((p.y > 54) && (p.y < 80)) { // Row 3 435 touchlocation = 57; 436 } 437 if ((p.y > 81) && (p.y < 107)) { // Row 4 438 touchlocation = 58; 439 } 440 if ((p.y > 108) && (p.y < 133)) { // Row 5 441 touchlocation = 59; 442 } 443 if ((p.y > 134) && (p.y < 160)) { // Row 6 444 touchlocation = 60; 445 } 446 if ((p.y > 161) && (p.y < 187)) { // Row 7 447 touchlocation = 61; 448 } 449 if ((p.y > 188) && (p.y < 213)) { // Row 8 450 touchlocation = 62; 451 } 452 if ((p.y > 214) && (p.y < 240)) { // Row 9 453 touchlocation = 63; 454 } 455 456 457 } else 458 if ((p.x > 188) && (p.x < 213)) { // Coloumn 8 459 460 if ((p.y > 0) && (p.y < 27)) { // Row 1 461 touchlocation = 64; 462 } 463 if ((p.y > 28) && (p.y < 53)) { // Row 2 464 touchlocation = 65; 465 } 466 if ((p.y > 54) && (p.y < 80)) { // Row 3 467 touchlocation = 66; 468 } 469 if ((p.y > 81) && (p.y < 107)) { // Row 4 470 touchlocation = 67; 471 } 472 if ((p.y > 108) && (p.y < 133)) { // Row 5 473 touchlocation = 68; 474 } 475 if ((p.y > 134) && (p.y < 160)) { // Row 6 476 touchlocation = 69; 477 } 478 if ((p.y > 161) && (p.y < 187)) { // Row 7 479 touchlocation = 70; 480 } 481 if ((p.y > 188) && (p.y < 213)) { // Row 8 482 touchlocation = 71; 483 } 484 if ((p.y > 214) && (p.y < 240)) { // Row 9 485 touchlocation = 72; 486 } 487 } else 488 if ((p.x > 214) && (p.x < 240)) { // Coloumn 9 489 490 if ((p.y > 0) && (p.y < 27)) { // Row 1 491 touchlocation = 73; 492 } 493 if ((p.y > 28) && (p.y < 53)) { // Row 2 494 touchlocation = 74; 495 } 496 if ((p.y > 54) && (p.y < 80)) { // Row 3 497 touchlocation = 75; 498 } 499 if ((p.y > 81) && (p.y < 107)) { // Row 4 500 touchlocation = 76; 501 } 502 if ((p.y > 108) && (p.y < 133)) { // Row 5 503 touchlocation = 77; 504 } 505 if ((p.y > 134) && (p.y < 160)) { // Row 6 506 touchlocation = 78; 507 } 508 if ((p.y > 161) && (p.y < 187)) { // Row 7 509 touchlocation = 79; 510 } 511 if ((p.y > 188) && (p.y < 213)) { // Row 8 512 touchlocation = 80; 513 } 514 if ((p.y > 214) && (p.y < 240)) { // Row 9 515 touchlocation = 81; 516 } 517 518 } 519 520 // debounce function to remove issue with first touch screen reading being spurious 521 if (debounce == false) { 522 touchlocation = 0; 523 debounce = true; 524 } 525 526// This code only applies to stylis activity within the Sudokumatrix 527if ( ((p.x < 235)&&(p.y < 230))&& (touchlocation != 0)) { 528 529 530 531 // tft.fillRect(250, 80, 15, 10, BLACK); 532 533/* 534 Serial.print("Y = "); Serial.print(p.x); 535 Serial.print("\ X = "); Serial.print(p.y); 536 Serial.print("\ Location = "); Serial.println(touchlocation); 537*/ 538 539// Calculate the incremental changes to the data array 540// Array Structure: {value , X , Y , Solved } 541 542// Only increment if has not been solved, Debounce by checking if this is the second time the same range is selected 543 if ((tempreading == touchlocation)&&(sudoku[touchlocation][0]==0)||(tempreading == touchlocation)&&(sudoku[touchlocation][0]==2)) { 544 sudoku[touchlocation][1]++; 545 if (sudoku[touchlocation][1] > 9) { 546 sudoku[touchlocation][1] = 0; 547 } 548 // Test to see if changing an item can be classified as solved 549 if (sudoku[touchlocation][1]!=0) { 550 sudoku[touchlocation][0]=2; // Set to Solved if a manually changed number however flag as manual change with va,ue of 2 551 } else { 552 sudoku[touchlocation][0]=0; // Set to Not Solved if 0 553 } 554 // Finally reset all of the data values in this location that have been manually changed to unsolved 555 for (byte u = 1; u < 82; u++) { 556 // If preprogrammed from a game then leave values otherwise reset data to baseline 557 if (sudoku[u][0]!=1){ 558 for (byte q = 4; q < 13; q++) { 559 sudoku[u][q]=q-3; 560 } 561 } 562 } 563 } 564 565// tft.setTextColor(WHITE); tft.setTextSize(1); 566// tft.setCursor(250, 80); tft.println(touchlocation); 567 568 569 570 // Refresh only the location concerned with new value and show colour coded 571 //First Clear Location 572 tft.fillRect(sudoku[touchlocation][3], sudoku[touchlocation][2], 15, 15, BLACK); 573 tft.setTextSize(2); 574 575 if (sudoku[touchlocation][0] != 0) { // Do not draw 0 just leave blank square 576 if (sudoku[touchlocation][0] == 1) { 577 tft.setTextColor(WHITE); 578 } else if (sudoku[touchlocation][0] == 2) { 579 tft.setTextColor(GREEN); // Set this colour if not a genuine set clue 580 } 581 tft.setCursor( sudoku[touchlocation][3], sudoku[touchlocation][2]); 582 tft.println(sudoku[touchlocation][1]); 583 } 584 585 if (tempreading == touchlocation) { 586 delay(delay1); 587 } 588 589 590 tempreading = touchlocation; // take a first sample then repeat and compare to debounce 591 592 593 } 594 595 // Inside touch sensor reading if statement 596 597 // HOME Button Pressed ************************************************ 598 if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 10)&&(p.x < 40))) { 599 600 601 tft.fillCircle(280, 30, 20, WHITE); 602 tft.setTextColor(BLACK); tft.setTextSize(1); 603 tft.setCursor(268, 27); tft.println("HOME"); 604 605 delay(delay1/2); 606 607 drawscreen(); // Clearscreen and setup Sudoku matrix 608 resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero: 609 refreshdisplay(); 610 drawbuttons(); 611 } 612 613 // PLAY Button Pressed ************************************************ 614 if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 80)&&(p.x < 110))) { 615 616 617 //PLAY Button pressed 618 //Button 2 619 tft.fillCircle(280, 90, 20, WHITE); 620 tft.setTextColor(BLACK); tft.setTextSize(1); 621 tft.setCursor(268, 87); tft.println("PLAY"); 622 623 624 625 delay(delay1/2); 626 627 drawscreen(); // Clearscreen and setup Sudoku matrix 628 resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero: 629 630 loadtestpuzzle1(); // Loads test puzzle into the location array 631 632 633 634 solvealigndata(); // Sanitize test puzzle data with correct data format 635 636 637 refreshdisplay(); // Only display testpuzzle data locations that are 638 drawbuttons(); // Redraw buttons togive push button effect 639 tft.setCursor(277, 97); tft.println(puzzlenum); 640 641 // Manage Puzzle Number 642 puzzlenum++; // increment puzzle number 643 if (puzzlenum > 5) { 644 puzzlenum = 1; 645 } 646 647 } 648 649 // HELP Button Pressed ************************************************ 650 if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 140)&&(p.x < 160))) { 651 652 //Button 3 653 tft.fillCircle(280, 150, 20, WHITE); 654 tft.setTextColor(BLACK); tft.setTextSize(1); 655 tft.setCursor(268, 147); tft.println("HELP"); 656 657 658 659 delay(delay1/2); 660 661 // drawscreen(); // Clearscreen and setup Sudoku matrix 662 // solvehorizontal(); // Solve horiontal rule 663 // solvevertical(); // Solve vertical rule 664 // solvepanel(); // Solve Panel rule 665 666 helpbutton(); // Run algorythm and test for incorrect locations then highlight in red 667 668 // reversesolve(); 669 delay(800);// Display the changes before reverting to original colors 670 671 672 refreshdisplay(); // Only display testpuzzle data locations that are 673 drawbuttons(); // Redraw buttons togive push button effect 674 } 675 676 // SOLVE Button Pressed ************************************************ 677 if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 200)&&(p.x < 220))) { 678 679 680 //SOLVE Button Pressed 681 682 //Button 4 683 tft.fillCircle(280, 210, 20, WHITE); 684 tft.setTextColor(BLACK); tft.setTextSize(1); 685 tft.setCursor(266, 207); tft.println("SOLVE"); 686 687 688 689 delay(delay1/2); 690 691 692 solvepanel(); // Solve Panel rule 693 solvehorizontal(); // Solve horiontal rule 694 solvevertical(); // Solve vertical rule 695 696 reversesolvecolor(); 697 698 699 uniquecandidate(); // Test 700 solvealigndata(); 701 reversesolvecolor(); 702 703 704 solvehorizontal(); // Solve horiontal rule 705 solvevertical(); // Solve vertical rule 706 solvepanel(); // Solve Panel rule 707 reversesolvecolor(); 708 709 solvehorizontal(); // Solve horiontal rule 710 solvevertical(); // Solve vertical rule 711 solvepanel(); // Solve Panel rule 712 reversesolvecolor(); 713 714 715 solvehorizontal(); // Solve horiontal rule 716 solvevertical(); // Solve vertical rule 717 solvepanel(); // Solve Panel rule 718 reversesolvecolor(); 719 720 721 solvehorizontal(); // Solve horiontal rule 722 solvevertical(); // Solve vertical rule 723 solvepanel(); // Solve Panel rule 724 reversesolvecolor(); 725 726 727 solvehorizontal(); // Solve horiontal rule 728 solvevertical(); // Solve vertical rule 729 solvepanel(); // Solve Panel rule 730 reversesolvecolor(); 731 732 733 solvehorizontal(); // Solve horiontal rule 734 solvevertical(); // Solve vertical rule 735 solvepanel(); // Solve Panel rule 736 reversesolvecolor(); 737 738 739 solvehorizontal(); // Solve horiontal rule 740 solvevertical(); // Solve vertical rule 741 solvepanel(); // Solve Panel rule 742 reversesolvecolor(); 743 744 745 solvehorizontal(); // Solve horiontal rule 746 solvevertical(); // Solve vertical rule 747 solvepanel(); // Solve Panel rule 748 reversesolvecolor(); 749 750 751 solvehorizontal(); // Solve horiontal rule 752 solvevertical(); // Solve vertical rule 753 solvepanel(); // Solve Panel rule 754 reversesolvecolor(); 755 756 757 solvehorizontal(); // Solve horiontal rule 758 solvevertical(); // Solve vertical rule 759 solvepanel(); // Solve Panel rule 760 reversesolvecolor(); 761 762 solvepanel(); // Solve Panel rule 763 solvehorizontal(); // Solve horiontal rule 764 solvevertical(); // Solve vertical rule 765 766 reversesolvecolor(); 767 768 uniquecandidate(); // Test 769 solvealigndata(); 770 reversesolvecolor(); 771 772 solvepanel(); // Solve Panel rule 773 solvehorizontal(); // Solve horiontal rule 774 solvevertical(); // Solve vertical rule 775 776 reversesolvecolor(); 777 778 uniquecandidate(); // Test 779 solvealigndata(); 780 reversesolvecolor(); 781 782 solvepanel(); // Solve Panel rule 783 solvehorizontal(); // Solve horiontal rule 784 solvevertical(); // Solve vertical rule 785 786 reversesolvecolor(); 787 788 uniquecandidate(); // Test 789 solvealigndata(); 790 reversesolvecolor(); 791 792 793 794 drawscreen(); // Clearscreen and setup Sudoku matrix 795 796 refreshdisplay(); // Only display testpuzzle data locations that are 797 helpbutton(); // Run algorythm and test for incorrect locations then highlight in red 798 drawbuttons(); // Redraw buttons togive push button effect 799 } 800 801 802 803/* 804 Serial.print("Y = "); Serial.print(p.x); 805 Serial.print("\ X = "); Serial.println(p.y); 806*/ 807 p.z = 0;// Force the sensor value below threshold to avoid ghost values 808 } 809 810} 811 812 813 814 815 816 817 818 819 820 821 822void loadtestpuzzle1(){ 823 824// Test Puzzle example 1 loaded into array 825 826 if (puzzlenum == 1 ){ 827 828 // Load Numbers 829 sudoku[1][1] = 2; sudoku[3][1] = 9; sudoku[19][1] = 3; sudoku[21][1] = 5; 830 831 sudoku[5][1] = 6; sudoku[6][1] = 3; sudoku[14][1] = 2; sudoku[23][1] = 9; 832 833 sudoku[7][1] = 4; sudoku[9][1] = 8; sudoku[26][1] = 7; 834 835 sudoku[39][1] = 1; sudoku[46][1] = 9; sudoku[47][1] = 7; sudoku[48][1] = 2; 836 837 sudoku[31][1] = 9; sudoku[32][1] = 8; sudoku[50][1] = 1; sudoku[51][1] = 6; 838 839 sudoku[34][1] = 7; sudoku[35][1] = 1; sudoku[36][1] = 6; sudoku[43][1] = 2; 840 841 sudoku[56][1] = 3; sudoku[73][1] = 5; sudoku[75][1] = 6; 842 843 sudoku[59][1] = 7; sudoku[68][1] = 3; sudoku[76][1] = 1; sudoku[77][1] = 4; 844 845 sudoku[61][1] = 6; sudoku[63][1] = 1; sudoku[79][1] = 8; sudoku[81][1] = 7; 846 847 // Set the Solved Flag for each 848 sudoku[1][0] = 1; sudoku[3][0] = 1; sudoku[19][0] = 1; sudoku[21][0] = 1; 849 850 sudoku[5][0] = 1; sudoku[6][0] = 1; sudoku[14][0] = 1; sudoku[23][0] = 1; 851 852 sudoku[7][0] = 1; sudoku[9][0] = 1; sudoku[26][0] = 1; 853 854 sudoku[39][0] = 1; sudoku[46][0] = 1; sudoku[47][0] = 1; sudoku[48][0] = 1; 855 856 sudoku[31][0] = 1; sudoku[32][0] = 1; sudoku[50][0] = 1; sudoku[51][0] = 1; 857 858 sudoku[34][0] = 1; sudoku[35][0] = 1; sudoku[36][0] = 1; sudoku[43][0] = 1; 859 860 sudoku[56][0] = 1; sudoku[73][0] = 1; sudoku[75][0] = 1; 861 862 sudoku[59][0] = 1; sudoku[68][0] = 1; sudoku[76][0] = 1; sudoku[77][0] = 1; 863 864 sudoku[61][0] = 1; sudoku[63][0] = 1; sudoku[79][0] = 1; sudoku[81][0] = 1; 865 866 } else 867 868 if (puzzlenum == 2 ){ 869 870 // Load Numbers 871 sudoku[1][1] = 4; sudoku[10][1] = 2; sudoku[19][1] = 1; 872 873 sudoku[5][1] = 2; sudoku[15][1] = 4; sudoku[24][1] = 5; 874 875 sudoku[25][1] = 2; sudoku[17][1] = 8; sudoku[18][1] = 6; 876 877 878 sudoku[29][1] = 3; sudoku[30][1] = 2; sudoku[37][1] = 9; sudoku[39][1] = 5; sudoku[46][1] = 7; sudoku[47][1] = 6; 879 880 sudoku[31][1] = 6; sudoku[40][1] = 4; sudoku[41][1] = 8; sudoku[42][1] = 3; sudoku[51][1] = 2; 881 882 sudoku[35][1] = 4; sudoku[36][1] = 1; sudoku[43][1] = 6; sudoku[45][1] = 2; sudoku[52][1] = 3; sudoku[53][1] = 5; 883 884 885 sudoku[57][1] = 1; sudoku[64][1] = 3; sudoku[65][1] = 8; 886 887 sudoku[58][1] = 7; sudoku[67][1] = 5; sudoku[77][1] = 9; 888 889 sudoku[63][1] = 9; sudoku[72][1] = 7; sudoku[81][1] = 5; 890 891 892 // Set the Solved Flag for each 893 sudoku[1][0] = 1; sudoku[10][0] = 1; sudoku[19][0] = 1; 894 895 sudoku[5][0] = 1; sudoku[15][0] = 1; sudoku[24][0] = 1; 896 897 sudoku[25][0] = 1; sudoku[17][0] = 1; sudoku[18][0] = 1; 898 899 900 sudoku[29][0] = 1; sudoku[30][0] = 1; sudoku[37][0] = 1; sudoku[39][0] = 1; sudoku[46][0] = 1; sudoku[47][0] = 1; 901 902 sudoku[31][0] = 1; sudoku[40][0] = 1; sudoku[41][0] = 1; sudoku[42][0] = 1; sudoku[51][0] = 1; 903 904 sudoku[35][0] = 1; sudoku[36][0] = 1; sudoku[43][0] = 1; sudoku[45][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1; 905 906 907 sudoku[57][0] = 1; sudoku[64][0] = 1; sudoku[65][0] = 1; 908 909 sudoku[58][0] = 1; sudoku[67][0] = 1; sudoku[77][0] = 1; 910 911 sudoku[63][0] = 1; sudoku[72][0] = 1; sudoku[81][0] = 1; 912 913 } else 914 915 if (puzzlenum == 3 ){ 916 917 // Load Numbers 918 sudoku[12][1] = 8; sudoku[19][1] = 4; 919 920 sudoku[5][1] = 2; sudoku[13][1] = 9; sudoku[14][1] = 4; sudoku[22][1] = 7; sudoku[24][1] = 8; 921 922 sudoku[7][1] = 8; sudoku[9][1] = 7; sudoku[25][1] = 2; sudoku[27][1] = 9; 923 924 925 sudoku[28][1] = 1; sudoku[29][1] = 2; sudoku[38][1] = 4; sudoku[39][1] = 3; sudoku[30][1] = 7; 926 927 sudoku[31][1] = 5; sudoku[41][1] = 8; sudoku[51][1] = 7; 928 929 sudoku[43][1] = 5; sudoku[44][1] = 7; sudoku[52][1] = 9; sudoku[53][1] = 2; sudoku[54][1] = 4; 930 931 932 sudoku[55][1] = 8; sudoku[57][1] = 9; sudoku[73][1] = 6; sudoku[75][1] = 4; 933 934 sudoku[58][1] = 1; sudoku[60][1] = 2; sudoku[68][1] = 6; sudoku[69][1] = 9; sudoku[77][1] = 3; 935 936 sudoku[70][1] = 1; sudoku[63][1] = 3; 937 938 939 // Set the Solved Flag for each 940 sudoku[12][0] = 1; sudoku[19][0] = 1; 941 942 sudoku[5][0] = 1; sudoku[13][0] = 1; sudoku[14][0] = 1; sudoku[22][0] = 1; sudoku[24][0] = 1; 943 944 sudoku[7][0] = 1; sudoku[9][0] = 1; sudoku[25][0] = 1; sudoku[27][0] = 1; 945 946 947 sudoku[28][0] = 1; sudoku[29][0] = 1; sudoku[38][0] = 1; sudoku[39][0] = 1; sudoku[30][0] = 1; 948 949 sudoku[31][0] = 1; sudoku[41][0] = 1; sudoku[51][0] = 1; 950 951 sudoku[43][0] = 1; sudoku[44][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1; sudoku[54][0] = 1; 952 953 954 sudoku[55][0] = 1; sudoku[57][0] = 1; sudoku[73][0] = 1; sudoku[75][0] = 1; 955 956 sudoku[58][0] = 1; sudoku[60][0] = 1; sudoku[68][0] = 1; sudoku[69][0] = 1; sudoku[77][0] = 1; 957 958 sudoku[70][0] = 1; sudoku[63][0] = 1; 959 960 } else 961 962 if (puzzlenum == 4 ){ 963 964 // Load Numbers 965 sudoku[3][1] = 6; sudoku[12][1] = 2; 966 967 sudoku[5][1] = 7; sudoku[6][1] = 9; sudoku[13][1] = 1; 968 969 sudoku[16][1] = 6; sudoku[17][1] = 5; sudoku[18][1] = 4; sudoku[25][1] = 7; sudoku[26][1] = 1; 970 971 972 sudoku[29][1] = 6; sudoku[30][1] = 5; sudoku[37][1] = 8; sudoku[46][1] = 1; sudoku[48][1] = 3; 973 974 sudoku[33][1] = 4; sudoku[40][1] = 7; sudoku[41][1] = 2; sudoku[42][1] = 5; sudoku[49][1] = 8; 975 976 sudoku[34][1] = 9; sudoku[36][1] = 8; sudoku[45][1] = 3; sudoku[52][1] = 4; sudoku[53][1] = 7; 977 978 979 sudoku[56][1] = 3; sudoku[57][1] = 7; sudoku[64][1] = 6; sudoku[65][1] = 4;sudoku[66][1] = 1; 980 981 sudoku[76][1] = 6; sudoku[77][1] = 4; sudoku[69][1] = 3; 982 983 sudoku[70][1] = 8; sudoku[79][1] = 5; 984 985 986 // Set the Solved Flag for each 987 sudoku[3][0] = 1; sudoku[12][0] = 1; 988 989 sudoku[5][0] = 1; sudoku[6][0] = 1; sudoku[13][0] = 1; 990 991 sudoku[16][0] = 1; sudoku[17][0] = 1; sudoku[18][0] = 1; sudoku[25][0] = 1; sudoku[26][0] = 1; 992 993 994 sudoku[29][0] = 1; sudoku[30][0] = 1; sudoku[37][0] = 1; sudoku[46][0] = 1; sudoku[48][0] = 1; 995 996 sudoku[33][0] = 1; sudoku[40][0] = 1; sudoku[41][0] = 1; sudoku[42][0] = 1; sudoku[49][0] = 1; 997 998 sudoku[34][0] = 1; sudoku[36][0] = 1; sudoku[45][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1; 999 1000 1001 sudoku[56][0] = 1; sudoku[57][0] = 1; sudoku[64][0] = 1; sudoku[65][0] = 1;sudoku[66][0] = 1; 1002 1003 sudoku[76][0] = 1; sudoku[77][0] = 1; sudoku[69][0] = 1; 1004 1005 sudoku[70][0] = 1; sudoku[79][0] = 1; 1006 1007 } else 1008 1009 if (puzzlenum == 5 ){ 1010 1011 // Load Numbers 1012 sudoku[2][1] = 3; sudoku[3][1] = 2; sudoku[12][1] = 6; sudoku[21][1] = 9; 1013 1014 sudoku[4][1] = 9; sudoku[5][1] = 8; sudoku[22][1] = 2; 1015 1016 sudoku[17][1] = 3; sudoku[27][1] = 7; 1017 1018 1019 sudoku[30][1] = 7; sudoku[47][1] = 9; 1020 1021 sudoku[31][1] = 1; sudoku[40][1] = 3; sudoku[42][1] = 5; sudoku[51][1] = 4; 1022 1023 sudoku[35][1] = 5; sudoku[52][1] = 6; 1024 1025 1026 sudoku[55][1] = 2; sudoku[65][1] = 6; 1027 1028 sudoku[60][1] = 9; sudoku[77][1] = 5; sudoku[78][1] = 3; 1029 1030 sudoku[61][1] = 3; sudoku[70][1] = 7; sudoku[79][1] = 2; sudoku[80][1] = 6; 1031 1032 1033 // Set the Solved Flag for each 1034 sudoku[2][0] = 1; sudoku[3][0] = 1; sudoku[12][0] = 1; sudoku[21][0] = 1; 1035 1036 sudoku[4][0] = 1; sudoku[5][0] = 1; sudoku[22][0] = 1; 1037 1038 sudoku[17][0] = 1; sudoku[27][0] = 1; 1039 1040 1041 sudoku[30][0] = 1; sudoku[47][0] = 1; 1042 1043 sudoku[31][0] = 1; sudoku[40][0] = 1; sudoku[42][0] = 1; sudoku[51][0] = 1; 1044 1045 sudoku[35][0] = 1; sudoku[52][0] = 1; 1046 1047 1048 sudoku[55][0] = 1; sudoku[65][0] = 1; 1049 1050 sudoku[60][0] = 1; sudoku[77][0] = 1; sudoku[78][0] = 1; 1051 1052 sudoku[61][0] = 1; sudoku[70][0] = 1; sudoku[79][0] = 1; sudoku[80][0] = 1; 1053 1054 } 1055 1056} 1057 1058 1059void refreshdisplay() { //Refresh the display once a value has changed 1060 1061 tft.setTextSize(2); 1062 1063 for (byte a = 1; a < 82; a++) { 1064 1065 //Test solve or set condition 1066 if (sudoku[a][1] != 0) { 1067 1068 //First Clear Location 1069 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1070 1071 if (sudoku[a][0] != 0) { // Do not draw 0 just leave blank square 1072 if (sudoku[a][0] == 1) { 1073 tft.setTextColor(WHITE); 1074 } else if (sudoku[a][0] == 2) { 1075 tft.setTextColor(GREEN); // Set this colour if not a genuine set clue 1076 } 1077 tft.setCursor( sudoku[a][3], sudoku[a][2]); 1078 tft.println(sudoku[a][1]); 1079 } 1080 1081 1082 1083 } 1084 } 1085 1086} 1087 1088 1089void drawscreen(){ 1090 1091// tft.fillScreen(BLACK); 1092 1093// Setup Screen 1094 1095GREEN = 0x07E0; 1096 1097 1098 tft.fillRect(1, 1, 239, 239, BLACK); 1099 1100 tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); 1101 tft.drawRect(0+BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); 1102 tft.drawRect(0+BOXSIZE+BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); 1103 1104 tft.drawRect(0, BOXSIZE, BOXSIZE, BOXSIZE, WHITE); 1105 tft.drawRect(0+BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE); 1106 tft.drawRect(0+BOXSIZE+BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE); 1107 1108 tft.drawRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE); 1109 tft.drawRect(0+BOXSIZE, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE); 1110 tft.drawRect(0+BOXSIZE+BOXSIZE, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE); 1111 1112} 1113 1114 1115void resetmatrix(){ // Initialize the sudoku matrix by setting all locations to zero and loading in the coordinates for each touch location 1116byte hole = 1; 1117 for (byte a = 0; a < 9; a++) { 1118 for (byte b = 0; b < 9; b++) { 1119 sudoku[hole][0] = 0; // Solve Flag 1120 sudoku[hole][1] = 0; // Display Value 1121 sudoku[hole][2] = colcoord[a]; // Matrix Column coordinate 1122 sudoku[hole][3] = rowcoord[b]; // Matrix Row coordinate 1123 sudoku[hole][4] = 1; // V1 1124 sudoku[hole][5] = 2; // V2 1125 sudoku[hole][6] = 3; // V3 1126 sudoku[hole][7] = 4; // V4 1127 sudoku[hole][8] = 5; // V5 1128 sudoku[hole][9] = 6; // V6 1129 sudoku[hole][10] = 7; // V7 1130 sudoku[hole][11] = 8; // V8 1131 sudoku[hole][12] = 9; // V9 1132 hole++; 1133 } 1134 } 1135} 1136 1137 1138void drawbuttons() { 1139 // Setup Buttons 1140 GREEN = 0x07E0; 1141 1142 //Button 1 1143 tft.drawCircle(280, 30, 24, GREEN); 1144 tft.fillCircle(280, 30, 20, GREEN); 1145 tft.setTextColor(BLACK); tft.setTextSize(1); 1146 tft.setCursor(268, 27); tft.println("HOME"); 1147 1148 //Button 2 1149 tft.drawCircle(280, 90, 24, YELLOW); 1150 tft.fillCircle(280, 90, 20, YELLOW); 1151 tft.setTextColor(BLACK); tft.setTextSize(1); 1152 tft.setCursor(268, 87); tft.println("PLAY"); 1153 1154 //Button 3 1155 tft.drawCircle(280, 150, 24, MAGENTA); 1156 tft.fillCircle(280, 150, 20, MAGENTA); 1157 tft.setTextColor(BLACK); tft.setTextSize(1); 1158 tft.setCursor(268, 147); tft.println("HELP"); 1159 1160 1161 //Button 4 1162 tft.drawCircle(280, 210, 24, BLUE); 1163 tft.fillCircle(280, 210, 20, BLUE); 1164 tft.setTextColor(BLACK); tft.setTextSize(1); 1165 tft.setCursor(266, 207); tft.println("SOLVE"); 1166 1167 1168 1169 1170} 1171 1172void solvealigndata(){ // Once a location is marked as solved then all data in that location nees to be set to Zero 1173 1174 for (byte a = 1; a < 82; a++) { // Cycle through all locations 1175 1176 if (sudoku[a][0] > 0) { // If location solved then zero out all data in array except correct value 1177 1178 /* 1179 Serial.print(a); Serial.print(" "); 1180 1181 Serial.print(sudoku[a][1]); Serial.print(" "); 1182 1183 Serial.print(3+sudoku[a][1]); Serial.print(" "); 1184 1185 Serial.print(sudoku[a][4]); 1186 1187 Serial.print(sudoku[a][5]); 1188 1189 Serial.print(sudoku[a][6]); 1190 1191 Serial.print(sudoku[a][7]); 1192 1193 Serial.print(sudoku[a][8]); 1194 1195 Serial.print(sudoku[a][9]); 1196 1197 Serial.print(sudoku[a][10]); 1198 1199 Serial.print(sudoku[a][11]); 1200 1201 Serial.println(sudoku[a][12]); 1202 1203 */ 1204 1205 sudoku[a][4] = 0; // V1 1206 sudoku[a][5] = 0; // V2 1207 sudoku[a][6] = 0; // V3 1208 sudoku[a][7] = 0; // V4 1209 sudoku[a][8] = 0; // V5 1210 sudoku[a][9] = 0; // V6 1211 sudoku[a][10] = 0; // V7 1212 sudoku[a][11] = 0; // V8 1213 sudoku[a][12] = 0; // V9 1214 1215 // Now poke the answer into the correct location 1216 sudoku[a][(sudoku[a][1]+3)] = sudoku[a][1]; // Load the solved value into the array 1217 1218 /* 1219 Serial.print(a); Serial.print(" "); 1220 1221 Serial.print(sudoku[a][1]); Serial.print(" "); 1222 1223 Serial.print(3+sudoku[a][1]); Serial.print(" "); 1224 1225 Serial.print(sudoku[a][4]); 1226 1227 Serial.print(sudoku[a][5]); 1228 1229 Serial.print(sudoku[a][6]); 1230 1231 Serial.print(sudoku[a][7]); 1232 1233 Serial.print(sudoku[a][8]); 1234 1235 Serial.print(sudoku[a][9]); 1236 1237 Serial.print(sudoku[a][10]); 1238 1239 Serial.print(sudoku[a][11]); 1240 1241 Serial.println(sudoku[a][12]); 1242 1243*/ 1244 1245 1246 } 1247 } 1248 1249 1250} 1251 1252void reversesolve(){ // subroutine to reverse engineer solved locations in the matrix and label themas solved 1253byte tempcount = 0; 1254 for (byte a = 1; a < 82; a++) { // Cycle through all locations 1255 1256/* 1257 Serial.print(a); Serial.print(" "); 1258 1259 Serial.print(sudoku[a][0]); Serial.print(" "); 1260 1261// Serial.print(3+sudoku[a][1]); Serial.print(" "); 1262 1263 Serial.print(sudoku[a][4]); 1264 1265 Serial.print(sudoku[a][5]); 1266 1267 Serial.print(sudoku[a][6]); 1268 1269 Serial.print(sudoku[a][7]); 1270 1271 Serial.print(sudoku[a][8]); 1272 1273 Serial.print(sudoku[a][9]); 1274 1275 Serial.print(sudoku[a][10]); 1276 1277 Serial.print(sudoku[a][11]); 1278 1279 Serial.println(sudoku[a][12]); 1280 1281 */ 1282 1283 if (sudoku[a][0] == 0) { // Ignore location if already solved 1284 1285 // Read each and count the number that have been elimated 1286 tempcount = 0; 1287 for (byte b = 4; b < 13; b++) { 1288 if (sudoku[a][b] == 0) {// If equal to 0 then count 1289 tempcount++; 1290 } 1291 } 1292 1293 if (tempcount == 8){ // If only one valid result then find again then mark location as solved 1294 for (byte c = 4; c < 13; c++) { // Read each and identify the only solution 1295 if (sudoku[a][c] > 0) { 1296 sudoku[a][0] = 1; // Set Solved Location Flag 1297 sudoku[a][1] = sudoku[a][c]; // Set value 1298 } 1299 } 1300 } 1301 } 1302 1303/* 1304 Serial.print(a); Serial.print(" "); 1305 1306 Serial.print(sudoku[a][0]); Serial.print(" "); 1307 1308 Serial.print(tempcount); Serial.print(" "); 1309 1310 Serial.print(sudoku[a][4]); 1311 1312 Serial.print(sudoku[a][5]); 1313 1314 Serial.print(sudoku[a][6]); 1315 1316 Serial.print(sudoku[a][7]); 1317 1318 Serial.print(sudoku[a][8]); 1319 1320 Serial.print(sudoku[a][9]); 1321 1322 Serial.print(sudoku[a][10]); 1323 1324 Serial.print(sudoku[a][11]); 1325 1326 Serial.println(sudoku[a][12]); 1327 1328*/ 1329 } 1330} 1331 1332void reversesolvecolor(){ // subroutine to reverse engineer solved locations in the matrix and label themas solved 1333byte tempcount = 0; 1334 for (byte a = 1; a < 82; a++) { // Cycle through all locations 1335 1336/* 1337 Serial.print(a); Serial.print(" "); 1338 1339 Serial.print(sudoku[a][0]); Serial.print(" "); 1340 1341// Serial.print(3+sudoku[a][1]); Serial.print(" "); 1342 1343 Serial.print(sudoku[a][4]); 1344 1345 Serial.print(sudoku[a][5]); 1346 1347 Serial.print(sudoku[a][6]); 1348 1349 Serial.print(sudoku[a][7]); 1350 1351 Serial.print(sudoku[a][8]); 1352 1353 Serial.print(sudoku[a][9]); 1354 1355 Serial.print(sudoku[a][10]); 1356 1357 Serial.print(sudoku[a][11]); 1358 1359 Serial.println(sudoku[a][12]); 1360 1361 */ 1362 1363 if (sudoku[a][0] == 0) { // Ignore location if already solved 1364 1365 // Read each and count the number that have been elimated 1366 tempcount = 0; 1367 for (byte b = 4; b < 13; b++) { 1368 if (sudoku[a][b] == 0) {// If equal to 0 then count 1369 tempcount++; 1370 } 1371 } 1372 1373 if (tempcount == 8){ // If only one valid result then find again then mark location as solved 1374 for (byte c = 4; c < 13; c++) { // Read each and identify the only solution 1375 if (sudoku[a][c] > 0) { 1376 sudoku[a][0] = 2; // Set Solved Location Flag 1377 sudoku[a][1] = sudoku[a][c]; // Set value 1378 } 1379 } 1380 } 1381 } 1382 1383/* 1384 Serial.print(a); Serial.print(" "); 1385 1386 Serial.print(sudoku[a][0]); Serial.print(" "); 1387 1388 Serial.print(tempcount); Serial.print(" "); 1389 1390 Serial.print(sudoku[a][4]); 1391 1392 Serial.print(sudoku[a][5]); 1393 1394 Serial.print(sudoku[a][6]); 1395 1396 Serial.print(sudoku[a][7]); 1397 1398 Serial.print(sudoku[a][8]); 1399 1400 Serial.print(sudoku[a][9]); 1401 1402 Serial.print(sudoku[a][10]); 1403 1404 Serial.print(sudoku[a][11]); 1405 1406 Serial.println(sudoku[a][12]); 1407 1408*/ 1409 } 1410} 1411 1412 1413 1414 1415void solvehorizontal(){ // Take Solved locations and apply horizontal rule 1416// Cycle through all locations and using solved flag remove all associate horizontal possibilities 1417 1418 1419/* 1420for (byte d = 1; d < 82; d++) { // Cycle through all locations 1421 Serial.print(d); Serial.print(" "); 1422 1423 Serial.print(sudoku[d][0]); Serial.print(" "); 1424 1425 Serial.print(sudoku[d][4]); 1426 1427 Serial.print(sudoku[d][5]); 1428 1429 Serial.print(sudoku[d][6]); 1430 1431 Serial.print(sudoku[d][7]); 1432 1433 Serial.print(sudoku[d][8]); 1434 1435 Serial.print(sudoku[d][9]); 1436 1437 Serial.print(sudoku[d][10]); 1438 1439 Serial.print(sudoku[d][11]); 1440 1441 Serial.println(sudoku[d][12]); 1442} 1443*/ 1444 // ROW 1 ************************ 1445 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1446 for (byte a = 1; a < 10; a++) { // Cycle through all locations 1447 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1448 for (byte r = 1; r < 10; r++) { 1449 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1450 sudoku[r][sudoku[a][1]+3] = 0; 1451 } 1452 } 1453 } 1454 } 1455 1456 1457 // ROW 2 ************************ 1458 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1459 for (byte a = 10; a < 19; a++) { // Cycle through all locations 1460 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1461 for (byte r = 10; r < 19; r++) { 1462 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1463 sudoku[r][sudoku[a][1]+3] = 0; 1464 } 1465 } 1466 } 1467 } 1468 1469 // ROW 3 ************************ 1470 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1471 for (byte a = 19; a < 28; a++) { // Cycle through all locations 1472 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1473 for (byte r = 19; r < 28; r++) { 1474 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1475 sudoku[r][sudoku[a][1]+3] = 0; 1476 } 1477 } 1478 } 1479 } 1480 1481 1482 // ROW 4 ************************ 1483 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1484 for (byte a = 28; a < 37; a++) { // Cycle through all locations 1485 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1486 for (byte r = 28; r < 37; r++) { 1487 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1488 sudoku[r][sudoku[a][1]+3] = 0; 1489 } 1490 } 1491 } 1492 } 1493 // ROW 5 ************************ 1494 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1495 for (byte a = 37; a < 46; a++) { // Cycle through all locations 1496 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1497 for (byte r = 37; r < 46; r++) { 1498 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1499 sudoku[r][sudoku[a][1]+3] = 0; 1500 } 1501 } 1502 } 1503 } 1504 1505 1506 // ROW 6 ************************ 1507 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1508 for (byte a = 46; a < 55; a++) { // Cycle through all locations 1509 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1510 for (byte r = 46; r < 55; r++) { 1511 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1512 sudoku[r][sudoku[a][1]+3] = 0; 1513 } 1514 } 1515 } 1516 } 1517 // ROW 7 ************************ 1518 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1519 for (byte a = 55; a < 64; a++) { // Cycle through all locations 1520 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1521 for (byte r = 55; r < 64; r++) { 1522 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1523 sudoku[r][sudoku[a][1]+3] = 0; 1524 } 1525 } 1526 } 1527 } 1528 1529 1530 // ROW 8 ************************ 1531 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1532 for (byte a = 64; a < 73; a++) { // Cycle through all locations 1533 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1534 for (byte r = 64; r < 73; r++) { 1535 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1536 sudoku[r][sudoku[a][1]+3] = 0; 1537 } 1538 } 1539 } 1540 } 1541 1542 // ROW 9 ************************ 1543 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1544 for (byte a = 73; a < 82; a++) { // Cycle through all locations 1545 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1546 for (byte r = 73; r < 82; r++) { 1547 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1548 sudoku[r][sudoku[a][1]+3] = 0; 1549 } 1550 } 1551 } 1552 } 1553 1554 /* 1555 for (byte e = 1; e < 82; e++) { // Cycle through all locations 1556 Serial.print(e); Serial.print(" "); 1557 1558 Serial.print(sudoku[e][0]); Serial.print(" "); 1559 1560 Serial.print(sudoku[e][4]); 1561 1562 Serial.print(sudoku[e][5]); 1563 1564 Serial.print(sudoku[e][6]); 1565 1566 Serial.print(sudoku[e][7]); 1567 1568 Serial.print(sudoku[e][8]); 1569 1570 Serial.print(sudoku[e][9]); 1571 1572 Serial.print(sudoku[e][10]); 1573 1574 Serial.print(sudoku[e][11]); 1575 1576 Serial.println(sudoku[e][12]); 1577 1578 } 1579*/ 1580} 1581 1582 1583 void solvevertical(){ // Take Solved locations and apply horizontal rule 1584// Cycle through all locations and using solved flag remove all associate vertical possibilities 1585 1586/* 1587for (byte d = 1; d < 82; d++) { // Cycle through all locations 1588 Serial.print(d); Serial.print(" "); 1589 1590 Serial.print(sudoku[d][0]); Serial.print(" "); 1591 1592 Serial.print(sudoku[d][4]); 1593 1594 Serial.print(sudoku[d][5]); 1595 1596 Serial.print(sudoku[d][6]); 1597 1598 Serial.print(sudoku[d][7]); 1599 1600 Serial.print(sudoku[d][8]); 1601 1602 Serial.print(sudoku[d][9]); 1603 1604 Serial.print(sudoku[d][10]); 1605 1606 Serial.print(sudoku[d][11]); 1607 1608 Serial.println(sudoku[d][12]); 1609} 1610*/ 1611 // COL 1 ************************ 1612 // Step through each of Col locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1613 for (byte a = 1; a < 74; a=a+9) { // Cycle through all locations 1614 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1615 for (byte r = 1; r < 74; r=r+9) { 1616 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1617 sudoku[r][sudoku[a][1]+3] = 0; 1618 } 1619 } 1620 } 1621 } 1622 1623 1624 // COL 2 ************************ 1625 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1626 for (byte a = 2; a < 75; a=a+9) { // Cycle through all locations 1627 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1628 for (byte r = 2; r < 75; r=r+9) { 1629 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1630 sudoku[r][sudoku[a][1]+3] = 0; 1631 } 1632 } 1633 } 1634 } 1635 1636 // COL 3 ************************ 1637 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1638 for (byte a = 3; a < 76; a=a+9) { // Cycle through all locations 1639 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1640 for (byte r = 3; r < 76; r=r+9) { 1641 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1642 sudoku[r][sudoku[a][1]+3] = 0; 1643 } 1644 } 1645 } 1646 } 1647 1648 1649 // COL 4 ************************ 1650 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1651 for (byte a = 4; a < 77; a=a+9) { // Cycle through all locations 1652 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1653 for (byte r = 4; r < 77; r=r+9) { 1654 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1655 sudoku[r][sudoku[a][1]+3] = 0; 1656 } 1657 } 1658 } 1659 } 1660 // COL 5 ************************ 1661 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1662 for (byte a = 5; a < 78; a=a+9) { // Cycle through all locations 1663 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1664 for (byte r = 5; r < 78; r=r+9) { 1665 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1666 sudoku[r][sudoku[a][1]+3] = 0; 1667 } 1668 } 1669 } 1670 } 1671 1672 1673 // COL 6 ************************ 1674 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1675 for (byte a = 6; a < 79; a=a+9) { // Cycle through all locations 1676 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1677 for (byte r = 6; r < 79; r=r+9) { 1678 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1679 sudoku[r][sudoku[a][1]+3] = 0; 1680 } 1681 } 1682 } 1683 } 1684 // COL 7 ************************ 1685 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1686 for (byte a = 7; a < 80; a=a+9) { // Cycle through all locations 1687 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1688 for (byte r = 7; r < 80; r=r+9) { 1689 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1690 sudoku[r][sudoku[a][1]+3] = 0; 1691 } 1692 } 1693 } 1694 } 1695 1696 1697 // COL 8 ************************ 1698 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1699 for (byte a = 8; a < 81; a=a+9) { // Cycle through all locations 1700 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1701 for (byte r = 8; r < 81; r=r+9) { 1702 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1703 sudoku[r][sudoku[a][1]+3] = 0; 1704 } 1705 } 1706 } 1707 } 1708 1709 // COL 9 ************************ 1710 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1711 for (byte a = 9; a < 82; a=a+9) { // Cycle through all locations 1712 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1713 for (byte r = 9; r < 83; r=r+9) { 1714 if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { 1715 sudoku[r][sudoku[a][1]+3] = 0; 1716 } 1717 } 1718 } 1719 } 1720 1721 /* 1722 for (byte e = 1; e < 82; e++) { // Cycle through all locations 1723 Serial.print(e); Serial.print(" "); 1724 1725 Serial.print(sudoku[e][0]); Serial.print(" "); 1726 1727 Serial.print(sudoku[e][4]); 1728 1729 Serial.print(sudoku[e][5]); 1730 1731 Serial.print(sudoku[e][6]); 1732 1733 Serial.print(sudoku[e][7]); 1734 1735 Serial.print(sudoku[e][8]); 1736 1737 Serial.print(sudoku[e][9]); 1738 1739 Serial.print(sudoku[e][10]); 1740 1741 Serial.print(sudoku[e][11]); 1742 1743 Serial.println(sudoku[e][12]); 1744 1745 } 1746*/ 1747} 1748 1749 1750void solvepanel(){ // Take Solved locations and apply horizontal rule 1751// Cycle through all locations and using solved flag remove all associate panel possibilities 1752 1753/* 1754 1755for (byte d = 1; d < 82; d++) { // Cycle through all locations 1756 Serial.print(d); Serial.print(" "); 1757 1758 Serial.print(sudoku[d][0]); Serial.print(" "); 1759 Serial.print(sudoku[d][4]); 1760 Serial.print(sudoku[d][5]); 1761 Serial.print(sudoku[d][6]); 1762 Serial.print(sudoku[d][7]); 1763 Serial.print(sudoku[d][8]); 1764 Serial.print(sudoku[d][9]); 1765 Serial.print(sudoku[d][10]); 1766 Serial.print(sudoku[d][11]); 1767 Serial.println(sudoku[d][12]); 1768 } 1769 1770*/ 1771 1772 1773 1774 // PANEL Algorythm ************************ 1775 // Step through each of locations and delete duplicates of the Solved location using the panel formulae. Ignore the current location you are solving for 1776 for (byte a = 1; a < 82; a++) { // Cycle through all locations 1777 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1778 for (byte r = 1; r < 82; r++) { // Step through all locations 1779 if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { // Identify the locations on the Same Panel 1780 if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { 1781 sudoku[r][sudoku[a][1]+3] = 0; 1782 } 1783 1784 } 1785 } 1786 } 1787 } 1788 1789 /* 1790 1791 1792 for (byte e = 1; e < 82; e++) { // Cycle through all locations 1793 Serial.print(e); Serial.print(" "); 1794 Serial.print(sudoku[e][0]); Serial.print(" "); 1795 Serial.print(sudoku[e][4]); 1796 Serial.print(sudoku[e][5]); 1797 Serial.print(sudoku[e][6]); 1798 Serial.print(sudoku[e][7]); 1799 Serial.print(sudoku[e][8]); 1800 Serial.print(sudoku[e][9]); 1801 Serial.print(sudoku[e][10]); 1802 Serial.print(sudoku[e][11]); 1803 Serial.println(sudoku[e][12]); 1804 */ 1805 1806} 1807 1808 1809 1810void loadpaneldata(){ // Load specifc Panel identification Data into the Array for each of the 81 locations 1811 1812 1813 1814 // Load Numbers 1815 // Panel 1 1816 sudoku[1][13] = 1; sudoku[2][13] = 1; sudoku[3][13] = 1; 1817 sudoku[10][13] = 1; sudoku[11][13] = 1; sudoku[12][13] = 1; 1818 sudoku[19][13] = 1; sudoku[20][13] = 1; sudoku[21][13] = 1; 1819 // Panel 2 1820 sudoku[4][13] = 2; sudoku[5][13] = 2; sudoku[6][13] = 2; 1821 sudoku[13][13] = 2; sudoku[14][13] = 2; sudoku[15][13] = 2; 1822 sudoku[22][13] = 2; sudoku[23][13] = 2; sudoku[24][13] = 2; 1823 // Panel 3 1824 sudoku[7][13] = 3; sudoku[8][13] = 3; sudoku[9][13] = 3; 1825 sudoku[16][13] = 3; sudoku[17][13] = 3; sudoku[18][13] = 3; 1826 sudoku[25][13] = 3; sudoku[26][13] = 3; sudoku[27][13] = 3; 1827 // Panel 4 1828 sudoku[28][13] = 4; sudoku[29][13] = 4; sudoku[30][13] = 4; 1829 sudoku[37][13] = 4; sudoku[38][13] = 4; sudoku[39][13] = 4; 1830 sudoku[46][13] = 4; sudoku[47][13] = 4; sudoku[48][13] = 4; 1831 // Panel 5 1832 sudoku[31][13] = 5; sudoku[32][13] = 5; sudoku[33][13] = 5; 1833 sudoku[40][13] = 5; sudoku[41][13] = 5; sudoku[42][13] = 5; 1834 sudoku[49][13] = 5; sudoku[50][13] = 5; sudoku[51][13] = 5; 1835 // Panel 6 1836 sudoku[34][13] = 6; sudoku[35][13] = 6; sudoku[36][13] = 6; 1837 sudoku[43][13] = 6; sudoku[44][13] = 6; sudoku[45][13] = 6; 1838 sudoku[52][13] = 6; sudoku[53][13] = 6; sudoku[54][13] = 6; 1839 // Panel 7 1840 sudoku[55][13] = 7; sudoku[56][13] = 7; sudoku[57][13] = 7; 1841 sudoku[64][13] = 7; sudoku[65][13] = 7; sudoku[66][13] = 7; 1842 sudoku[73][13] = 7; sudoku[74][13] = 7; sudoku[75][13] = 7; 1843 // Panel 8 1844 sudoku[58][13] = 8; sudoku[59][13] = 8; sudoku[60][13] = 8; 1845 sudoku[67][13] = 8; sudoku[68][13] = 8; sudoku[69][13] = 8; 1846 sudoku[76][13] = 8; sudoku[77][13] = 8; sudoku[78][13] = 8; 1847 // Panel 9 1848 sudoku[61][13] = 9; sudoku[62][13] = 9; sudoku[63][13] = 9; 1849 sudoku[70][13] = 9; sudoku[71][13] = 9; sudoku[72][13] = 9; 1850 sudoku[79][13] = 9; sudoku[80][13] = 9; sudoku[81][13] = 9; 1851 1852} 1853 1854// Used to identify and highlight errors in a current matrix - use solve method however instead of solving outcome just highlight conflicts in red 1855void helpbutton(){ 1856 1857 1858// Horizontal ********************* 1859 // ROW 1 ************************ 1860 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1861 for (byte a = 1; a < 10; a++) { // Cycle through all locations 1862 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1863 for (byte r = 1; r < 10; r++) { 1864 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1865 // Refresh only the location concerned with new value and show colour coded 1866 //First Clear Location 1867 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1868 tft.setTextSize(2); 1869 tft.setTextColor(RED); 1870 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1871 } 1872 } 1873 } 1874 } 1875 1876 1877 // ROW 2 ************************ 1878 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1879 for (byte a = 10; a < 19; a++) { // Cycle through all locations 1880 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1881 for (byte r = 10; r < 19; r++) { 1882 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1883 // Refresh only the location concerned with new value and show colour coded 1884 //First Clear Location 1885 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1886 tft.setTextSize(2); 1887 tft.setTextColor(RED); 1888 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1889 } 1890 } 1891 } 1892 } 1893 1894 // ROW 3 ************************ 1895 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1896 for (byte a = 19; a < 28; a++) { // Cycle through all locations 1897 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1898 for (byte r = 19; r < 28; r++) { 1899 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1900 // Refresh only the location concerned with new value and show colour coded 1901 //First Clear Location 1902 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1903 tft.setTextSize(2); 1904 tft.setTextColor(RED); 1905 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1906 } 1907 } 1908 } 1909 } 1910 1911 1912 // ROW 4 ************************ 1913 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1914 for (byte a = 28; a < 37; a++) { // Cycle through all locations 1915 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1916 for (byte r = 28; r < 37; r++) { 1917 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1918 // Refresh only the location concerned with new value and show colour coded 1919 //First Clear Location 1920 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1921 tft.setTextSize(2); 1922 tft.setTextColor(RED); 1923 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1924 } 1925 } 1926 } 1927 } 1928 // ROW 5 ************************ 1929 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1930 for (byte a = 37; a < 46; a++) { // Cycle through all locations 1931 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1932 for (byte r = 37; r < 46; r++) { 1933 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1934 // Refresh only the location concerned with new value and show colour coded 1935 //First Clear Location 1936 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1937 tft.setTextSize(2); 1938 tft.setTextColor(RED); 1939 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1940 } 1941 } 1942 } 1943 } 1944 1945 1946 // ROW 6 ************************ 1947 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1948 for (byte a = 46; a < 55; a++) { // Cycle through all locations 1949 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1950 for (byte r = 46; r < 55; r++) { 1951 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1952 // Refresh only the location concerned with new value and show colour coded 1953 //First Clear Location 1954 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1955 tft.setTextSize(2); 1956 tft.setTextColor(RED); 1957 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1958 } 1959 } 1960 } 1961 } 1962 // ROW 7 ************************ 1963 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1964 for (byte a = 55; a < 64; a++) { // Cycle through all locations 1965 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1966 for (byte r = 55; r < 64; r++) { 1967 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1968 // Refresh only the location concerned with new value and show colour coded 1969 //First Clear Location 1970 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1971 tft.setTextSize(2); 1972 tft.setTextColor(RED); 1973 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1974 } 1975 } 1976 } 1977 } 1978 1979 1980 // ROW 8 ************************ 1981 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1982 for (byte a = 64; a < 73; a++) { // Cycle through all locations 1983 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 1984 for (byte r = 64; r < 73; r++) { 1985 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 1986 // Refresh only the location concerned with new value and show colour coded 1987 //First Clear Location 1988 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 1989 tft.setTextSize(2); 1990 tft.setTextColor(RED); 1991 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 1992 } 1993 } 1994 } 1995 } 1996 1997 // ROW 9 ************************ 1998 // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for 1999 for (byte a = 73; a < 82; a++) { // Cycle through all locations 2000 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2001 for (byte r = 73; r < 82; r++) { 2002 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2003 // Refresh only the location concerned with new value and show colour coded 2004 //First Clear Location 2005 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2006 tft.setTextSize(2); 2007 tft.setTextColor(RED); 2008 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2009 } 2010 } 2011 } 2012 } 2013 2014// Vertical **************** 2015 // COL 1 ************************ 2016 // Step through each of Col locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2017 for (byte a = 1; a < 74; a=a+9) { // Cycle through all locations 2018 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2019 for (byte r = 1; r < 74; r=r+9) { 2020 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2021 // Refresh only the location concerned with new value and show colour coded 2022 //First Clear Location 2023 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2024 tft.setTextSize(2); 2025 tft.setTextColor(RED); 2026 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2027 } 2028 } 2029 } 2030 } 2031 2032 2033 // COL 2 ************************ 2034 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2035 for (byte a = 2; a < 75; a=a+9) { // Cycle through all locations 2036 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2037 for (byte r = 2; r < 75; r=r+9) { 2038 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2039 // Refresh only the location concerned with new value and show colour coded 2040 //First Clear Location 2041 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2042 tft.setTextSize(2); 2043 tft.setTextColor(RED); 2044 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2045 } 2046 } 2047 } 2048 } 2049 2050 // COL 3 ************************ 2051 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2052 for (byte a = 3; a < 76; a=a+9) { // Cycle through all locations 2053 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2054 for (byte r = 3; r < 76; r=r+9) { 2055 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2056 // Refresh only the location concerned with new value and show colour coded 2057 //First Clear Location 2058 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2059 tft.setTextSize(2); 2060 tft.setTextColor(RED); 2061 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2062 } 2063 } 2064 } 2065 } 2066 2067 2068 // COL 4 ************************ 2069 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2070 for (byte a = 4; a < 77; a=a+9) { // Cycle through all locations 2071 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2072 for (byte r = 4; r < 77; r=r+9) { 2073 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2074 // Refresh only the location concerned with new value and show colour coded 2075 //First Clear Location 2076 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2077 tft.setTextSize(2); 2078 tft.setTextColor(RED); 2079 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2080 } 2081 } 2082 } 2083 } 2084 // COL 5 ************************ 2085 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2086 for (byte a = 5; a < 78; a=a+9) { // Cycle through all locations 2087 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2088 for (byte r = 5; r < 78; r=r+9) { 2089 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2090 // Refresh only the location concerned with new value and show colour coded 2091 //First Clear Location 2092 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2093 tft.setTextSize(2); 2094 tft.setTextColor(RED); 2095 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2096 } 2097 } 2098 } 2099 } 2100 2101 2102 // COL 6 ************************ 2103 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2104 for (byte a = 6; a < 79; a=a+9) { // Cycle through all locations 2105 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2106 for (byte r = 6; r < 79; r=r+9) { 2107 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2108 // Refresh only the location concerned with new value and show colour coded 2109 //First Clear Location 2110 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2111 tft.setTextSize(2); 2112 tft.setTextColor(RED); 2113 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2114 } 2115 } 2116 } 2117 } 2118 // COL 7 ************************ 2119 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2120 for (byte a = 7; a < 80; a=a+9) { // Cycle through all locations 2121 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2122 for (byte r = 7; r < 80; r=r+9) { 2123 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2124 // Refresh only the location concerned with new value and show colour coded 2125 //First Clear Location 2126 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2127 tft.setTextSize(2); 2128 tft.setTextColor(RED); 2129 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2130 } 2131 } 2132 } 2133 } 2134 2135 2136 // COL 8 ************************ 2137 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2138 for (byte a = 8; a < 81; a=a+9) { // Cycle through all locations 2139 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2140 for (byte r = 8; r < 81; r=r+9) { 2141 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2142 // Refresh only the location concerned with new value and show colour coded 2143 //First Clear Location 2144 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2145 tft.setTextSize(2); 2146 tft.setTextColor(RED); 2147 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2148 } 2149 } 2150 } 2151 } 2152 2153 // COL 9 ************************ 2154 // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for 2155 for (byte a = 9; a < 82; a=a+9) { // Cycle through all locations 2156 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2157 for (byte r = 9; r < 83; r=r+9) { 2158 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2159 // Refresh only the location concerned with new value and show colour coded 2160 //First Clear Location 2161 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2162 tft.setTextSize(2); 2163 tft.setTextColor(RED); 2164 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2165 } 2166 } 2167 } 2168 } 2169// Panels ******************* 2170 2171 // PANEL Algorythm ************************ 2172 // Step through each of locations and delete duplicates of the Solved location using the Oanel formulae. Ignore the current location you are solving for 2173 for (byte a = 1; a < 82; a++) { // Cycle through all locations 2174 if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry 2175 for (byte r = 1; r < 82; r++) { // Step through all locations 2176 if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { // Identify the locations on the Same Panel 2177 if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED 2178 // Refresh only the location concerned with new value and show colour coded 2179 //First Clear Location 2180 tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); 2181 tft.setTextSize(2); 2182 tft.setTextColor(RED); 2183 tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); 2184 } 2185 2186 } 2187 } 2188 } 2189 } 2190 2191 2192// Horizontal conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE 2193 2194// Vertical conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE 2195 2196// Panel conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE 2197 2198 2199} 2200 2201 2202void uniquecandidate() { // Each panel, row and column on a Sudoku board must contain every number between 1 and 9. 2203 // 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. 2204 2205/* 2206 2207for (byte d = 1; d < 82; d++) { // Cycle through all locations 2208 Serial.print(d); Serial.print(" "); 2209 2210 Serial.print(sudoku[d][0]); Serial.print(" "); 2211 Serial.print(sudoku[d][1]); Serial.print(" "); 2212 Serial.print(sudoku[d][4]); 2213 Serial.print(sudoku[d][5]); 2214 Serial.print(sudoku[d][6]); 2215 Serial.print(sudoku[d][7]); 2216 Serial.print(sudoku[d][8]); 2217 Serial.print(sudoku[d][9]); 2218 Serial.print(sudoku[d][10]); 2219 Serial.print(sudoku[d][11]); 2220 Serial.println(sudoku[d][12]); 2221 } 2222 2223*/ 2224 2225byte tempcount = 0; 2226 2227 for (byte p = 1; p < 10; p++) { // Cycle through all panels 1 to 9 2228 2229 for (byte v = 1; v < 10; v++) { // Step through all possible unique location values in each panel 2230 2231 2232 for (byte r = 1; r < 82; r++) { // Step through all locations 2233 2234 if (sudoku[r][13] == p) { //Only operate on those locations that are in this panel 2235 2236 if (sudoku[r][v+3] == v) {// Count this if value is what we are looking for 2237 tempcount++; 2238 } 2239 } 2240 } 2241 // Check if unique 2242 if ( tempcount == 1) { // This is a unique value so reset the location with this being a solved location 2243 // Repeat process to locate unique location 2244 for (byte r = 1; r < 82; r++) { // Step through all locations and then mark as solved 2245 2246 if (sudoku[r][13] == p) { //Only operate on those locations that are in this panel 2247 if (sudoku[r][v+3] == v) {// Count this if value is what we are looking for 2248 2249 // Now poke the answer into the correct location 2250 if (sudoku[r][0] == 0) { // Change to solved but remain green 2251 sudoku[r][0] = 2; 2252 } 2253 sudoku[r][1] = v; 2254 } 2255 } 2256 } 2257 } 2258 // Reset temp counter 2259 tempcount = 0; 2260 } 2261 } 2262/* 2263for (byte d = 1; d < 82; d++) { // Cycle through all locations 2264 Serial.print(d); Serial.print(" "); 2265 2266 Serial.print(sudoku[d][0]); Serial.print(" "); 2267 Serial.print(sudoku[d][1]); Serial.print(" "); 2268 Serial.print(sudoku[d][4]); 2269 Serial.print(sudoku[d][5]); 2270 Serial.print(sudoku[d][6]); 2271 Serial.print(sudoku[d][7]); 2272 Serial.print(sudoku[d][8]); 2273 Serial.print(sudoku[d][9]); 2274 Serial.print(sudoku[d][10]); 2275 Serial.print(sudoku[d][11]); 2276 Serial.println(sudoku[d][12]); 2277 } 2278*/ 2279 2280} 2281
Downloadable files
Circuit Diagram
Circuit Diagram
Documentation
3D Enclosure files
The 3D case was printed with White PLA with each part oriented so that Lid and Base are facing upwards using the following settings Layer Height: 0.2mm Speed: 40mm/s Nozzle Diameter: 0.4mm Supports: Enabled Nozzle Temperature: 210 Degrees
https://www.thingiverse.com/thing:3638281
Comments
Only logged in users can leave comments