Buch Cover Buch Cover Buch Cover Buch Cover

Web-Code: - Webcode Help

Sudoku (Datenstrukturen)

Schreiben Sie eine Datenstruktur (Klasse) Sudoku und ein separates Programm analog
dem Theoriebeispiel 'Kamel', das darauf die folgenden Methoden implementiert:

 

setzteZiffer(, , , )
leseZiffer(, , ): ): 
loescheZiffer(Sudoku>, , )
istGeloest() : boolean {
 return alleGefuellt() &&
 keinRegelVerstoss(); }

Ein Sudoku ist dabei eine Matrix bestehend aus 81 Feldern. Eine   ist dabei einfach ein Zeichen (char oder int). Die Methode alleGefuellt() prüft, ob alle Positionen im Sudoku-Rätsel bereits mit einer Ziffer gefüllt sind. Die Methode keinRegelverstoss() bringt in Erwägung, ob pro Zeile, pro Spalte und in jedem 3x3 Kästchen jede Ziffer von 1 bis 9 maximal einmal vorkommt. Testen Sie ihr Programm mit einem real existierenden Sudoku-Rätsel aus einer Zeitschrift. Zum Vergnügen und zum Testen können Sie freiwillig noch eine Methode angeben, hemes/advanced/langs/de.js" type="text/javascript"> die ein Sudoku mit print auf der Konsole ausgibt.

 

//TODO: Aufgaben zu Arrays von Referenzen. Z. B. Array fasst 100 Referenzen. Der User kann Personen-Objekte (Name, Vorname) erfassen und dieser werden dann in besagtem Array referenziert.

//TODO: Didaktische Reihenfolge prüfen:

0 Kommentare

Bitte melde dich an um einen Kommentar abzugeben

2 Lösung(en)

/**
 * sudoku (JavaScript)
 * Autor: phi@gressly.ch 
 * Kurs: Siemens Modul 307: April 2010
 */

function startSudoku() {
  var sudoku = initialisiereSudoku();
  loeseSudoku(sudoku);
}

function initialisiereSudoku() {
  sudoku = new Array(9); // 9 Spalten
  sudoku[0] = new Array(0, 8, 1, 0, 0, 0, 7, 3, 0);
  sudoku[1] = new Array(9, 0, 0, 2, 0, 8, 0, 0, 4);
  sudoku[2] = new Array(6, 0, 0, 0, 0, 0, 0, 0, 8);
  sudoku[3] = new Array(0, 3, 0, 7, 0, 1, 0, 2, 0);
  sudoku[4] = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0);
  sudoku[5] = new Array(0, 9, 0, 5, 0, 2, 0, 1, 0);
  sudoku[6] = new Array(8, 0, 0, 0, 0, 0, 0, 0, 7);
  sudoku[7] = new Array(7, 0, 0, 3, 0, 6, 0, 0, 1);
  sudoku[8] = new Array(0, 4, 5, 0, 0, 0, 6, 9, 0);
  return sudoku;
}

function loeseSudoku(sudoku) {
  if(istRegelVerletzt(sudoku)) { 
    return;
  }
  if(istVoll(sudoku)) {
    ausgabe(sudoku);
    return;
  }
  loeseRekursiv(sudoku);
}

/**
 * Erstelle neue einfachere Sudokus und löse diese mit obigem
 * "Algorithmus".
 */
function loeseRekursiv(sudoku) {
  var zeile  = findeErsteZeileMitLeereintraegen(sudoku);
  var ziffer = findeKleinsteUnbenutzteZifferInZeile(sudoku, zeile);
  var sudokus = erzeugeNeueSudokus(sudoku, zeile, ziffer);
  for(var i = 0; i < sudokus.length; i++) {
    loeseSudoku(sudokus[i]);
  }
}

/**
 * Ist eine der drei Sudoku-Reglen (zeile, spalte, block)
 * verletzt?
 */
function istRegelVerletzt(sudoku) {
  return istEineZeileVerletzt(sudoku)   ||
         istEineSpalteVerletzt(sudoku)  ||
         istEinBlockVerletzt(sudoku);
}

function istEineZeileVerletzt(sudoku) {
  for(var zeile = 0; zeile < 9; zeile++) {
    if(istZeileVerletzt(sudoku, zeile)) {
      return true;
    }
  }
  return false;
}

function istEineSpalteVerletzt(sudoku) {
  for(var spalte = 0; spalte < 9; spalte ++) {
    if(istSpalteVerletzt(sudoku, spalte)) {
      return true;
    }
  }
  return false;
}

function istEinBlockVerletzt(sudoku) {
  for(var xb = 0; xb <= 6; xb = xb + 3) {
    for(var yb = 0; yb <= 6; yb = yb + 3) {
      if(istBlockVerletzt(sudoku, xb, yb)) {
        return true;
      }
    }
  }
  return false;
}

function istZeileVerletzt(sudoku, zeile) {
  for(ziffer = 1; ziffer <= 9; ziffer ++) {
    if(vorkommenEinerZifferInZeile(sudoku, ziffer, zeile) > 1) {
      return true;
    }
  }
  return false;
}

/**
 * Wie oft kommt "ziffer" auf "zeile" vor?
 */
function vorkommenEinerZifferInZeile(sudoku, ziffer, zeile) {
  var vk = 0;
  for(var spalte = 0; spalte <= 8; spalte ++) {
    if(sudoku[spalte][zeile] == ziffer) {
      vk = vk + 1;
    }
  }
  return vk;
}

function istSpalteVerletzt(sudoku, spalte) {
  for(ziffer = 1; ziffer <= 9; ziffer ++) {
    if(vorkommenEinerZifferInSpalte(sudoku, ziffer, spalte) > 1) {
      return true;
    }
  }
  return false;
}

/**
 * Wie oft kommt "ziffer" in "spalte" vor?
 */
function vorkommenEinerZifferInSpalte(sudoku, ziffer, spalte) {
  var vk = 0;
  for(var zeile = 0; zeile <= 8; zeile ++) {
    if(sudoku[spalte][zeile] == ziffer) {
      vk = vk + 1;
    }
  }
  return vk;
}

function istBlockVerletzt(sudoku, xb, yb) {
  for(var ziffer = 1; ziffer <= 9; ziffer ++) {
    if(vorkommenInBlock(sudoku, xb, yb, ziffer) > 1) {
      return true;
    }
  }
  return false;
}

/**
 * Wie oft kommt "ziffer" im 3x3 Kästchen ab (xb, yb) vor?
 */
function vorkommenInBlock(sudoku, xb, yb, ziffer) {
  var vk = 0;
  for(var x = xb; x < xb + 3; x ++) {
    for(var y = yb; y < yb + 3; y++) {
      if(ziffer == sudoku[y][x]) {
        vk = vk + 1;
      }
    }
  }
  return vk;
}

/**
 * Sind alle Felder besetzt? 
 */
function istVoll(sudoku) {
  var total = 0;
  for(var zeile = 0; zeile <= 8; zeile ++) {
    for(var spalte = 0; spalte <= 8; spalte ++) {
      if(sudoku[spalte][zeile] > 0) {
        total = total + 1;
      }
    }
  }
  return 81 == total;
}

function ausgabe(sudoku) {
  var para = document.getElementById("ausgabe");
  var ausgabeString = "";
  for(var zeile = 0; zeile <= 8; zeile ++) {
    for(var spalte = 0; spalte <= 7; spalte ++) {
      ausgabeString += sudoku[spalte][zeile] + " | ";
      if(0 == (spalte + 1) % 3) {
        ausgabeString += "| ";
      }
    }
    ausgabeString += sudoku[8][zeile] + "<br />";
    if(0 == (zeile + 1) % 3) {
      ausgabeString += "---------------------------------------------<br />";
    }
  }
  para.innerHTML = ausgabeString;
}

/**
 * Suche die oberste Zeile, die noch nicht voll besetzt ist.
 */
function findeErsteZeileMitLeereintraegen(sudoku) {
  for(var zeile = 0; zeile <= 8; zeile++) {
    if(hatLeerEintragAufZeile(sudoku, zeile)) {
      return zeile;
    }
  }
}

