Asbjørn H Skrevet 27. mars 2007 Del Skrevet 27. mars 2007 (endret) Hei. Jeg tar førsteårsstudiumet i programmering ved UiB. Vi har fått en obligatorisk innlevering som går ut på å lage et sudoku-spill. Når jeg kjører programmet mitt får jeg en ganske sær utskrift. I stedet for to tall, som jeg egentlig vil ha, får jeg dette: Region@112f614 Region@1d9dc39 (Foreløpig har jeg bare prøvd å skrive ut innholdet i to ruter i sudokubrettet) Jeg kan ganske lite java, og skjønner ikke hva dette betyr. Er det en slags referanseverdi eller noe slikt som blir skrevet ut? Her er hvertfall koden: Klikk for å se/fjerne innholdet nedenfor /** * 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[i] = new Region(dimensjon, sudokuBrett[i]); } for (int i = 0; i < dimensjon;i++) { soyle[i] = new Region(dimensjon); soyle[i].initSoyle(rekke, i); } for (int i = 0; i < dimensjon;i++) { kvadrat[i] = new Region(dimensjon); kvadrat[i].initKvadrat(rekke, i); } } public static void main(String[] args) { Innleser innleser = new Innleser(); SudokuSolver sudokuSolver = new SudokuSolver(); System.out.println("Det er 6 tilgjengelige brett"); sudokuSolver.brettID = innleser.lesInnHeltall("Oppgi index på ønsket brett (0-5): ", "Feil: index må være et heltall i intervallet (0-5)."); sudokuSolver.initialiserRegioner(); sudokuSolver.printSudoku(); } private void printSudoku() { System.out.println(rekke[0]); System.out.println(soyle[0]); } Koden for SudokuBrett: Klikk for å se/fjerne innholdet nedenfor 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}, }, { {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} } //Her skal det være 4 sudokubrett til, men de har jeg utelatt for //å spare dere for masse lesning... }; public static int antallBrett() { return brett.length; } public static int[][] hentBrett(int index) { return brett[index]; } } Koden for Region: Klikk for å se/fjerne innholdet nedenfor /** * 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[i] = new Beholder(dimensjon); if (tabell[i] != 0) ruter[i].settVerdi(tabell[i] - 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[i] = rekke[i].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[i].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[i].erEntydig()) { int j = ruter[i].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[i].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[i].erLovlig(j)) { lovligePosForVerdi[j]++; } } } for (int j = 0; j < dimensjon; j++) { if (lovligePosForVerdi[j] == 1) { for (int i = 0; i < dimensjon; i++) { if (ruter[i].erLovlig(j)) { p = ruter[i].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(); } } Klassen Beholder, som det refereres til i Region, er det ikke så mye vits i å gjengi tror jeg. Beholder-objektene er bare "beholdere" for tall, altså et tall per Beholder-objekt. Metoden settVerdi fastsetter verdien til det aktuelle Beholder-objektet. Mesteparten av dette har vi fått utdelt. Det eneste jeg har skrevet selv er main-metoden og printSudoku-metoden. Jeg har prøvd å sette meg inn i hvordan programmet fungerer, men jeg skjønner ganske lite av det... Håper virkelig noen kan hjelpe meg med dette før førstkommende fredag, hvis ikke er det fare for at jeg ikke får tatt eksamen i faget, og stryker... Endret 27. mars 2007 av Asbjørn H Lenke til kommentar
___ Skrevet 27. mars 2007 Del Skrevet 27. mars 2007 Verdiene du får ut er objektreferansene til rekke[0] og soyle[0]. Dette fordi println ikke har noen snøring på hvordan sudokudiagrammer ser ut. Siden du ikke har tatt deg bryet med å komme med all koden din, kan du heller ikke forvente særlig mer konstruktive svar enn det du får av meg. Werner Lenke til kommentar
Asbjørn H Skrevet 27. mars 2007 Forfatter Del Skrevet 27. mars 2007 (endret) Takk for svar. Siden du spør så pent skal jeg ta meg "bryet" (jeg unnlot bare å legge ut ekstra kode for å spare deg for masse lesning)med å legge ut koden til Beholder.java: Klikk for å se/fjerne innholdet nedenfor /** * Klassen Beholder holder orden pa mulige verdier for * en gitt posisjon i en permutasjon der noen, men ikke alle * verdier er bestemt allerede. */ public class Beholder { /** * Antall mulige verdier i denne beholderen (f.eks. 9 i vanlig Sudoku). */ private final int dimensjon; /** * Tabell med en plass for hver mulig verdi. True hvis verdien er lovlig, * ellers false. Eks: Hvis posisjon 3 i denne tabellen er true, er 3 en * lovlig verdi for denne beholderen. * NB! Tabellen starter paa posisjon 0! Siste posisjon (største mulige * tallet) er altså N-1. */ private boolean[] lovligeVerdier; /** * Antall lovlige verdier for denne beholderen. Er i begynnelsen samme som * dimensjonen, men minker etter hvert som tall blir plassert andre steder i * permutasjonen (f.eks. en rekke eller søyle i Sudoku). */ private int antallLovlige; /** * Naar kun en lovlig verdi for beholderen gjenstaar (antallLovlige == 1) * lagres verdien i denne variabelen. * Tilsvarer aa fylle ut et tall i sudoku-brettet. */ private int fastVerdi; /** * Konstruktor * * @param dimensjon antall mulige verdier for denne beholderen */ public Beholder(int dim) { dimensjon = dim; lovligeVerdier = new boolean[dimensjon]; antallLovlige = dimensjon; for (int i = 0; i < dimensjon; i++) lovligeVerdier[i] = true; } /** * Sett en fastverdi for denne beholderen. Samtidig settes alle andre * verdier som ulovlige. Tilsvarer å fylle ut et tall i Sudoko. * * @param nyVerdi ny verdi som skal settes som fastverdi * @return true hvis operationen var vellykket, ellers false */ public boolean settVerdi(int nyVerdi) { if (lovligeVerdier[nyVerdi]) { if (antallLovlige > 1) { antallLovlige = 1; for (int i = 0; i < dimensjon; i++) lovligeVerdier[i] = false; lovligeVerdier[nyVerdi] = true; fastVerdi = nyVerdi; return true; } else return false; } else { return false; } } /** * Setter en verdi som ulovlig for denne beholderen. Så sjekkes det om kun en * lovlig verdi gjenstaar, i så fall blir fastVerdi satt til den verdien. * * @param verdi verdi som skal settes som ulovlig * @return true hvis operasjonen var vellykket, ellers false */ public boolean settVerdiUlovlig(int verdi) { if (lovligeVerdier[verdi]) { lovligeVerdier[verdi] = false; antallLovlige--; if (antallLovlige == 1) { int i; for (i = 0; !lovligeVerdier[i] && i < dimensjon; i++); fastVerdi = i; } if (antallLovlige == 0) { System.out.println("FEIL: ingen lovlige verdier igjen for denne beholderen!"); return false; } return true; } else return false; } /** * Sjekk om en gitt verdi er lovlig for denne beholderen. * * @param verdi verdi som skal sjekkes * @return true hvis verdien er lovlig, ellers false */ public boolean erLovlig(int verdi) { return lovligeVerdier[verdi]; } /** * Sjekk om en kun en verdi er lovlig for denne beholderen (og fastVerdi * derfor må være satt). * * @return true hvis kun en verdi er lovlig, ellers false */ public boolean erEntydig() { return (antallLovlige == 1); } /** * Hent eventuell fastverdi. * * @return fastverdi hvis den er satt, ellers -1 */ public int hentVerdi() { if (antallLovlige == 1) { return fastVerdi; } else return -1; } /** * Printer fastverdi til Standard Out hvis den er satt, ellers print '-'. * Printer ikke linjeskift og returnerer ikke noe. */ public void print() { if (antallLovlige == 1) System.out.print(fastVerdi + 1); else System.out.print("-"); } } Endret 27. mars 2007 av Asbjørn H Lenke til kommentar
___ Skrevet 27. mars 2007 Del Skrevet 27. mars 2007 ...hvilket fremdeles ikke er nok, da klassen Innleser mangler Werner Lenke til kommentar
Asbjørn H Skrevet 27. mars 2007 Forfatter Del Skrevet 27. mars 2007 (endret) Edit: fikk hjelp av en venn av en venn av meg, som løste problemet... Men takk for hjelpen allikevel Endret 27. mars 2007 av Asbjørn H Lenke til kommentar
BlueJSucks Skrevet 24. juni 2007 Del Skrevet 24. juni 2007 Tips: Skal du skrive ut tekstlig informasjon om et objekt må du ha med en toString()-metode! Lag alltid en egen toString()-metode i klasser du instansierer objekter fra. Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå