first commit

This commit is contained in:
Stefano Rossi 2025-07-10 03:30:51 +02:00
commit b4fa9ed710
Signed by: chadmin
GPG key ID: 9EFA2130646BC893
13 changed files with 749 additions and 0 deletions

16
CambiaTitoloeIcona.pde Normal file
View file

@ -0,0 +1,16 @@
PImage fai_iconi;
PGraphics fai_icong;
String fai_filename;
void frameAndIcon(String frameText, String iconFilename) {
if ( fai_filename == null || !fai_filename.equals(iconFilename) ) {
fai_iconi = loadImage(iconFilename);
fai_icong = createGraphics(16, 16, JAVA2D);
fai_filename = iconFilename;
}
surface.setTitle( frameText );
fai_icong.beginDraw();
fai_icong.image( fai_iconi, 0, 0 );
fai_icong.endDraw();
frame.setIconImage(fai_icong.image);
}

83
Celle.pde Normal file
View file

@ -0,0 +1,83 @@
private void creaCelle(){
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
celle[r][c] = new Cella(r, c, lato/cellePerLato);
}
}
}
private void risolviSudoku(){
new thRisolutore(celle);
}
//metodo per l inserimento del numero nella cella, questo metodo controlla se il numero è inseribile
// e lo inserisce, se non lo è ritorna r e c della cella che va in conflitto
private void inserisciNumero(int r, int c, int n){
//println(c);
//println(r);
Cella[] cellaConflitto = new Cella[3];
cellaConflitto[1] = null;
cellaConflitto[1] = null;
cellaConflitto[2] = null;
//Controllo in tutta la COLONNA se è già presente il numero che si vuole inserire
for(int iC = 0; iC < 9; iC++){
if(n != 0 && n == celle[r][iC].getN()){
cellaConflitto[0] = new Cella(r, iC, n);
//println("numero gia presente alla Col: " + r + " e alla rig: " + iC);
//println("n conf " + celle[c][iC].getN() + " n nuovo: " + celle[c][r].getN());
}
}
//Controllo in tutta la RIGA se è già presente il numero che si vuole inserire
for(int iR = 0; iR < 9; iR++){
if(n != 0 && n == celle[iR][c].getN()){
cellaConflitto[1] = new Cella(iR, c, n);
//println("numero gia presente alla Col: " + iR + " e alla rig: " + c);
//println("n conf " + celle[c][iR].getN() + " n nuovo: " + celle[c][r].getN());
}
}
//Controllo che nella regione non è già presente lo stesso numero
//trovo la regione della cella
int cR = floor(r/3);
int rR = floor(c/3);
//println(rR);
//println(cR);
for(int i = 0; i <3; i++){
for(int j = 0; j <3; j++){
if(n != 0 && n == celle[cR*3 + j][rR*3 + i].getN()){
//controllo che cella modificata e controllata siano diverse
if(r != (cR*3 + j) && c != (rR*3 + i)){ //<>//
cellaConflitto[2] = new Cella(cR*3 + j, rR*3 + i, n);
//println(cR*3 + j + " " + r);
//println(rR*3 + i + " " + c);
//println();
}
//println(celle[rR*3 + j][cR*3 + i].getN());
}
//println(rR*3 + j + " " + c);
//println(cR*3 + i + " " + r);
//println();
}
}
if(cellaConflitto[0] != null){
new ThTiming(cellaConflitto[0].getR(), cellaConflitto[0].getC()).inizia();
}
if(cellaConflitto[1] != null){
new ThTiming(cellaConflitto[1].getR(), cellaConflitto[1].getC()).inizia();
}
if(cellaConflitto[2] != null){
new ThTiming(cellaConflitto[2].getR(), cellaConflitto[2].getC()).inizia();
}
if(cellaConflitto[0] == null && cellaConflitto[1] == null && cellaConflitto[2] == null){
celle[r][c].setN(n);
}
}

119
Classe_Cella.pde Normal file
View file

