hei. jeg skal lage et program som forsøker å løse sudokubrett og som skriver løsningen ut til terminal. har begynt å implementere main men får så mange feilmeldinger, er det noen som vet va som er galt i min kode?
vedlagt er 3 ferdige klasser og den siste har jeg gjort selv.
[code][//**
* Klasse SudokuSolver
*
* Løser symmetriske (f.eks. (2x2 eller 3x3) Sudokubrett med hjelp av klassene
* Beholder, Region og Sudokubrett.
*/
public class SudokuSolver {
/**
* Størrelsen på brettet (f.eks. 9 i vanlig Sudoku). Dette vil
* være det samme tallet som antall mulige verdier i hver rute (f.eks. 1-9
* i vanlig Sudoku). Definieres av metoden initialiserRegioner().
*/
private int dimensjon;
/**
* Vi har tre typer regioner; rekker, søyler og kvadrater. I et vanlig
* Sudokubrett har vi 9 av hver type. Definieres av metoden
* initialiserRegioner().
*/
private Region[] rekke;
private Region[] soyle;
private Region[] kvadrat;
/**
* Etter at brukeren har valgt brett lagres id'en for det valgte brettet
* i denne variabelen.
*/
private int brettID;
/**
* Henter inn valgt brett og initialiserer alle regioner i brettet.
*/
private void initialiserRegioner() {
int[][] sudokuBrett = SudokuBrett.hentBrett(brettID);
dimensjon = sudokuBrett.length;
rekke = new Region[dimensjon];
soyle = new Region[dimensjon];
kvadrat = new Region[dimensjon];
for (int i = 0; i < dimensjon;i++) {
rekke
= new Region(dimensjon, sudokuBrett);
}
for (int i = 0; i < dimensjon;i++) {
soyle = new Region(dimensjon);
soyle.initSoyle(rekke, i);
}
for (int i = 0; i < dimensjon;i++) {
kvadrat = new Region(dimensjon);
kvadrat.initKvadrat(rekke, i);
}
}
// Implementer main
// Implementer printSudoku
// Implementer solveSudoku
}
]
[code][//**
* Klasse Region.
*
* Et objekt av typen Region tilsvarer en rekke, soyle eller kvadrat i Sudoku,
* og innholder en liste av Beholder-objekter som tilsvarer rutene i
* denne regionen. Lengden av denne listen er 9 i vanlig Sudoku.
*
* Klassen innholder metoder for å sjekke om det er mulig å oppdatere aktuell
* region, i forhold til lovlige eller ulovlige verdier for rutene i regionen.
*
* I en ferdig utfylt region (for eksempel en rekke) har alle ruter noyaktig en
* entydig verdi.
*/
public class Region {
/**
* Antall ruter i denne regionen (f.eks. 9 i vanlig Sudoku). Dette vil
* være det samme tallet som antall mulige verdier i hver rute (f.eks. 1-9
* i vanlig Sudoku).
*/
private final int dimensjon;
/**
* Kvadratroten av dimensjonen
*/
private final int dimensjonRot;
/**
* Liste av ruter i denne regionen. Husk at ruter er delt mellom regioner.
* For eksempel vil alle ruter i en rekke-region også være del av en
* soyle-region og en kvadrat-region. Dette er mulig ved bruk av referanser,
* slik at vi sparer både minnebruk og ender opp med mer ryddig og robust
* kode. For eksempel, unngår vi å måtte synkronisere rekke, soyle og
* kvadrat ved hver oppdatering.
*/
private Beholder[] ruter;
/**
* Konstruktor. Initialiserer en region uten å fylle ut tall i noen av rutene.
*
* @param dim dimensjon
*/
public Region(int dim) {
dimensjon = dim;
dimensjonRot = (int)Math.round(Math.sqrt(dimensjon));
ruter = new Beholder[dimensjon];
}
/**
* Konstruktor. Initialiserer region fra en tabell av verdier. Noen av
* verdiene i regionen kan være gitt på forhånd når en starter spillet.
*
* @param dim dimensjon
* @param tabell
*/
public Region(int dim, int[] tabell) {
dimensjon = dim;
dimensjonRot = (int)Math.round(Math.sqrt(dimensjon));
ruter = new Beholder[dimensjon];
for (int i = 0; i < dimensjon; i++){
ruter = new Beholder(dimensjon);
if (tabell != 0)
ruter.settVerdi(tabell - 1);
}
}
/**
* Initialiserer en enkelt soyle-region fra en liste av samtlige rekker.
*
* @param rekke liste av regioner (av "typen" rekke)
* @param soyleNr nummer på den som søyle som skal initialiseres
*/
public void initSoyle(Region[] rekke, int soyleNr) {
for (int i = 0; i < dimensjon; i++)
ruter = rekke.ruter[soyleNr]; // referanse
}
/**
* Initialiserer en enkelt kvadrat-region fra en liste av samtlige rekker.
*
* @param rekke liste av regioner (av "typen" rekke)
* @param kvadratNr nummer på den kvadrat som skal initialiseres
*/
public void initKvadrat(Region[] rekke, int kvadratNr) {
int startrekke = dimensjonRot * (kvadratNr / dimensjonRot);
int sluttrekke = startrekke + dimensjonRot;
int startsoyle = (dimensjonRot * kvadratNr) % dimensjon;
int sluttsoyle = startsoyle + dimensjonRot;
for (int i = startrekke; i < sluttrekke; i++)
for (int j = startsoyle; j < sluttsoyle; j++)
ruter[(i - startrekke) * dimensjonRot + (j - startsoyle)]
= rekke.ruter[j]; // referanse
}
/**
* Sjekker om det er mulig å foreta lovlige oppdateringer (forbedringer)
* i aktuell region. Målet ved hver oppdatering er å finne nye entydige
* tall i en eller flere av rutene.
*
* @return true hvis metoden har oppdatert regionen, false hvis det
* (i øyeblikket) ikke er mulig å foreta noen oppdateringer i
* denne regionen.
*/
public boolean sjekk() {
boolean p = false;
for (int i = 0; i < dimensjon; i++) {
if (ruter.erEntydig()) {
int j = ruter.hentVerdi();
p = oppdater(i,j) || p;
p = sjekkVerdi() || p;
}
}
return p;
}
/**
* Hvis vi har funnet en entydig verdi for en gitt rute (posisjon), bruker
* vi denne metoden til å sette verdien for den aktuelle ruten, og
* sette denne samme verdien som ulovlig for alle andre ruter i regionen.
*
* @return true hvis metoden har oppdatert regionen, false hvis det
* (i øyeblikket) ikke er mulig å foreta noen oppdateringer med
* denne metoden.
*/
private boolean oppdater(int pos, int v) {
boolean p = false;
for (int i = 0; i < dimensjon; i++) {
if (i != pos) {
p = ruter.settVerdiUlovlig(v) || p;
}
}
p = ruter[pos].settVerdi(v) || p;
return p;
}
/**
* Går gjennom samtlige mulige verdier og sjekker i hvor mange ruter de er
* lovlige. Hvis det for en gitt verdi kun er en mulig rute igjen, blir
* den aktuelle verdien lagret i den ruten.
*
* @return true hvis metoden har oppdatert regionen, false hvis det
* (i øyeblikket) ikke er mulig å foreta noen oppdateringer med
* denne metoden.
*/
private boolean sjekkVerdi() {
boolean p = false;
int[] lovligePosForVerdi = new int[dimensjon];
for (int i = 0; i < dimensjon; i++) {
for (int j = 0; j < dimensjon; j++) {
if (ruter.erLovlig(j)) {
lovligePosForVerdi[j]++;
}
}
}
for (int j = 0; j < dimensjon; j++) {
if (lovligePosForVerdi[j] == 1) {
for (int i = 0; i < dimensjon; i++) {
if (ruter.erLovlig(j)) {
p = ruter.settVerdi(j) || p;
}
}
} else if (lovligePosForVerdi[j] == 0) {
System.out.println("Feil: Ingen lovlige ruter for verdi " + j + "!!!");
}
}
return p;
}
/**
* Sjekk om en kun en verdi er lovlig for gitt rute i regionen.
*
* @param rute som skal sjekkes
* @return true hvis kun en verdi er lovlig, ellers false
*/
public boolean erEntydig(int ruteIndex) {
return ruter[ruteIndex].erEntydig();
}
/**
* Hent eventuell fastverdi i gitt rute i regionen.
*
* @param rute som skal sjekkes
* @return fastverdi hvis den er satt, ellers -1
*/
public int hentVerdi(int ruteIndex) {
return ruter[ruteIndex].hentVerdi();
}
/**
* Printer fastverdi for gitt rute til Standard Out hvis den er satt,
* ellers print '-'.
* Printer ikke linjeskift og returnerer ikke noe.
*
* @param rute som skal printes
*/
public void print(int ruteIndex) {
ruter[ruteIndex].print();
}
}
]
[code][/public class SudokuBrett {
private static final int[][][] brett =
{
{
{2,0,0,0}, // Meget lett
{0,1,0,4},
{4,0,1,0},
{0,0,0,2},
},
{
{4,0,0,1}, // Meget lett
{2,0,0,0},
{0,0,0,2},
{1,0,0,4},
},
{
{0,8,0,1,3,4,0,0,9}, // Lett
{0,0,0,0,0,5,7,1,0},
{0,3,2,6,0,0,4,0,0},
{5,1,0,9,8,2,3,0,0},
{0,0,0,4,0,0,1,5,8},
{6,0,0,5,0,0,0,7,0},
{0,0,9,3,0,1,2,4,6},
{0,2,6,0,9,8,0,0,0},
{0,0,1,0,4,6,8,0,0}
},
{
{3,0,0,0,0,7,0,0,0}, // Middels vanskelig
{0,8,0,0,0,0,0,3,0},
{0,9,6,0,0,4,0,1,0},
{0,0,0,0,0,9,5,0,0},
{0,0,2,6,7,0,0,0,0},
{4,0,0,0,0,0,1,0,0},
{0,0,0,7,8,0,0,0,0},
{0,4,1,0,0,0,0,6,2},
{0,6,9,0,0,0,0,0,0}
},
{
{0,0,6,8,0,9,0,0,0}, // Vanskelig
{0,0,4,0,0,6,0,2,0},
{0,0,9,0,0,0,0,0,5},
{0,3,0,0,7,0,0,0,2},
{1,5,0,0,0,0,7,0,0},
{0,0,0,0,1,0,3,0,0},
{0,0,0,0,0,0,0,5,7},
{0,0,0,2,3,0,0,0,8},
{4,8,1,0,0,0,0,0,0}
},
{
{9,0,0,0,0,1,0,0,5}, // Meget vanskelig. Løses ikke av metodene
{4,7,0,0,5,0,0,8,3}, // brukt i oblig 2.
{0,2,0,3,0,0,0,1,0},
{2,0,0,5,0,3,8,0,0},
{0,9,0,0,0,0,0,3,0},
{0,0,8,4,0,9,0,0,2},
{0,4,0,0,0,5,0,7,0},
{7,1,0,0,3,0,0,2,9},
{3,0,0,7,0,0,0,0,8}
}
};
public static int antallBrett() {
return brett.length;
}
public static int[][] hentBrett(int index) {
return brett[index];
}
}
]
[code][import java.util.Scanner;
/**
* Klasse SudokuSolver
*
* Løser symmetriske (f.eks. (2x2 eller 3x3) Sudokubrett med hjelp av klassene
* Beholder, Region og Sudokubrett.
*/
public class SudokuSolver {
public static void main(String[] args) {
/**
* Størrelsen på brettet (f.eks. 9 i vanlig Sudoku). Dette vil
* være det samme tallet som antall mulige verdier i hver rute (f.eks. 1-9
* i vanlig Sudoku). Definieres av metoden initialiserRegioner().
*/
private int dimensjon;
/**
* Vi har tre typer regioner; rekker, søyler og kvadrater. I et vanlig
* Sudokubrett har vi 9 av hver type. Definieres av metoden
* initialiserRegioner().
*/
private Region[] rekke;
private Region[] soyle;
private Region[] kvadrat;
/**
* Etter at brukeren har valgt brett lagres id'en for det valgte brettet
* i denne variabelen.
*/
private int brettID;
/**
* Henter inn valgt brett og initialiserer alle regioner i brettet.
*/
private void initialiserRegioner() {
int[][] sudokuBrett = SudokuBrett.hentBrett(brettID);
dimensjon = sudokuBrett.length;
rekke = new Region[dimensjon];
soyle = new Region[dimensjon];
kvadrat = new Region[dimensjon];
for (int i = 0; i < dimensjon;i++) {
rekke = new Region(dimensjon, sudokuBrett);
}
for (int i = 0; i < dimensjon;i++) {
soyle = new Region(dimensjon);
soyle.initSoyle(rekke, i);
}
for (int i = 0; i < dimensjon;i++) {
kvadrat = new Region(dimensjon);
kvadrat.initKvadrat(rekke, i);
}
}
//implementerer main
public static void main(String[] args) {
Scanner tastatur = new Scanner(System.in);
SudokuSolver sudoku = new SudokuSolver();
System.out.println("Det er " + SudokuBrett.antallBrett() + " tilgjengelige brett.");
do {
System.out.print("Oppgi index på ønsket brett (0-" + (SudokuBrett.antallBrett()-1) + "): ");
String stall = tastatur.next(); // Tar input fra tastaturet
try{
sudoku.brettID = Integer.parseInt(stall); // Prøver å konvertere til int
if(sudoku.brettID < 0 || sudoku.brettID >= SudokuBrett.antallBrett()) { // Gir beskjed hvis du gir et for lavt tall
System.out.println("Feil: Index må være mellom 0 og " + (SudokuBrett.antallBrett()-1));
System.out.println();
}
}
catch (NumberFormatException exception) { //Gir beskjed hvis input ikke kan konverteres til int
System.out.println("Feil: Inndata er ikke et heltall");
System.out.println();
}
} while (sudoku.brettID < 0 || sudoku.brettID >= SudokuBrett.antallBrett());
sudoku.initialiserRegioner();
sudoku.printSudoku();
sudoku.solveSudoku();
sudoku.printSudoku();
}
}
]
Indlæg senest redigeret d. 30.03.2007 08:58 af Bruger #11575