function hatLeerEintragAufZeile(sudoku, zeile) {
  for(var spalte = 0; spalte <= 8; spalte ++) {
    if(0 == sudoku[spalte][zeile]) {
      return true;
    }
  }
}

function findeKleinsteUnbenutzteZifferInZeile(sudoku, zeile) {
  for(ziffer = 1; ziffer <= 9; ziffer++) {
    if(!kommtZifferAufZeileVor(sudoku, ziffer, zeile)) {
      return ziffer;
    }
  }
}

function kommtZifferAufZeileVor(sudoku, ziffer, zeile) {
  for(var spalte = 0; spalte <= 8; spalte ++) {
    if(ziffer == sudoku[spalte][zeile]) {
      return true;
    }
  }
  return false;
}

/**
 * Erzeuge für jedes freie Feld auf "zeile" ein neues
 * Sudoku mit "ziffer" anstelle des freien Feldes.
 */
function erzeugeNeueSudokus(sudoku, zeile, ziffer) {
  var plaetze = findeAnzahlFreiePlaetze(sudoku, zeile);
  var sudokus = new Array(plaetze);
  var pos = 0;
  for(var spalte = 0; spalte <= 8; spalte ++) {
    if(0 == sudoku[spalte][zeile]) {
      sudokus[pos++] = neuesSudoku(sudoku, zeile, spalte, ziffer);
    }
  }
  return sudokus;
}

/**
 * Wie viele Felder sind auf "zeile" noch frei?
 */
function findeAnzahlFreiePlaetze(sudoku, zeile) {
  var anz = 0;
  for(var spalte = 0; spalte <= 8; spalte++) {
    if(0 == sudoku[spalte][zeile]) {
      anz++;
    }
  }
  return anz;
}

/**
 * Erzeuge aus "sudoku" ein neues (Kopie), das an der Stelle
 * [spalte][zeile] die "ziffer" eingefüllt hat.
 * Alle anderen Werte werden einfach aus "sudoku" kopiert.
 */
function neuesSudoku(sudoku, zeile, spalte, ziffer) {
  var neuesSudoku = new Array(9);
  for(var sp = 0; sp <= 8; sp ++) {
    neuesSudoku[sp] = new Array(9);
    for(var ze = 0; ze <= 8; ze ++) {
      neuesSudoku[sp][ze] = sudoku[sp][ze];
    }
  }
  neuesSudoku[spalte][zeile] = ziffer;
  return neuesSudoku;
}

                
/*------------------------------------------------------*\
|  TODO:                                                 |
|  -- funktion zum setzen von möglichen zellwerten       |
|     (und automatischem lösen)                          |
|  -- kürzere notation für vorgegebene gitter            |
|  -- noch zwei komplett sinnlose todos einfügen         |
\*------------------------------------------------------*/

Array.prototype.hasDuplicates = function() {
  let arr = this.slice();
  // ausgenommen null-stellen
  arr = arr.filter(function(c) {
    return c != null;
  });
  return (new Set(arr)).size != arr.length;
}