@ -0,0 +1,119 @@
private class Cella{
private int R; //Riga della cella
private int C; //Colonna della cella
private int L; //lato
private int N; //numero contenuto nella cella
private color ColCella; // colore bg della cella
private color ColN; //colore del numero
private int pntFontN; //grnadezza carattere
private color warningColor; //colore sfondo per evidenziare celle in conflitto col nuovo num da inserire
private boolean fissa;
private boolean selezionata; //true se la cella è stata cliccata
//COSTRUTTORE
public Cella(int R, int C, int L){
this.R = R;
this.C = C;
this.L = L;
this.N = 0;
this.ColCella = color(0, 200, 200, 80); //Azzurro trasp
this.warningColor = color(255, 0, 0, 0); //rosso completamente trasparente
this.pntFontN = 20;
this.selezionata = false;
this.fissa = false;
this.ColN = color(0, 102, 153); //blu chiaro
}
//METODI
public void toggleFissa(){
this.fissa = !this.fissa;
//println(fissa);
if(this.fissa){
this.ColN = color(0, 0, 0); //nero
this.ColCella = color(255, 128, 0, 200); //arancione
}else{
this.ColN = color(0, 102, 153); //blu chiaro
this.ColCella = color(0, 200, 200, 80); //Azzurro trasp
}
}
//GETTER E SETTER
public boolean isSelezionata() {
return this.selezionata;
}
public void setSelezionata(boolean selezionata) {
this.selezionata = selezionata;
}
public int getX() {
return this.R * this.L;
}
public int getY() {
return this.C * this.L;
}
public int getL() {
return this.L;
}
public void setR(int R) {
this.R = R;
}
public int getR() {
return this.R;
}
public void setC(int C) {
this.C = C;
}
public int getC() {
return this.C;
}
public void setN(int N) {
this.N = N;
}
public int getN() {
return this.N;
}
public void setWarningColor(color warningColor) {
this.warningColor = warningColor;
}
public int getWarningColor() {
return this.warningColor;
}
public void setPntFontN(int pntFontN) {
this.pntFontN = pntFontN;
}
public int getPntFontN() {
return this.pntFontN;
}
public void setColN(color ColN) {
this.ColN = ColN;
}
public color getColN() {
return this.ColN;
}
public color getColCella() {
return this.ColCella;
}
public void setFissa(boolean fissa) {
this.fissa = fissa;
}
public boolean isFissa() {
return this.fissa;
}
}

160
Classe_ThRisolutore.pde Normal file
View file

@ -0,0 +1,160 @@
public class thRisolutore extends Thread{
private Cella[][] celleSoluzione;
private boolean esecuzione;
private boolean arretra;
public thRisolutore(Cella[][] celleInput) {
celleSoluzione = new Cella[9][9];
//creao un secondo array bidim celle dove andrò a salvare i numeri della soluzione
//ora riempo l array soluzioni con i numeri gia inseriti e li metto fissi
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
celleSoluzione[c][r] = new Cella(c, r, lato/cellePerLato);
celleSoluzione[c][r].setN(celleInput[c][r].getN());
if(celleSoluzione[c][r].getN() > 0){
celleSoluzione[c][r].setFissa(true);
//println("Riga" + r + "Colonna" + c + "è fissata: " + celleSoluzione[c][r].getN());
}
}
}
//faccio subito partire il thread
this.inizia();
}
public void inizia(){
this.esecuzione = true;
this.start();
}
boolean isEsecuzione() {
return this.esecuzione;
}
private boolean inserisciVal(int r, int c, int n){
//println("provo con " + n);
//Controllo in tutta la COLONNA se è già presente il numero che si vuole inserire
for(int iC = 0; iC < 9; iC++){
//println("c: " + iC);
if(n != 0 && n == celleSoluzione[iC][r].getN()){
//println(n + " gia presente in c: " + iC);
return true;
}//else println(n + " non presente in c: " + iC);
}
//Controllo in tutta la COLONNA se è già presente il numero che si vuole inserire
for(int iR = 0; iR < 9; iR++){
//println("r: " + iR);
if(n != 0 && n == celleSoluzione[c][iR].getN()){
//println(n + " gia presente in c: " + iR);
return true;
}//else println(n + " non presente in c: " + iR);
}
//Controllo che nella regione non è già presente lo stesso numero
//trovo la regione della cella
int cR = floor(c/3);
int rR = floor(r/3);
for(int iR = 0; iR <3; iR++){
for(int iC = 0; iC <3; iC++){
if(n != 0 && n == celleSoluzione[cR*3 + iC][rR*3 + iR].getN()){
//controllo che cella modificata e controllata siano diverse
if(c != (cR*3 + iC) && r != (rR*3 + iR)){
return true;
}
}
}
}
//try {
// Thread.sleep(500);
//}catch(InterruptedException e) {
// esecuzione = false;
//}
celleSoluzione[c][r].setN(n);
return false;
}
public void run()
{
while(esecuzione){
celle = celleSoluzione;
boolean errore; //numero inserito non valido
int prove;
errore = true;
try {
celle = celleSoluzione;
for(int r = 0; r < 9; r++){
for(int c = 0; c < 9; c++){
//println(r + " " + c);
//parto dalla prima cella in alto a sx, controlo se è non è fissa altrimenti la salto
if(!celleSoluzione[c][r].isFissa()){
arretra = false;
//println("cella non fissa: " + c);
if(celleSoluzione[c][r].getN() < 9){
//println("n < 9: ");
errore = true;
prove = 1;
while(errore){
//quando arrivo a dover inserire 10 nella esco dal while e torno indietro
if(celleSoluzione[c][r].getN() + prove < 10){
//println("controllo fattibilità");
errore = inserisciVal(r, c, celleSoluzione[c][r].getN() + prove);
prove ++;
}else{
//se arrivo a provare il 9 e non va allora arretro di una cella
arretra = true;
errore = false;
celleSoluzione[c][r].setN(0);
if(c!=0){
c -= 2;
}else{
r --;
c = 7;
}
}
}
}else{
//se la cella in cui ho indietreggiato contiene nove allora arretro ancroa
errore = false;
arretra = true;
celleSoluzione[c][r].setN(0);
if(c!=0){
c -= 2;
}else{
r --;
c = 7;
}
}
}else if (arretra){
//se ho appena arretrato e la cella è ancora fissa aretro ancora
if(c!=0){
c -= 2;
}else{
r --;
c = 7;
}
}
//println("nuova cella colonna");
Thread.sleep(0);
}
//println("nuova cella riga");
}
println("è stato facile");
esecuzione = false;
}catch(InterruptedException e) {
esecuzione = false;
}
}
}
}

