/* Program: JSudokuResolver | Class: Board
Copyright (C) 2014 Ruggiero Altini
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.ithsoft.sudoku;
/**
* <b>Classe</b> Board. <p>
* Questa classe definisce la tavola del Sudoku da risolvere.
* Per utilizzarla e' sufficiente dichiararne un'istanza e inserire come parametro un array di interi da 81 elementi
* <p>Sebbene il gioco del Sudoku sia formalmente quadrato, per motivi di semplicita', qui viene ridotto come una serie sola di numeri.
* E' possibile immettere valori nella tavola con il metodo push o toglierli con il metodo pop.
* @author Ruggiero Altini
* @version 1.0
*/
public class Board
{
/**
* Contiene tutti gli elementi della tavola di gioco
*/
public int[] elems;
/**
* Contiene la posizione degli elementi inizialmente vuoti (Attenzione:
* Questi sono gli elementi che il Resolver deve riempire, ma vengono
* definiti bianchi anche successivamente.
*/
public int[] pwhites;
/**
* Contiene gli elementi inizialmente vuoti che il Resolver deve riempire.
* Per questo motivo, la lunghezza di questo array e' minore di {@code elems}. <p>
* Per non perdere la posizione di questi elementi, nella variabile pwhites viene salvata la loro locazione
* nella tavola di gioco
* @see elems
*/
public int[] whites;
/**
* Contiene l'elemento di punta dello stack
*/
private int top;
/**
* Contiene il numero degli 0 inseriti nell'inizializzazione dell'oggetto
*/
private int blanks;
/**
* Contiene gli elementi massimi della griglia
*/
private final int size = 81;
/**
* Conta tutti i push effettuati, utile per verificare se e' difficile piu' un Sudoku o un altro
*/
private long pushes;
/**
* Conta tutti i pop effettuati, utile per verificare quante volte un programma "ritorna sui propri passi"
*/
private long pops;
/**
* Inizializza una tavola di gioco vuota
* @since 1.0
*/
public Board() {
int[] def = new int[size];
for(int e : def) e = 0;
elems = def;
initialize();
}
/**
* Inizializza una tavola di gioco sulla base dell'array.
* @param grid Array di numeri da prendere in input
* @since 1.0
*/
public Board(int[] grid)
{
elems = grid;
initialize();
}
/**
* <p>Il metodo {@code initialize} si occupa di inizializzare le variabili della tavola di gioco
* una volta creata. </p>
* In piu' qui vengono assegnate alla variabile {@code whites} gli 0 iniziali e alla variabile
* {@code pwhites} le rispettive posizioni.
* @since 1.0
*/
private void initialize()
{
blanks = 0;
pushes = 0;
pops = 0;
top = -1;
// Conta i bianchi (gli 0) presenti
for(int e : elems) if(e == 0) blanks++;
// Inizializza l'array con il numero di bianchi creato
whites = new int[blanks];
pwhites = new int[blanks];
int count = 0;
for(int i = 0; i < size; i++)
{
if(elems[i] == 0)
{ // Salva in pwhites le posizioni dei punti bianchi
whites[count] = 0;
pwhites[count] = i;
count++;
}
}
}
/**
* <p>La funzione {@code getPushes} restituisce il valore della variabile privata {@code pushes} (che si occupa di contare i push effettuati). </p>
* @return pushes
* @since 1.0
*/
public long getPushes()
{
return pushes;
}
/**
* <p>La funzione {@code getPops} restituisce il valore della variabile privata {@code pops} (che si occupa di contare i push effettuati). </p>
* @return pops
* @since 1.0
*/
public long getPops()
{
return pops;
}
/**
* <p>La funzione {@code getBlanks} restituisce il valore della variabile privata {@code blanks} (che contiene gli 0 iniziali). </p>
* @return blanks
* @since 1.0
*/
public int getBlanks()
{
return blanks;
}
/**
* <p>La funzione {@code getTop} restituisce il valore della variabile privata {@code top} (che contiene l'elemento di punta dello stack). </p>
* @return top
* @since 1.0
*/
public int getTop()
{
return top;
}
/**
* <p>La funzione {@code getSize} restituisce il valore della variabile privata {@code size} (che contiene il numero degli elementi della tavola). </p>
* @return size
* @since 1.0
*/
public int getSize()
{
return size;
}
/**
* <p>Il metodo {@code push} immette un valore nello stack. </p>
* @param value Questa variabile corrisponde al numero da aggiungere allo stack. Da precisare che questo numero e'
* inseribile senza previo controllo di legalita'.
* @since 1.0
*/
public void push(int value) // Mette un valore nello stack
{ // Verifica se lo stack e' pieno
if(top == blanks - 1)
System.
out.
println("Log: Griglia Piena!");
else
{
pushes++;
whites[++top] = value;
elems[pwhites[top]] = value;
}
}
/**
* <p>Il metodo {@code pop} rimuove un valore dallo stack. </p>
* @since 1.0
*/
public void pop() // Rimuove un valore dallo stack
{
if(top == -1) // Se la griglia e' vuota non fare niente
{
System.
out.
println("Log: Griglia vuota!");
}else // Altrimenti rimuovi un valore dallo stack
{
pops++;
whites[top] = 0;
elems[pwhites[top]] = 0;
top--;
}
}
/**
* <p>La funzione {@code toString} restituisce la griglia di gioco in maniera "quadrata", ovvero viene troncata ogni 9 elementi e mandata a capo.
*
* @since 1.0
*/
public String toString
() // Stampa la griglia
{
StringBuilder str = new StringBuilder();
int count = 0;
for(int i = 0; i < size; i++)
{
// Ogni tre numeri, dai uno spazio
if(i % 3 == 0 && i % 9 != 0) str.append(" ");
// La griglia e' in realta' una serie di interi, spezzala ogni 9
if(i % 9 == 0) str.append("\n");
// Ogni 3 file di numeri, manda due volte a capo per distanziare i blocchi
if(i % 27 == 0) str.append("\n\n");
// Dai uno spazio dopo il numero
str.append(elems[i] + " ");
count++;
}
str.append("\n");
return str.toString();
}
}