Ausgabeprozeduren

Erstellen-Knopf

Der Erstellen-Knopf ruft der Reihe nach alle Prozeduren auf, die für das Erstellen, das Testen und die Ausgabe nötig sind. Diese Prozeduren werden später im Einzelnen erklärt.

Zunächst weist das Programm die eingegebenen Werte Variablen zu. Dann entscheidet es, welche Algorithmus das gewünschte Quadrat erzeugen soll. Dazu eignet sich

procedure TfrmCreateMagSquar.btnCreateClick(Sender: TObject);
begin
  val(edtsize.text,size,code);
  val(edtAdd.text,AddVal,code);
  val(edtMult.text,MultVal,code);
  case (Size mod 4) of
    0:createQuartMS;
    1,3:createoddms;
    2:createevenms;
  end;
  testmagsquare;
  if sqrmagic=true then
  begin
    GetMaxLength;
    getrotindex;
    MagSquareOutput;
  end
  else
  begin
    messagedlg('Der Algorithmus hat kein echtes Magisches Quadrat erzeugt.',mterror,[mbok],0);
  end;
end;

Die Funktion MultStr

Um zu gewährleisten, dass die Zahlen alle in einer Spalte stehen, müssen vor jede Zahl verschieden viele Leerzeichen geschrieben werden. Eine Funktion, die abhängig von den zu wiederholenden Zeichen und der Anzahl der Wiederholungen die Zeichenkette zurück gibt, sieht folgendermaßen aus:

function tfrmCreateMagsquar.MultStr(Character:String;Multiplicator:Word):String;

var
  resStr:String;
  c:Byte;

begin
  resstr:='';
  if (multiplicator>0) and (character<>'') then for c:=1 to multiplicator do resstr:=resstr+character;
  multstr:=resstr;
end;

Die GetMaxLength-Prozedur

Wenn man alle Zahlen des Magischen Quadrates in Spalten, durch Leerzeichen getrennt, ausgeben will, so muss man natürlich wissen, wie breit die Spalten sind. die Breite der Spalten hängt aber von der größten bzw. längsten Zahl ab. Deshalb muss man das Magische Quadrat durchgehen und nach der längsten Zahl suchen. Die folgende Prozedur gibt die Länge der längsten Zahl in einer Variable zurück.

Sobald die Prozedur eine Zahl entdeckt, deren Länge größer als das bisherige Maximum der Länge ist, so wird das alte Maximum mit dem neuen Maximum überschrieben. Zunächst wird davon ausgegangen, dass die längste Zahl, das Maximum, in dem Magischen Quadrat 0 Zeichen lang ist. Dadurch wird das Maximum schon bei der ersten Zelle überschrieben.

var
  MagSquare:Array[0..99{Spalten},0..99{Zeilen}Of Word;
  size,a{Spalte},b{Zeile}:byte;
  AddVal,MultVal:Longint;
  MaxLen:Byte;

procedure tfrmCreateMagsquar.GetMaxLength;

var
  len:Byte;

begin
  maxlen:=0;
  for a:=0 to size-1 do
  begin
    for b:=0 to size-1 do
    begin
      len:=length(inttostr(multval*magsquare[a,b]+addval));
      if len>maxlen then maxlen:=len;
    end;
  end;
end;

Die Output-Prozedur

Als erstes muss das Textfeld im Output-Fenster gelehrt werden, weil dort sonst die Magischen Quadrate nacheinander ausgegeben werden würden.

Danach geht die Prozedur das Array Zelle für Zelle durch. Da die Ausgabe nur in Zeilen erfolgen kann, müssen alle Zellen einer Zeile zusammen gefügt werden. Die Stringvariable line für die Zeile wird vorher immer geleert.

Je nach dem, wie gedreht und gespiegelt werden soll, bzw. welchen Wert RotationIndex hat, so werden andere Zellen in der Zeile ausgegeben.

RotationIndex  Koordinaten [a,b] 
0 [a,b]
1 [b,size-a-1]
2 [size-a-1,size-b-1]
3 [size-b-1,a]
4 [size-a-1,b]
5 [b,a]
6 [a,size-b-1]
7 [size-b-1,size-a-1]

Jede Zelle wird mit dem Faktor multipliziert, und zu jeder wird der Summand hinzuaddiert.

Vor jede Zelle kommen genau so viele Leerzeichen, wie bis zum längsten Element noch fehlen. Das ermöglicht die Ausgabe in gleich großen Spalten. Um zu verhindern, dass jede Zeile mit einem Leerzeichen beginnt wird das erste Zeichen immer gelöscht.

Die Variable line wird nach jeder Zeile zum Textfeld hinzugefügt.

Zum Schluss wird eine Mitteilung über die Größe der Seitensumme gebracht und das Ausgabe-Fenster angezeigt.

var
  MagSquare:Array[0..99{Spalten},0..99{Zeilen}] of Word;
  n:word;
  size,a{Spalte},b{Zeile}:byte;
  AddVal,MultVal:Longint;
  MaxLen:Byte;
  SqrMagic:Boolean;
  RotationIndex:Byte;
  Item:String;
  code:Integer;

procedure TfrmCreateMagSquar.MagSquareOutput;

var
  line:String;
  len:Byte;

begin
  frmOutput.memMagSquar.Lines.Clear;
  for b:=0 to size-1 do
  begin
    line:='';
    for a:=0 to size-1 do
    begin
      case rotationindex of
        0:str((Multval*magsquare[a,b]+addval):0,item);
        1:str((Multval*magsquare[b,size-a-1]+addval):0,item);
        2:str((Multval*magsquare[size-a-1,size-b-1]+addval):0,item);
        3:str((Multval*magsquare[size-b-1,a]+addval):0,item);
        4:str((Multval*magsquare[size-a-1,b]+addval):0,item);
        5:str((Multval*magsquare[b,a]+addval):0,item);
        6:str((Multval*magsquare[a,size-b-1]+addval):0,item);
        7:str((Multval*magsquare[size-b-1,size-a-1]+addval):0,item);
      end;
      line:=concat(line,multstr(' ',maxlen-length(item)+1),item);
    end;
    delete(line,1,1);
    frmOutput.memMagSquar.Lines.Add(Line);
  end;
  messagedlg('Die Seitensumme des Magischen Quadrates beträgt '+InttoStr((multval*Size*(Sqr(Size)+1) div 2)+size*addval)+'.',mtinformation,[mbOK],0);
  frmOutput.show;
end;