44
Classe_ThTiming.pde Normal file
View file

@ -0,0 +1,44 @@
public class ThTiming extends Thread {
private boolean esecuzione;
int r, c;
public ThTiming(int r, int c) {
this.esecuzione = false;
this.r = r;
this.c = c;
}
public void inizia(){
this.esecuzione = true;
this.start();
}
boolean isEsecuzione() {
return this.esecuzione;
}
void run () {
//salvo il colore iniziale
try {
celle[r][c].setWarningColor(color(255, 0, 0, 255));
Thread.sleep(800);
}catch(InterruptedException e) {
esecuzione = false;
}
while (esecuzione) {
for(int i = 0; i<=255 && esecuzione; i += 5){
try {
Thread.sleep(20);
celle[r][c].setWarningColor(color(255, 0, 0, 255 - i));
//println(i);
}
catch(InterruptedException e) {
esecuzione = false;
}
}
esecuzione = false;
celle[r][c].setWarningColor(color(255, 0, 0, 0));
}
}
}

103
KeyPressed.pde Normal file
View file

@ -0,0 +1,103 @@
void keyPressed() {
//trova keyCode
//println("CODICE: " + keyCode);
if(keyCode == 71){
creaCelle();
}
//QUANDO PREMO r o R parte il ciclo della rosoluzione del sudoku
if(keyCode == 82 || keyCode == 16){
risolviSudoku();
}
//QUANDO PREMO ENTER o SPAZIO confermo il numero nella cella selezionata
if(keyCode == 10 || keyCode == 32){
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
celle[r][c].setSelezionata(false);
UCS.setSelezionata(false);
}
}
}
//QUANDO PREMO DEL o CANC confermo il numero nella cella selezionata
if(keyCode == 8 || keyCode == 127){
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
if(celle[r][c].isSelezionata()) celle[r][c].setN(0);
if(celle[r][c].isSelezionata()) celle[r][c].setFissa(false);
}
}
}
//QUANDO PREMO TAB togglo lo stato fisso della cella selezionata
if(keyCode == 9){
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
if(celle[r][c].isSelezionata()) celle[r][c].toggleFissa();
}
}
}
//QUANDO PREMO ESC parte la chiusura del programma nel draw
if(keyCode == 27){
exit();
}
//QUANDO PREMO FRECCIA SX 37, DX 39, SU 38, GIU 40 se la cella non è stata messa fissa
if(keyCode == 37 || keyCode == 39 || keyCode == 38 || keyCode == 40){
//println(UCS.getR());
//println(UCS.getC());
if(keyCode == 37){ //sx
if(UCS.getR() - 1>= 0){
celle[UCS.getR()][UCS.getC()].setSelezionata(false); //deseleziono la cella selezionata attualmente
celle[UCS.getR() - 1][UCS.getC()].setSelezionata(true);
UCS.setR(UCS.getR() - 1);
}
} else if(keyCode == 39){ //dx
if(UCS.getR() + 1< 9){
celle[UCS.getR()][UCS.getC()].setSelezionata(false); //deseleziono la cella selezionata attualmente
celle[UCS.getR() + 1][UCS.getC()].setSelezionata(true);
UCS.setR(UCS.getR() + 1);
}
} else if(keyCode == 38){ //su
if(UCS.getC() - 1>= 0){
celle[UCS.getR()][UCS.getC()].setSelezionata(false); //deseleziono la cella selezionata attualmente
celle[UCS.getR()][UCS.getC() - 1].setSelezionata(true);
UCS.setC(UCS.getC() - 1);
}
} else if(keyCode == 40) { // giu
if(UCS.getC() + 1 < 9){
celle[UCS.getR()][UCS.getC()].setSelezionata(false); //deseleziono la cella selezionata attualmente
celle[UCS.getR()][UCS.getC() + 1].setSelezionata(true);
UCS.setC(UCS.getC() + 1);
}
}
}
//controllo se ho cliccato un tasto numerico, in tal caso vado a vedere r e c della cella clicata
if((keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 105) && (!celle[UCS.getR()][UCS.getC()].isFissa() || celle[UCS.getR()][UCS.getC()].getN() == 0)){
int rPreSelezionata = - 1;
int cPreSelezionata = - 1;
boolean trovata = false;
//deseleziono ogni cella, trovo se ce n era una ancora cliccata e in tal caso salvo num riga e col
for(int r = 0; r < cellePerLato && !trovata; r++){
for(int c = 0; c < cellePerLato && !trovata; c++){
if(celle[r][c].isSelezionata()){
rPreSelezionata = r;
cPreSelezionata = c;
trovata = true;
}
}
}
if(trovata){
//controllo se premo un tasto per l inserimento di numeri, e se sono tra 0 e 9 li assegno alla cella cliccata
if(keyCode - 48 <= 9) inserisciNumero(rPreSelezionata,cPreSelezionata, keyCode - 48);
else inserisciNumero(rPreSelezionata,cPreSelezionata, keyCode - 96);
}
}
}

