Buch Cover Buch Cover Buch Cover Buch Cover

Web-Code: - Webcode Help

Bimaru (Datenstrukturen)

Ein Bimaruspiel (Battleship oder Marinespiel) ist eine Art Schiffeversenken. Das Spielfeld ist eine quadratische Matrix. Die Schiffe darin haben alle die Breite Eins (1 Feld) und die Längen 1, 2, 3 bzw. 4 Felder. Wir bezeichnen die Schiffe daher auch Einer, Zweier, Dreier oder Vierer. Ein Schiff der Länge 3 hat also 3 Schiffsteile und nimmt 3 aneinanderliegende Quadrätchen in Anspruch. Schiffe berühren sich dabei nicht, auch nicht diagonal. Das heißt, die Schiffe sind komplett von Wasser umgeben. Beim Lösen eines Bimaru ist rechts (bzw. unten) pro Zeile (bzw. Spalte) angegeben, wie viele Schiffsteile total vorkommen. Einige Schiffsteile sind dabei manchmal schon vorgegeben. Dabei sieht man jeweils, ob es sich um ein Schiffsanfang oder -ende oder um eine Schiffsmitte handelt. In anderen Feldern ist vorgegeben, dass es sich um Wasser (also nicht um einen Schiffsteil) handelt. Weiter ist vorgegeben, wie viele Schiffe von welcher Länge (welchen Typs) total vorkommen. (Ob das hier abgebildete Bimaru lösbar ist, ist nicht Inhalt dieser Aufgabe).

< img src="../uploads/eximage-1d88f6.JPG" alt="" width="242" height="344" />

Schreiben Sie eine Datenstruktur, die ein (noch ungelöstes) Bimaru wie oben speichern kann. Schreiben Sie zudem ein Programm, das die einzelnen Informationen beschreiben, bzw lesen kann. Dabei ist eine Position (feld) immer durch einen der folgenden Werte bestimmt:

 

String feld = …
  "unbestimmt"   : Dieses Feld ist noch nicht gelöst.
  "Wasser"       : An dieser Position befindet sich sicher kein
                   Schiff.
  "Schiffsmitte" : hier ist ein Schiffsteil, jedoch kein
                   Schiffsende
                   weder Bug noch Heck (Quadrat).
  "Einzelschiff" : Schiff bestehend aus nur einer Zelle (Kreis).
  "Ende_Oben"    : Bug oder Heck oben
                   (wie im Bild 6. Zeile, 8. Spalte).
  "Ende_Unten"   : analog
  "Ende_Links"   : analog
  "Ende_Rechts"  : analog
  "Schiffsteil"  : An dieser Position befindet sich ein Teil
                   eines Schiffes (also kein Wasser), es ist
                   jedoch noch nicht bekannt, um welchen Typ
                   der obigen Definitionen es sich handeln
                   wird.

Definieren Sie die obigen nominalen Werte und schreiben Sie danach die folgenden Methoden (Dabei muss die Variable feld den entsprechenden nominalen Wert aufweisen).

 

 

setzeFeld(Bimaru b, int x, int y, String feld)
leseFeld (Bimaru b, int x, int y) : String
   -> x, y = SpaltenNummer, ZeilenNummer
setzeSchiffeProZeile (Bimaru b, int y, int anzahl)
setzeSchiffeProSpalte(Bimaru b, int x, int anzahl)
leseSchiffeProZeile (Bimaru b, int y) : int
leseSchiffeProSpalte (Bimaru b, int x) : int
   -> Das sind die am Rande aufgeführten Zahlen
setzeAnzahlSchiffe(Bimaru b, int typ, int anzahl)
leseAnzahlSchiffe (Bimaru b, int typ) : int
   -> typ: Einer, Zweier, Dreier oder Vierer (= Länge der Schiffe)
anzahl = Wie viele Schiffe des Typs sind total vorhanden.

 

Die "lese-" bzw. "setze"-Methoden werden im Englischen getter- bzw. setter-Methoden genannt.

Option: Ersetzen Sie "String" durch einen Enumerationstypen.

//TODO: Evtl. als Kleinprojekt formulieren, denn nur so, macht es vielleicht gar keinen Spaß.

0 Kommentare

Bitte melde dich an um einen Kommentar abzugeben

1 Lösung(en)

// TODO irgendwann:
// 1. verkürzung der zweiten und dritten abteilung
//    (ohne die lesbarkeit zu verschlechtern)
// 2. plausbilitätsüberprüfungen der eingaben

/*---------------------------------------------------*\
|  S T R U K T U R   E I N E R   P B N                |
|=====================================================|
|  PBN = Portable Bimaru Notation (hab ich mir        |
|  gerade ausgedacht)                                 |
|-----------------------------------------------------|
|  SYMBOLE der PBN-meerbeschreibung                   |
|      (leerzeichen) = ungelöstes feld                |
|    ~ = wasser                                       |
|    X = schiffsteil ohne erkennbares ende            |
|    O = einer                                        |
|    N = oberes schiffsende                           |
|    S = unteres schiffsende                          |
|    W = linkes schiffsende                           |
|    E = rechtes schiffsende                          |
|    x (zahl) = x leerfelder,                         |
|          leerfelder am rechten rand können          |
|          weggelassen werden                         |
|    . = leere zeile                                  |
|    / = ende einer zeile                             |
|-----------------------------------------------------|
|  Meerbeschreibung des aufgabenbeispiels:            |
|    ./8~/././6~/7N/3~/././.                          |
|=====================================================|
|  Eine PBN besteht aus 4 abteilungen, getrennt durch |
|  Semikola:                                          |
|    [meerbeschreibung];                              |
|    [schiffsanzahl letzte spalte];                   |
|    [schiffsanzahl letzte zeile];                    |
|    [anzahl der schiffstypen]                        |
|  wobei die letzten drei zahlengruppen sind,         |
|  getrennt durch leerzeichen.                        |
|=====================================================|
|  So der plan...                                     |
\*---------------------------------------------------*/

let Bimaru = function(size) {
  this.size = size;
  this.sea = [];
  // $sea initialisieren
  for (let x = 0; x <= this.size; x++) {
    this.sea[x] = new Array(this.size+1).fill(' ');
  }

  this.setField = function(x, y, item) {
    this.sea[x][y] = item;
  }
  this.getField = function(x, y) {
    return this.sea[x][y];
  }

  this.setShipsInRow = function(x, n) {
    this.sea[x][this.size] = n;
  }
  this.setShipsInCol = function(y, n) {
    this.sea[this.size][y] = n;
  }

  this.getShipsInRow = function(x) {
    return this.sea[x][this.size];
  }
  this.getShipsInCol = function(y) {
    return this.sea[this.size][y];
  }
  // statt setzeAnzahlSchiffe und leseAnzahlSchiffe
  // ... weil zu trivial:
  this.ships = [];  // [einer, zweier, dreier, vierer]

  this.toPBN = function() {
    let pbn = [];

    // erste abteilung:
    // meerbeschreibung
    let lines=[];
    for (let i = 0; i < this.size; i++) { // $sea zeilenweise lesen
      let line = '';
      for (let j = 0; j < this.size; j++) line += this.sea[i][j];
      lines.push(line);
    }
    for (i = 0; i < lines.length; i++) {
      lines[i] = lines[i].trimEnd().split('');
      if (lines[i].length == 0) lines[i] = '.';
      else {
        let str = '';
            count = 0;
        while (lines[i].length > 0) {
          let tmp = lines[i].shift();
          // leerfelder zählen
          if (tmp == ' ') count++;
          else {
            if (count > 0) {
              str += count + tmp;
              count = 0;
            } else str += tmp;
          }
        }
        lines[i] = str;
      }
    }
    pbn.push(lines.join('/'));

    // zweite und dritte abteilung:
    // schiffanzahl letzte spalte und letzte zeile
    let arrC = [], arrR = [];
    for (i = 0; i < this.size; i++) {
      arrC.push(this.getShipsInCol(i));
      arrR.push(this.getShipsInRow(i));
    }
    pbn.push(arrR.join(' '), arrC.join(' '));

    // vierte abteilung:
    // verwendete schiffe
    pbn.push(this.ships.join(' '));

    return pbn.join(';');
  }
}

function parsePBN(pbn) {
  pbn = pbn.split(';');

  // erste abteilung:
  // meerbeschreibung
  let div = pbn.shift();
  // das auszugebende bimaru
  let b = new Bimaru(div.split('/').length);

  div = div.split('');
  // eventuelle mehrstellige ziffern zusammenfassen
  for (let i = 0; i < div.length; i++)
    if (div[i] == '.') div.splice(i, 1);
    else if (!isNaN(div[i])) {
      let j = i + 1;
      while (!isNaN(div[j])) {
        div[i] += '' + div[j];
        div.splice(j, 1);
      }
    }
  let x = 0; y = 0;
  while (div.length > 0) {
    let tmp = div.shift();
    if (tmp == '/') { x++; y = 0; }
    else if (!isNaN(tmp)) y += parseInt(tmp);
    else b.setField(x, y, tmp);
  }

  // zweite und dritte abteilung:
  // anzahl der schiffe in letzter spalte und zeile
  let cols = pbn.shift().split(' '),
      rows = pbn.shift().split(' ');
  for (i = 0; i < b.size; i++) {
    b.setShipsInCol(i, cols[i]);
    b.setShipsInRow(i, rows[i]);
  }

  // vierte abteilung:
  // verwendete schiffstypen
  b.ships = pbn.shift().split(' ');

  return b;
}

/*---------*\
|  D E M O  |
\*---------*/

// händische eingabe des aufgabenbeispiels
let b1 = new Bimaru(10);
b1.setField(1, 8, '~'); b1.setField(4, 6, '~');
b1.setField(5, 7, 'N'); b1.setField(6, 3, '~');
let rows = '1 3 1 1 1 3 6 1 2 1'.split(' '),
    cols = '4 1 1 4 1 1 3 2 1 3'.split(' ');
for (let i = 0; i <= b1.size; i++) {
  b1.setShipsInRow(i, rows[i]);
  b1.setShipsInCol(i, cols[i]);
}
b1.ships = [4, 3, 2, 1];
console.table(b1.sea);
console.log(b1.ships);
console.log(b1.toPBN());

// erstellung eins bimaru per PBN
// beispiel nach https://de.wikipedia.org/wiki/Bimaru#/media/Datei:Bimaru_raetsel.gif
let desc = './7O/./4X/./././.;5 1 3 1 4 1 2 3;2 3 2 3 4 2 2 2;4 3 2 1';
let b2 = parsePBN(desc);
console.table(b2.sea);
console.log(b2.ships);                            //  lissalanda@gmx.at

                

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

Aktionen

Bewertung

Durchschnittliche Bewertung:

Eigene Bewertung:
Bitte zuerst anmelden

Meta

Zeit: 4.8
Schwierigkeit: k.A.
Webcode: myrw-tke4
Autor: Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch)

Download PDF

Download ZIP

Zu Aufgabenblatt hinzufügen