Code
//sudoku | dictionary - grid - 9x9 | cell - 3x3 | slot - 1x1
import javax.swing.JOptionPane;
int grid[][] = new int[9][9];
int saved[][][] = new int[9][9][3];
boolean locked[][] = new boolean[9][9];
boolean editing = false, editLocked=false, showMoves=false, showCovered=true, showNotes=true;
int num = 9, moves = 0, sel =1;
float scl=64;
float scl2=128, p2x = 646, p2y = 115;
float scl3=96, p3x = 646, p3y = 19;
float scl4X=96, scl4Y=18, p4x=934, p4y=499;
float scl5X=21.333, scl5Y=16;
float p6x = 934-3*scl4X, p6y=499, scl6X=96, scl6Y=24;
PFont roboto;
String loadString = "873410900065028070020703000540000210208007490690080000480000500700031609010009807";
//EASY: 873410900065028070020703000540000210208007490690080000480000500700031609010009807
//MEDIUM: 730095000600030709200000300068704190000000860000000004900108400051900270000050080
//HARD: 080200009000300006960070001000000000090700200040001008070400500004030800306000000
void setup() {
roboto = createFont("Roboto-Light.ttf", 70);
textFont(roboto);
size(1100, 576);
textAlign(3, 3);
textSize(scl*0.6);
if (loadString.length()==81) loadBlueprint(loadString);
//for (int i = 0; i < 100; i++) saved[(int)random(9)][(int)random(9)][(int)random(3)]= (int)random(9);
}
void draw() {
background(0);
if (showCovered) for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) if (grid[i][j]==sel && sel!=0) showCovered(i, j);
noFill();
//stroke(255, 20);
noStroke();
for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) { //drawing the main grid
textSize(scl*0.6);
fill(0, 0, 255, 50);
if (locked[i][j]) square(i*scl, j*scl, scl);
fill( ((grid[i][j]==sel)? color(255, 0, 55) : color(255) ) ); //all slots that match the selected number will be red-ish
if (grid[i][j]!=0)text(grid[i][j], (i+0.5)*scl, (j+0.5)*scl);
textSize(scl5Y*0.9);
if (showNotes&&locked[i][j] == false) for (int k = 0; k < 3; k++) {
fill( ((saved[i][j][k]==sel)? color(255, 0, 55) : color(255) ));
if (saved[i][j][k]!=0) text( saved[i][j][k], i*scl+(k+0.5)*scl5X, j*scl+0.5*scl5Y );
}
}
stroke(255, 40);
for (int i = 1; i < 9; i++) line( i*scl, 0, i*scl, height); //drawing the stronger 3 lines
for (int i = 1; i < 9; i++) line( 0, i*scl, height, i*scl);
stroke(255);
for (int i = 1; i < 4; i++) line( 3*i*scl, 0, 3*i*scl, height); //drawing the stronger 3 lines
for (int i = 1; i < 3; i++) line( 0, 3*i*scl, height, 3*i*scl);
//fill(255);
textSize(scl2*0.6);
noFill();
for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { //drawing the select button area
square(p2x+scl2*i, p2y+scl2*j, scl2);
fill( ((sel==i+j*3+1)? color(255) : color(255, 150)));
text(i+j*3+1, p2x+scl2*(i+0.5), p2y+scl2*(j+0.5));
noFill();
}
textSize(scl3*0.65);
for (int i = 0; i < 4; i+=((i==1)? 2 : 1)) { //displaying the 3 upper, smaller buttons
noFill();
square(p3x+i*scl3, p3y, scl3);
fill( ( (i==0 && sel==0)? color(255) : ((i==1)? color(255, 150) : (i==3 && editing)? color(255) : color(255, 150))));
text( ( (i==0)? "Ж" : ((i==1)? "Ф" : "LK") ), p3x+(i+0.5)*scl3, p3y+scl3*0.4);
}
if (editing) { //displaying the SHOW MOVES/EDIT LOCKED/SHOW COVERED buttons
textSize(scl4Y*0.65);
for (int i = 0; i < 4; i++) { //CHANGED TO 4
noFill();
rect(p4x, p4y+i*scl4Y, scl4X, scl4Y);
fill( (( i==0&&editLocked || i==1&&showMoves || i==2&&showCovered || i==3&&showNotes)? color(255) : color(255, 150) ) );
text( ((i==0)? "EDIT LOCKED" : ((i==1)? "SHOW MOVES" : ((i==2)?"SHOW COVERED":"SHOW NOTES"))), p4x+0.5*scl4X, p4y+(i+0.5)*scl4Y);
}
//LOAD/SAVE BUTTONS
noFill();
textSize(scl6Y*0.5);
for (int i = 0; i < 2; i++) {
rect(p6x, p6y+scl6Y*i, scl6X, scl6Y);
text( ((i==0)? "LOAD BLUEPRINT" : "SAVE BLUEPRINT" ), p6x+scl6X*0.5, p6y+scl6Y*(i+0.5));
}
}
fill(255);
textSize(scl*0.6);
if (showMoves==true && !editing) text("MOVES: "+moves, 838, 530);
}
void showCovered(int x, int y) {
fill(0, 200, 40, 20);
noStroke();
rect(0, y*scl, scl*num, scl);
rect(x*scl, 0, scl, scl*num);
square( floor(x/3)*3*scl, floor(y/3)*3*scl, scl*3);
}
void mousePressed() {
if (mouseButton==LEFT) {
if (mouseX>p2x&&mouseY>p2y&&mouseX<p2x+3*scl2&&mouseY<p2y+3*scl2) { //number selection menu
float mmx = mouseX-p2x, mmy = mouseY-p2y;
sel = (int)(mmx/scl2+1)+ (int)(mmy/scl2)*3;
}
if (mouseX<scl*num) {//main grid - getting the mouse position and filling the slot
int mx = constrain(floor(mouseX/scl), 0, 9), my = constrain(floor(mouseY/scl), 0, 9);
if ((setSlot(mx, my, sel)==0)) grid[mx][my] = 0; //if the slot already has the number you selected, it will clear the slot
if (locked[mx][my]==true && grid[mx][my] != 0) sel = grid[mx][my]; //if user clicks on a locked slot, selection will shift
}
if (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+4*scl3&&mouseY<p3y+scl3) { //The top 4 buttons (id = 3)
int mx = floor((mouseX-p3x)/scl3);
if (mx==0) sel = 0;
if (mx==1 && JOptionPane.showConfirmDialog (null, "Do you want to clear the board?", "Confirm", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_NO_OPTION) {
for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) {
if (grid[i][j]!=0&&locked[i][j]==false) grid[i][j]=0;
for (int k = 0; k < 3; k++) saved[i][j][k]=0;
}
moves=0;
}
if (mx==3) editing = !editing;
}
if (mouseX>p4x&&mouseY>p4y&&mouseX<p4x+scl4X&&mouseY<p4y+scl4Y*4) {
int my = floor((mouseY-p4y)/scl4Y);
if (my==0) editLocked = !editLocked;
if (my==1) showMoves = !showMoves;
if (my==2) showCovered = !showCovered;
if (my==3) showNotes=!showNotes;
}
if(mouseX>p6x&&mouseY>p6y&&mouseX<p6x+scl6X&&mouseY<p6y+scl6Y*2) {
int my = floor((mouseY-p6y)/scl6Y);
if(my==0) loadBlueprint( JOptionPane.showInputDialog(null, "ENTER BLUEPRINT" ) );
if(my==1) saveBlueprint();
}
} else if (mouseButton==RIGHT) {
if (mouseX<scl*num && editing == true && editLocked) {//main grid - edit locked slots
int mx = floor(mouseX/scl), my = floor(mouseY/scl);
locked[mx][my] = !locked[mx][my];
}
if (mouseX<scl*num) {
int mx = constrain(floor(mouseX/scl), 0, 9), my = constrain(floor(mouseY/scl), 0, 9);
if (showNotes==true) {
int mx2 = floor(map(mouseX-mx*scl, 0, scl, 0, 3));
saved[mx][my][mx2] = ((saved[mx][my][mx2]==sel)? 0 : sel);
}
}
}
}
void keyPressed() {
if (keyCode>47&&keyCode<58) { //numbers 0-9
int mx = floor(mouseX/scl), my = floor(mouseY/scl), nnum = keyCode-48;
if (sel==nnum) if ((setSlot(mx, my, sel)==0)) grid[mx][my] = 0; //first time pressing the number will set the number as sel, second will input it
sel=keyCode-48;
}
}
int setSlot(int x, int y, int value) { //0 - slot matches the selection - will empty | 1 - success | 2 - slot is locked
if (grid[x][y]==value && (!locked[x][y]||editing)) {
println("slot is already filled with the same number!");
return 0;
}
if (locked[x][y]==false||editing==true) {
println("changing the slot!");
moves++;
grid[x][y] = value;
} else {
println("FAILED-the slot is locked");
return 2;
}
return 1;
}
void loadBlueprint(String blueprint) {
if (blueprint.length()==81) {
for (int i = 0; i < 81; i++) {
int x = i%num, y = floor(i/num), number = int(blueprint.charAt(i)-48);
grid[x][y]=number;
locked[x][y]=(number!=0);
for(int k = 0; k < 3; k++) saved[x][y][k]=0;
}
}
}
String saveBlueprint() {
String output="";
for (int j = 0; j < num; j++) for (int i = 0; i < num; i++) output+=grid[i][j];
println("Blueprint:"+output);
JOptionPane.showMessageDialog(frame, "Current blueprint: [Available in console]\n"+output);
return output;
}
void mouseWheel(MouseEvent event) {
int e = event.getCount();
sel= (sel-e)%(num+1);
if(sel<0) sel = num;
println(e,sel);
}
/* TODO:
the error checker will store the quantity of numbers instead of just if they are there.
Add a LOAD/SAVE | Will be replaced with the BLUEPRINT button. It will make a popup, where it will ask you what you want
so 1) SAVE 2) LOAD -> next menu, choose difficulty (1:easy,2:medium,3:hard)-> there are x blueprints of [difficulty], choose a number, -1 for random
load/save prompt should show up if clicked
NEW CONTENT:
- can save up to 3 numbers per slot with right click
- roboto light font
- confirmation before board erasure
- can save/load blueprints mid game
- scroll mouse wheel to change selection
*/