26
LICENSE Normal file
View file

@ -0,0 +1,26 @@
# DON'T BE A DICK PUBLIC LICENSE
> Version 1.1, December 2016
> Copyright (C) 2024 Rossi Stefano
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document.
> DON'T BE A DICK PUBLIC LICENSE
> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
1. Do whatever you like with the original work, just don't be a dick.
Being a dick includes - but is not limited to - the following instances:
1a. Outright copyright infringement - Don't just copy this and change the name.
1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick.
1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick.
2. If you become rich through modifications, related works/services, or supporting the original work,
share the love. Only a dick would make loads off this work and not buy the original work's
creator(s) a pint.
3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes
you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.

47
MouseClicked.pde Normal file
View file

@ -0,0 +1,47 @@
void mouseClicked() {
//println(mouseX);
//println(mouseY);
//println(mouseButton);
//deseleziono ogni cella, trovo se ce n era una ancora cliccata e in tal caso salvo num riga e col
if(mouseButton == 37){ //clic sinistro{
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
if(celle[r][c].isSelezionata()){
UCS.setR(r);
UCS.setC(c);
UCS.setSelezionata(true);
}
celle[r][c].setSelezionata(false);
}
}
//inverto lo stato di selezionata della cella cliccata, se era già selezionata la deseleziono
int rigaSel = floor(mouseX / (lato/cellePerLato));
int colonnaSel = floor(mouseY / (lato/cellePerLato));
if(rigaSel == UCS.getR() && colonnaSel == UCS.getC() && !UCS.isSelezionata()){
celle[rigaSel][colonnaSel].setSelezionata(true);
UCS.setSelezionata(true);
//println("riseleziono");
}else if(rigaSel == UCS.getR() && colonnaSel == UCS.getC()){
celle[rigaSel][colonnaSel].setSelezionata(false);
UCS.setSelezionata(false);
//println("deseleziono");
}else{
celle[rigaSel][colonnaSel].setSelezionata(true);
UCS.setSelezionata(true);
//println("seleziono");
}
UCS.setR(rigaSel);
UCS.setC(colonnaSel);
}
else if (mouseButton == 39){
//trovo la cella selezionata
int rigaSel = floor(mouseX / (lato/cellePerLato));
int colonnaSel = floor(mouseY / (lato/cellePerLato));
celle[rigaSel][colonnaSel].toggleFissa();
}
}