let Sudoku = function(initArr) {
  let x, y;
  this.isFilled = false;
  this.isConsistent = false;
  this.isSolved = false;

  // hilfsfunktion für zentralfelder
  function getNeighbours(t, x, y) {
    let out = [];
    for (let i = x-1; i <= x+1; i++)
      for (let j = y-1; j <= y+1; j++)
        out.push(t.grid[i][j]);
    return out;
  }

  this.check = function() {
    /* ausgefüllt? */
    this.isFilled = true;
    for (let x = 0; x < this.grid.length; x++)
      for (let y = 0; y < this.grid.length; y++)
        if (this.grid[x][y] == null) this.isFilled = false;
    /* widerspruchsfrei? */
    // zeilen
    let r = true;
    for (x = 0; x < this.grid.length; x++)
      if (this.grid[x].hasDuplicates()) r = false;
    // spalten
    let c = true;
    for (y = 0; y < this.grid.length; y++) {
      buff = [];
      for (x = 0; x < this.grid.length; x++)
        buff.push(this.grid[x][y]);
      if (buff.hasDuplicates()) c = false;
    }
    // blocks
    let f = true;
    for (x of [
      [1, 1], [1, 4], [1, 7],
      [4, 1], [4, 4], [4, 7],
      [7, 1], [7, 4], [7, 7]
    ]) {
      buff = getNeighbours(this, x[0], x[1]);
      if (buff.hasDuplicates()) f = false;
    }
    /* auswertung */
    this.isConsistent = (r && c && f);
    this.isSolved = (this.isFilled && this.isConsistent);
    if (!this.isFilled) console.info('La sudoko ne jam estas plenita.');
    if (!this.isConsistent)
      console.warn('Duobla cifér en linio, kolón a? sekcio.');
    if (this.isSolved)
      alert('Elkoran gratulon,\nla sudók estas solvita!');
  }

  if (initArr) {
    for (x = 0; x < initArr.length; x++)
      for (y = 0; y < initArr.length; y++)
        if (initArr[x][y] == 0) initArr[x][y] = null;
    this.grid = initArr.slice();
    this.check();
  } else {  // leeres sudoku erstellen
    this.grid = new Array(9).fill(null);
    for (x = 0; x < this.grid.length; x++)
      this.grid[x] = new Array(9).fill(null);
  }

  this.print = function() { console.table(this.grid); }

  this.setCell = function(x, y, val) {
    this.grid[x][y] = val;
    this.check();
  }

  this.getCell = function(x, y) { return this.grid[x][y]; }

  this.delCell = function(x, y) { this.setCell(x, y, null); }
}

/*---------------------------*\
|  TEST 1                     |
|                             |
|  1 2 3   - - -   - - -      |
|  4 5 6   - - -   - - -      |
|  7 8 9   - - -   - - -      |
|                             |
|  - - -   - - -   - - -      |
|  - - -   - - -   - - -      |
|  - - -   - - -   - - -      |
|                             |
|  - - -   - - -   - - -      |
|  - - -   - - -   - - -      |
|  - - -   - - -   - - -      |
\*---------------------------*/
let s1 = new Sudoku();
for (let x of [
  [0, 0, 1], [0, 1, 2], [0, 2, 3],
  [1, 0, 4], [1, 1, 5], [1, 2, 6],
  [2, 0, 7], [2, 1, 8], [2, 2, 9],
]) s1.setCell(x[0], x[1], x[2]);

s1.setCell(3, 0, 1);  // gleiche zahl in gleicher spalte
s1.print();
s1.delCell(3, 0);

s1.setCell(0, 8, 1);  // gleiche zahl in gleicher reihe
s1.print();
s1.delCell(0, 8);

s1.setCell(1, 1, 1);  // gleiche zahl in gleicher zelle
s1.print();

/*--------------------------------------------------------------*\
|  TEST 2                                                        |
\*--------------------------------------------------------------*/
let s2 = new Sudoku([
  [4, 8, 7,   9, 2, 5,   6, 1, 3],
  [6, 9, 1,   7, 4, 3,   2, 5, 8],
  [5, 2, 3,   8, 6, 1,   4, 7, 9],

  [7, 4, 5,   2, 3, 9,   8, 6, 1],
  [9, 1, 2,   6, 0, 8,   5, 3, 4],  // zentralzelle noch unbelegt
  [8, 3, 6,   1, 5, 4,   9, 2, 7],

  [1, 7, 8,   5, 9, 2,   3, 4, 6],
  [2, 6, 4,   3, 8, 7,   1, 9, 5],
  [3, 5, 9,   4, 1, 6,   7, 8, 2]
]);
s2.print();

s2.setCell(4, 4, 7);
                

Lösung von: Lisa Salander (Heidi-Klum-Gymnasium Bottrop)

Aktionen

Bewertung

Durchschnittliche Bewertung:

Eigene Bewertung:
Bitte zuerst anmelden

Meta

Zeit: 2
Schwierigkeit: k.A.
Webcode: 2xx2-yfb2
Autor: Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch)

Zu Aufgabenblatt hinzufügen