Links und Funktionen
Sprachumschaltung

Navigationspfad
Sie sind hier: Startseite / Lehre / WS 2017/18 / Einführung in die Programmierung / Material / Magisch.java (fertig)


Inhaltsbereich

Magisch.java (fertig)

Magische Quadrate, funktionierende Version aus der Vorlesung am 28.11.17

Java source code icon Magisch.java — Java source code, 5 KB (5221 bytes)

Dateiinhalt

/**
 *  Demonstration zu Schleifen in Java.
 *  Überprüft, ob ein quadratisches 2D Array
 *  ein magisches Quadrat ist.
 *
 *  Live erstellt in der Vorlesung
 *    "Einführung in die Programmierung mit Java"
 *  am 23.11. und 28.11.2017 an der LMU München.
 *
 *  @author mhofmann, jost
 */

public class Magisch {
  private static final int SPALTENBREITE = 3;

  public static void main(String[] args) {
    int[][][] tests = {
            { {16,  3,  2, 13},
              { 5, 10, 11,  8},
              { 9,  6,  7, 12},
              { 4, 15, 14,  1}},
            { {16,  2,  3, 13},
              { 5, 10, 11,  8},
              { 9,  6,  7, 12},
              { 4, 15, 14,  1}},
            { {10,  8,  8,  8},
              { 8,  8, 10,  8},
              { 8,  8,  8, 10},
              { 8, 10,  8,  8}}
    };

    for (int[][] square : tests) {
      System.out.println("Test: " + ausgeben(square));
      System.out.println("Ergebnis: " + magisch(square));
    }

    // Hier noch ein paar Tests, um zu sehen,
    // das wir wirklich richtig rechnen:
    System.out.println("====================");
    int[][] square = tests[0];
    System.out.println(ausgeben(square));
    int[] zeile2 = zeile(2, square);
    System.out.print("Zeile 2:" + ausgeben(new int[][] {zeile2}));
    int[] spalte1 = spalte(1,square);
    System.out.print("Spalte 1:" + ausgeben(new int[][] {spalte1}));
    int[] diag1 = diag1(square);
    System.out.print("Diagonale 1:" + ausgeben(new int[][] {diag1}));
    int[] diag2 = diag2(square);
    System.out.print("Diagonale 2:" + ausgeben(new int[][] {diag2}));
  }

  public static boolean magisch(int[][] square) {
    /* Wir nehmen zur Vereinfachung quadratisches Format an */
    int n = square.length;
    int zielsumme = n * (n * n + 1) / 2;
    boolean vorangegangeneTestsOkay = true; // meldeten alle vorherigen Test true zurück?
    // Idee: wir ermitteln zuerst Zeile/Spalte/Diagonale und summieren diese jeweils in gleicher Weise auf.
    vorangegangeneTestsOkay = vorangegangeneTestsOkay && eintraegeKorrekt(square);
    for (int j = 0; j < n; j++) {
      vorangegangeneTestsOkay = vorangegangeneTestsOkay && (zielsumme == summe(zeile(j, square)));
    }
    for (int i = 0; i < n; i++) {
      vorangegangeneTestsOkay = vorangegangeneTestsOkay && (zielsumme == summe(spalte(i, square)));
    }
    vorangegangeneTestsOkay = vorangegangeneTestsOkay && (zielsumme == summe(diag1(square)));
    vorangegangeneTestsOkay = vorangegangeneTestsOkay && (zielsumme == summe(diag2(square)));
    return vorangegangeneTestsOkay;
  }

  private static String ausgeben(int[][] square) {
    String result = System.lineSeparator();
    for (int zeile=0; zeile<square.length; zeile++){
      for (int spalte=0; spalte<square[zeile].length; spalte++){
        // Formatierung wie in 4.45. Alternative siehe Folie 2.27.
        String iteZahl = " " + square[zeile][spalte];
        while(iteZahl.length() <= SPALTENBREITE){
          iteZahl = " " + iteZahl;
        }
        result = result + iteZahl;
      }
      result = result + System.lineSeparator();
    }
    return result;
  }

  static int[] zeile(int zeile, int[][] square) {
    // Gefährlich: Empfänger könnte mit Ergebnis square verändern!
    // Wir müssen also sicherstellen, dass wir nie schreibend darauf zugreifen!
    return square[zeile];
    // Normalerweise sollte man hier defensiv kopieren, also
    // eine Kopie des Arrays zurückgeben.
  }

  static int[] spalte(int spalte, int[][] square) {
    int[] result = new int[square.length]; // liefert neues Array zurück!
    for (int zeile = 0; zeile < square.length; zeile++){
      result[zeile] = square[zeile][spalte];
    }
    return result;
  }

  static int[] diag1(int[][] square) {
    int[] result = new int[square.length];
    for (int index = 0; index < square.length; index++){
      result[index] = square[index][index];
    }
    return result;
  }

  static int[] diag2(int[][] square) {
    int[] result = new int[square.length];
    for (int index = 0; index < square.length; index++){
      result[index] = square[index][square.length - index - 1];
    }
    return result;
  }

  /**
   * Summiert ein Array auf.
   * @param data zu summierende Daten
   * @return Summe von data
   */
  static int summe(int[] data) {
    int summe = 0;
    for (int elem : data){
      summe += elem;
    }
    return summe;
  }

  /* pruefen ob genau die Zahlen 1..n^2 drinstehen*/
  static boolean eintraegeKorrekt(int[][] square) {
    boolean bisNokay = true;
    for (int n = 1; n <= square.length * square.length && bisNokay; n++) {
      boolean nGefunden = false;
      for (int zeile=0; zeile < square.length && !nGefunden; zeile++){
        for (int spalte=0; spalte < square[zeile].length && !nGefunden; spalte++) {
//        nGefunden = nGefunden || n == square[zeile][spalte];
//        Da wir die Schleife bei nGefunden==true abbrechen, reicht hier auch:
          nGefunden = n == square[zeile][spalte];
        }
      }
//    bisNokay = bisNokay && nGefunden;
//    Da wegen der Schleifenbedingung im Schleifenrumpf bisNokay==true gelten muss, reicht hier auch:
      bisNokay = nGefunden;
    }
    return bisNokay;
  }
}

Artikelaktionen


Funktionsleiste