54
README.md Normal file
View file

@ -0,0 +1,54 @@
# SudoSolver
## Description
A simple sudoku solver in processing 3
## Instructions
- select any cell with left click, move with arrows
- pres Del to delete any cell content
- press R to solve the sudoku
- the algorithm prevent you to insert a number in a wrong cell
Start with an empty map.
Write some number into the map.
![Scheme](images/main.png)
Press R
![Scheme](images/resolv.png)
Good work!
## Executables
You can find the executables for windows and linux, arm architecture supported: [releases](https://gitlab.com/stefanorossiti/sudosolver/-/releases).
### Executables Requirements
- [Java 7](https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html)
## Development Requirement
[Processing 3.1+](https://processing.org/download/) (best) until 3.5.4 should be fine.
## Installation and run
Download processing 3
run it in the IDE
This is a Processing 3 Project. You need the Pframe library to compile and run the code.
- [PFrame](https://github.com/shigeodayo/PFrame)
Extract the library in a separate folder into sketchbook libraries folder:
- Default libraries folder: `<user>\Documents\Processing\libraries`. If it doesn't exist, create it.
## License
All my work is released under [DBAD](https://www.dbad-license.org/) license

97
SudoSolver.pde Normal file
View file

@ -0,0 +1,97 @@
import g4p_controls.*;
int lato = 450; //lato della finestra (quadrato)
int cellePerLato = 9; //quante celle ha un lato
Cella[][] celle = new Cella[cellePerLato][cellePerLato];
Cella UCS = new Cella(0, 0, lato/cellePerLato);; // per riferimento all Ultima Cella Selezionata
void setup() {
println(dataPath(""));
//chiamo il metodo per il cambio di icona e del titolo
frameAndIcon("|SudoSolver| Powered by Stefano BBC Rossi",dataPath("") + "\\me.jpg");
size(450, 450); // Size must be the first statement
//width(displayWidth);
//height(displayHeight);
surface.setSize(width + 5, height + 5);
frameRate(30);
//frame.setResizable(true);
//creo array bidim di celle chiamato tabella
creaCelle();
}
void draw() {
background(255);
//lato = width;
//frame.setSize(lato, lato);
stampaTabella();
stampaCelle();
stampaWarning();
stampaNumCelle();
}
private void stampaWarning(){
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
fill(celle[r][c].getWarningColor()); //rosso in strasparenza
rect(celle[r][c].getX() + 7, celle[r][c].getY() + 7, celle[r][c].getL() -9, celle[r][c].getL() - 9, 10);
}
}
}
private void stampaNumCelle(){
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
if(celle[r][c].getN() != 0){
fill(celle[r][c].getColN());
textSize(celle[r][c].getPntFontN());
text(str(celle[r][c].getN()), celle[r][c].getX() + 21, celle[r][c].getY() + 37);
}
}
}
}
private void stampaCelle(){
noStroke();
for(int r = 0; r < cellePerLato; r++){
for(int c = 0; c < cellePerLato; c++){
//se la cella è fissa stampo uno sfondo più grigio
if(celle[r][c].isFissa()){
fill(100, 0, 0, 40); //grigio
rect(celle[r][c].getX() + 3, celle[r][c].getY() + 3, celle[r][c].getL(), celle[r][c].getL());
}
if(celle[r][c].isSelezionata()){
fill(celle[r][c].getColCella()); //Azzutto
rect(celle[r][c].getX() + 13, celle[r][c].getY() + 13, celle[r][c].getL() - 20, celle[r][c].getL() - 20, 8);
}else{
noFill();
rect(celle[r][c].getX() + 13, celle[r][c].getY() + 13, celle[r][c].getL() - 20, celle[r][c].getL() - 20, 8);
}
}
}
}
private void stampaTabella(){
stroke(0);
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++){
if (j == 0 || j == 3 || j == 6 || j == 9){
if (i == 0 || i == 3 || i == 6 || i == 9) strokeWeight(5);
else strokeWeight(1);
}
else strokeWeight(1);
line(0, (lato/cellePerLato) * i + 2, lato, (lato/cellePerLato) * i + 2);
if (i == 0 || i == 3 || i == 6 || i == 9) strokeWeight(5);
else strokeWeight(1);
line((lato/cellePerLato) * i + 2, 0, (lato/cellePerLato) * i + 2, lato + 2);
}
}
}

BIN
data/me.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
images/main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
images/resolv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB