Logeleien - Rätsel wie aus dem Buch

"Wenn Sie weiterlesen und zur Rätselseite wollen, bezahlen Sie bitte € -,60!" - So starrte mich neulich eine Internet-Seite an, als ich nach Logikrätseln suchte. Neben tausend anderen Gedanken schoss mir durch den Kopf:"... dann mache ich mir halt selbst eins!" Und ich fand heraus, dass das Erstellen eines solchen Logicals, von mir für meine Javascript-Spielesammlung umgetauft in Logelei, genausoviel Spaß macht wie eins zu lösen.

Inhalt


Entwicklung der Katzen-Logelei

Was ist eine Logelei?

Logeleien lassen sich für's Web mit wenig Aufwand erstellen. Man braucht eine nette Geschichte, in der es um 4 bis 6 Objekte und Personen geht, und die nicht zu deutlich darstellt, in welchem Zusammenhang diese Obkjekte stehen. Mit diese spärlichen Hinweisen muss der Leser nun die Zusammenhänge herausfinden.



zum Seitenanfang
zum Seitenende




Vorarbeiten auf Papier

Diese Art Rätsel erfordern viel Vorplanung. Zweckmäßigerweise erstellt man sich als erstes auf Papier eine Tabelle, die den Zusammenhang der Objekte darstellt, etwa so:

Revier:Katzenname:Fellfarbe:Baum:Futter:
obenMauzigetigertBucheBrekkies
obere MitteSaschaschildpattEscheThunfisch
untere MitteMinkasilberKirscheEdelfisch
untenPeterschwarzBirkeHuhn
Der nächste Schritt ist das Erstellen eine Liste mit Hinweisen, die nicht zu deutlich sind. Ich schreibe zum Beispiel nicht: "Die rote Katze liebt Thunfisch" sondern: "Die schwarze Katze mag keinen Thunfisch." Manchmal bin ich noch fieser und velange Fachkenntnisse: "Keiner der Cichliden bekam Mückenlarven." Und ganz gemein bin ich, wenn ich die Hinweise nicht in der Liste, sondern in der Geschichte verstecke :-) - Im nächsten Durchgang, immer noch auf Papier, teste ich, ob mit den Hinweisen alle Zuweisungen gefunden werden können, gleichzeitig prüfe ich, ob ein Hinweis zu deutlich oder gar überflüssig ist. Der wird dann abgeändert oder fliegt ganz raus.



zum Seitenanfang
zum Seitenende




Elemente für die Seite

Damit die Seite einladend aussieht, erstelle ich eine nette Grafik zu dem gewählten Thema. Die Geschichte schreibt sich dann in einem Zug fast wie von selbst, daran schließt sich die Liste mit den Hinweisen an, die in der Katzenlogelei etwa so aussieht:

Nun, wo habe die Katzen ihre Reviere, auf welchen Bäumen sitzen sie? - Wie sehen sie aus, und was fressen sie am liebsten?

Zuletzt folgt eine Formulareingabe mit select-Feldern, in dem die Antwort eingetragen werden kann, und einem Link zum Abschicken -fertig ist der HTML-Teil der Hauptseite. Da sich die Eingaben hier wiederholen, lasse ich diesen Teil mit Javascript schreiben.


<form name="form1" action="dummy" onsubmit="return false">
<script type="text/javascript" language="javascript">
  document.writeln(auswahltabelle());
</script>
</form>

Um die Formularelemente ansprechen zu können, bekommt das Formular sowie alle Elemente Namen. Bei action gebe ich irgendwas ein, was nicht notwendigerweise existieren muss, onsubmit="return false" verhindert, dass die action ausgeführt wird.

Was wäre nun, wenn ich action und onsubmit einfach weglasse? Im IE ist die Welt noch in Ordnung, ebenso scheint in späteren Netscape-Versionen alles ok zu sein. Andere Browser hingegen verweigern das Auslesen der Formularelemente.

Und was soll die lange Zeile bei der Einbindung von Javascript? - HTML3.2 braucht language="javascript", um zwischen Jscript und Javascript unterscheiden zu können, HTML4 besteht auf type="text/javascript". Also wird beides eingebaut, nach W3C werden unbekannte Elemente ignoriert.



zum Seitenanfang
zum Seitenende




Javascript: globale Variable, von Logelei zu Logelei verschieden

Dieser Teil soll leicht und einfach für andere Logeleien umgebaut werden können, also versuchen wir, die functions so allgemein wie möglich zu halten. Die Javascript-Teile der Logeleien werden sich nur in bestimmten Daten, die im Kopfteil global definiert werden, unterscheiden. Eventuell werden die functions in einer allgemeinen Bibliothek ausgelagert, wahrscheinlich bei der 4. oder 5. zu erstellenden Logelei.

Im Kopfteil werden also die Kategorien und deren Anzahl festgelegt sowie deren möglichen Werte. Geschicktes Vorgehen und genaue Protokollierung erleichtern später das Erstellen der Module.

// --- Dimensionierungen der Logelei:
n_kategorien=4;
n_auswahlen=4;

// --- eine Kategorie wird fest zugeordnet:
k_name='Revier';
var k_fest=new Array('oben','obere Mitte','untere Mitte','unten');

// --- Name der variablen Kategorien:
var k_vari =new Array('Name','Fell','Baum','Futter');

// --- Auswahl in den Kategorien hintereinander weg:
// --- Kategorie 1: Wahlmöglichkeiten,
// --- Kategorie 2: Wahlmöglichkeiten ...
var k_daten =new Array('Mauzi','Minka','Peter','Sascha',
                       'silber','schildpatt','getigert','schwarz',
                       'Birke','Buche','Esche','Kirsche',
                       'Brekkies','Edelfisch','Huhn','Thunfisch');

// --- die Reihenfolge der korrekten Auswahl:
// --- Kategorie 1: korrekte Wahl 1, Kat.2: Wahl 1, Kat.3: Wahl 1,
// --- Kategorie 1: korrekte Wahl 2, Kat.2: Wahl 2, Kat.3: Wahl 2, ...
var k_ok   =new Array(1,4,2,3, 3,2,1,4, 2,3,4,1, 1,4,2,3);

In dem Rätsel wird im Lösungsschema die Position der ersten Kategorie festgelegt. n_kategorien gibt die Anzahl der restlichen Kategorien an, n_auswahlen ist dann die Anzahl der Katzen, Hunde, Fische, oder um was sich die Geschichte gerade rankt. Die Kategorienamen werden im Fall der festen Kategorie in eine Variable, im Fall der variablen in ein Array abgelegt, die Inhalte je in ein Array. k_daten enthält hintereinanderweg die vorhandenen Werte. Aufpassen muss man nun bei dem Lösungs-Array k_ok. Die Vierergruppen, in denen die Arrays k_daten und k_ok aufgeteilt sind, helfen, die Übersicht zu behalten. Sie stehen in Beziehung mit dem Aufbau des Formulars, dessen select-Namensgebung genau dieselbe Reihenfolge einhalten muss wie das k_ok-Feld, d.h. das select-Element mit der 0 im Namen hat als korrekte Lösung das k_ok-Element mit dem Index 0, das mit der 1 im Namen das k_ok-Element mit dem Index 1 u.s.w. - Die Kommentare geben an, in welcher Reihenfolge die Lösungswerte hier einzutragen sind.

Ab hier kann die Logelei-Bibliothek eingebunden werden, die im nächsten Abschnitt besprochen wird.



zum Seitenanfang
zum Seitenende




Javascript- Logelei-Bibliothek

Erstellen des select-Teils des Lösungsformulars

Bei diesen Arbeiten muss ich an eine alte Zeichnung denken, wo ein Ägypter eine Wand mit gleichartigen Schriftzeichen vollmeisselte, und der Boss hinter ihm meinte: "Gibt es denn keine andere Möglichkeit, zu schreiben: der Pharao hatte 10 000 Krieger?" In DHTML gibt es sie gottseidank:

// --- Schreiben der Auswahltabelle,
// --- so dass das Aussehen der 1.Zeile der Dreiecksmatrix entspricht:
// --------------------------------------------------------------------
function auswahltabelle()
{ var i,i1,i2,j,k=0,t='<table align="center"><tr><td> </td>';
  for (i=0; i<n_kategorien; i++) t=t+'<td align="center">'+k_vari[i]+'</td>';
  t=t+'</tr>';
  for (i=0; i<n_auswahlen; i++)
  { t=t+'<tr><td>'+k_fest[i]+':</td>';
    for (j=0; j<n_kategorien; j++)
    { t=t+'<td><select name="p_'+k+'" size="1">';
      t=t+'<option value=0 selected> unbekannt</option>';
      i2=j*n_auswahlen; // --- Startindex der jeweiligen Auswahl in k_daten
      for (i1=0; i1<n_auswahlen; i1++)
           t=t+'<option value='+(i1+1)+'>'+k_daten[i1+i2]+'</option>';
      t=t+'</select></td>';
      k++;
    }
    t=t+'</tr>';
  }
  t=t+'</table>';
  return t;
}

Das Lösungsfeld wird genauso erstellt wie in der Plan-Tabelle angegeben. Die Auswahlfelder erhalten die entsprechenden Daten aus dem Array k_daten, es wird ihnen zusätzlich eine Auswahl "unbekannt"vorangestellt, die vorselektiert ist, damit der Betrachter sieht, welchen Wert er noch nicht bestimmt hat. Die Namen der Auswahlfelder enthalten die Laufnummer k, die mit 0 initialisiert wird und je geschriebenes Auswahlfeld um 1 hochgezählt wird. Die Optionen für die Auswahlfelder selbst beginnen in k_daten selbst für jede Kategorie bei n_auswahlen*Kategorielaufzahl. Abgesehen von dem Select-Namen sind die Auswahl-Zellen einer Spalte identisch, so dass wir uns um die Formatierung der Auswahlfelder keine Gedanken zu machen brauchen.



zum Seitenanfang
zum Seitenende




Prüfen der Auswahlfelder

Diese function tut nichts weiter, als der Reihe nach die Werte der gewählten Select-Elemente zu bestimmen und mit dem Lösungsvektor (Array) k_ok zu vergleichen.

// --- Auswertung der select-Formfelder:
function ab_die_post()
{ var i,j,my_object,korrekt=1;
  for (i=0; i<k_ok.length; i++)
  { my_object=document.form1.elements['p_'+i];
    j=my_object.selectedIndex;
    if (k_ok[i]!=my_object[j].value) korrekt=0;
  }
  var win2=window.open('k_auswert.htm?richtig='+korrekt,
                       'popup','width=600,height=320,scrollbars=yes');
}
Die Variable korrekt ist dabei ein Schalter, der mit 1 initialisiert wird und bei Auftreten eines falschen Wertes auf 0 gesetzt wird. Die Auswahlen selbst werden angesprochen durch document.form1.elements[selectname], dieser wird in der i-Schleife dynamisch erzeugt. Damit dies nicht bei jedem Zugriff geschieht, wird das Element für die weitere Verwendung in die Variable my_object geschrieben. my_object ist danach ein Objekt-Array, das die Werte enthält. Die Eigenschaft selectedIndex gibt dann den Index der gewählten Option an, auslesen oder auch ändern kann man sie mit der Eigenschaft value.



zum Seitenanfang
zum Seitenende




Übergabe der Parameter an ein anderes Fenster und Auswertung

Die vorletzte Zeile im vorigen Abschnitt ruft ein Popup namens k_auswert.htm auf, dem mittels eines Parameterstrings, der mit ? an den Locator angefügt wird. Man könnte den String durch ein php-Modul o.ä. auswerden lassen. Weil php nur in Provider-Paketen für Profis dabei ist, machen wir weiter mit Javascript. Es geht, ist leider nur etwas umständlicher. Zunächst sei hier ein Ansatz quick and dirty genannt, der für die Übergabe eines einzigen Wertes an ein aufzurufendes Fenster durchaus geeignet ist. Der Parameterstring besteht dazu nur aus dem ?-Trenner und dem zu übermittelnden Wert:

 var win2=window.open('k_auswert.htm?'+korrekt);
auslesen ginge dann schlicht und einfach über:
  my_params=window.location.search;
  my_params=my_params.split('\?');
  my_wert=my_params[1];
- und fertig wäre die Laube.

Den Parameter-String erhält man in dem neuen Fenster mit my_params=window.location.search, dieser enthält jedoch noch das ?. my_params=my_params.split('\?'); splittet am Fragezeichen auf, man erhält ein Array, dessen erstes Element leer ist (der Teil vor ?) und den bereinigten Parameterstring. Programmierern, die mit Pascal angefangen haben, ist diese Syntax ein Greuel, es findet nämlich eine Typenkonversion statt: aus dem ursprünglichem String entsteht duch split ein Array, nach einiger Zeit hat man sich daran gewöhnt.

Warum steht der Backslash vor dem Fragezeichen? Das Fragezeichen ist ein Steuerzeichen im Parameterstring, muss somit maskiert werden. Auf diese Art wird richtig ausgewertet, egal, ob der String vom aufrufenden Fenster oder von händischer Eingabe erzeugt wird. Sonst kann es passieren, dass man mal auf ?, mal auf %26 oder noch gröberen Unfug prüfen muss.



zum Seitenanfang
zum Seitenende




Verfeinerung der function zum Auswerten des Parameter-Strings eines Fensters

Dieses Modul soll aber später mal mit in die Crossbrowser-Bibliothek, und bei Adventures gibt es mehrere Parameter zum Auslesen (vgl.Weinkeller). Also übt man schon mal für ein allgemeines Modul:

// --- Function für den Ende-Bildschirm,
// der seine Daten als Parameterstring erhält:

// --- Function zum Auslesen einer Variablen des Param-Strings:
function get_win_param(my_key)
{ var i,my_ppaare,my_wert;
  var my_params=window.location.search;

  // ? aus Parameterstring entfernen:
  my_params=my_params.split('\?');

  // Parameterstring zerteilen in einzelne Hashes:
  my_params=my_params[1].split('\&');

  // Hashes nach Key durchsuchen, den Wert abfangen:
  for (i=0; i<my_params.length; i++)
  { my_ppaare=my_params[i].split('\=');
    if (my_ppaare[0]==my_key) my_wert=my_ppaare[1];
  }
  return my_wert;
}

Der bereinigte Parameterstring wird zerlegt mittels my_params[1].split('\&'); in seine Parameterpaare, meist schlicht Hash-Array genannt. Jetzt müssen wir der Reihe nach noch die Schlüssel durchsuchen und die passenden Werte fischen. Dies geschieht mit my_ppaare=my_params[i].split('\='); my_ppaare[0] enthält den Schlüssel richtig, my_ppaare[1] dessen Wert (0 oder 1, je nach Intelligenz und Ausdauer des Anwenders).

Das Gegenstück im Ende-Fenster, das als Popup angelegt ist, gestaltet sich nun recht einfach:

<script type="text/javascript" language="javascript">
  if (get_win_param('richtig')==1)
       document.writeln('(Mi-)Jau, so isset gewesen!');
  else document.writeln('Hm, nun ja, nicht ganz, doch so beinahe!');
</script>

- Ach, was ist php da doch schön, das ganze Kapitel wird erschlagen mit in dieser einzigen Zeile: $my_wert=$$my_key;

Man könnte das Spiel jetzt testen und veröffentlichen, aber wer sich schon länger mit Logeleien befasst hat, kennt diese schönen Hilfsgitter. Selber zeichnen macht bei weitem nicht so viel Spaß wie selber lösen, also sollten wir diese Arbeit dem Anwender abnehmen. Ein Hilfsgitter, um die Beziehungen online einzutragen, oder zum Ausdrucken muss her.



zum Seitenanfang
zum Seitenende




Das Hilfsgitter

Planung: ein wenig Mathematik schadet nicht

Dieses Hilfsgitter soll die Beziehungen der Auswahlen je zweier Kategorien darstellen. Dieses Beziehungsfeld pro Kategoriepaar ist eine quadratische Matrix der Dimension n_auswahl*n_auswahl. Die Auswahlmöglichkeiten der einen Kategorie, z.B. Baum, sind horizontal angeordnet, die der anderen vertikal.

Trifft eine Aussage eindeutig zu, d.h. "Buche steht im obersten Revier", so wird die Zelle in der Spalte, in der "Buche" steht, und der Reihe, in der "oben" steht, mit einem Plus markiert. Trifft eine Aussage eindeutig nicht zu, d.h. "Kirsche steht nicht im untersten Revier", so wird die Zelle in der Spalte, in der "Buche" steht, und der Reihe, in der "oben" steht, mit einem Minus markiert. Das sähe dann so aus:

 ...BucheKirsche...
oben +  
Mitte    
unten  - 

Um alle 2er-Kombinationen der Kategorien darzustellen, ist eine Dreiecksmatrix in folgender Form geeignet, bei der sich die Kategorien in Zeilen und Spalten anordnen lassen:

Kat.1 x Kat.2 Kat.1 x Kat.3 Kat.1 x Kat.4
Kat.4 x Kat.2 Kat.4 x Kat.3
Kat.3 x Kat.2
Diese Überlegungen sollten reichen, um einen netten Ausdruck für das Rätsel zu ermöglichen.



zum Seitenanfang
zum Seitenende




Bildelemente des Hilfsgitters

Da der Bildwechsel in Javascript einfach und schnell ist, wenn man die Bilder vorläd (vgl. Making of Reversi), wenden wir ihn auch für die "online-Markierung" im Hilfsgitter an. Es gibt 3 Zustände, Plus, Minus und unbestimmt, also erstellen wir uns die 3 entsprechenden Grafiken. Der Zustand sollte von Undefiniert nach Minus nach Plus wechseln, dann wieder nach Undefiniert. Wir brauchen also noch ein Array, welches die Zustände protokolliert. Und wer oft solche Logeleien spielt, weiss, dass man sich da schon mal total vergaloppieren kann, also braucht man noch eine function, die alles resettet.


// --- Bilder vorladen:
var ima=new Array();
for (var i=0; i<3; i++)
{ ima[i]=new Image();
  ima[i].src='marke_'+i+'.gif';
}

// --- Feld zur Protokollierung der geklickten Auswahlen
var f=new Array();

// --- Reaktion auf Anklicken:
function klick(nr)
{ // --- 3 Zustände möglich, 0,1, und 2:
  f[nr]=++f[nr]%3;
  // --- Bildwechsel:
  document.images['i_'+nr].src=ima[f[nr]].src;
}

function resetten()
{ for (var i=0; i<f.length; i++)
  { f[i]=0;
    document.images['i_'+i].src=ima[0].src;
  }
}

Für die, die kein C gewohnt sind: ++f[nr] entspricht in etwa (f[nr]+1). Bei dieser Schreibweise sind Feinheiten zu beachten: x++ heisst: führe alles aus, dann zähle x eins hoch, ++x heisst: zähle x eins hoch, dann führe alles aus. f[nr]++%3 gibt also genauso falsche Ergebnisse wie (f[nr]++)%3.



zum Seitenanfang
zum Seitenende




Beschriftungen der Dreiecksmatrix

Da im Hinterkopf (hoffentlich) immer noch der Pharao mit den 10 000 Soldaten spukt, erzeugen wir den HTML-Code für diese Matrix wieder mit Javascript. Zunächst mal spart man Platz, wenn man die Spaltenüberschriften einzeilig macht. Das erledigt diese kleine function:


// --- Längsschrift für die Kategorien:
function laengsschrift(temp)
{ var cc,i=0,t='';
  do
  { t=t+temp.charAt(i);
    if (temp.charAt(i)=='&') // Entity
    { do
      { i++;
        cc=temp.charAt(i);
        t=t+cc;
      }
      while ((cc!=';') && (i<temp.length)); // Ende Entity oder String
    }
    if (i<temp.length-1) t=t+'<br>';
    i++;
  }
  while (i<temp.length);
  return t;
}

In temp wird die Zeichenkette übergeben, temp.length enhält deren Länge, die einzelnen Buchstaben werden mit temp.charAt(i) angesprochen, die neue Zeichenkette mit Zeilenumbrüchen nach jedem kompletten Buchstaben in t zusammengesetzt. Mit dieser function ist sichergestellt, dass die Grafik das breiteste Element der Spalte bleibt und kein Browser versucht, etwaige Spaltenbreitenvorgaben zu ignorieren.

Als erstes und einfachstes erstellen wir die Spaltenüberschriften, sie bestehen aus dem Kategoriennamen, der sich über n_anzahl Spalten erstreckt und den Auswahlmöglichkeiten:

  t='<table cellpadding=0 cellspacing=0 border=1><tr>';

// Hilfstext in die Tabellenzelle links oben, die sonst leer wäre:
  t=t+'<td rowspan="2">zum<br>Markieren<br>klicken:<br>';
  t=t+';<br>1x: -<br>2x: +<br>3x: leer</td>';

// --- obere Kategoriennamen, je einer in 5 Spalten,
// --- danach eine 2-zeilige Spalte zum Abtrennen, erhöht die Lesbarkeit:
  for (i=0; i<n_kategorien; i++)
  { t=t+'<td colspan="'+n_auswahlen+'">'+k_vari[i]+':</td>';
    t=t+'<td rowspan="2" class="trenner"> </td>';
  }
  t=t+'</tr>';

// --- Auswahlmöglichkeiten in Längsschrift,
// --- können hier noch hintereinanderweg geschrieben werden:
  t=t+'<tr>';
  for (i=0; i<k_daten.length; i++)
  { t=t+'<td valign="bottom" align="center" width="16">';
    t=t+laengsschrift(k_daten[i])+'</td>';
  }
  t=t+'</tr>';



zum Seitenanfang
zum Seitenende




Codierung der Dreiecksmatrix

Die nächste function ist etwas unübersichtlich, da versucht wird, aus Formatierungsgründen die Dreiecksmatrix samt ihrer quadratischen Untermatrizen in eine einzige Tabelle zu schreiben, so dass man nur oben und links die Kategorien mit ihren Auswahlmöglichkeiten angeben muss, und die Tabelleninhalte nicht "verrutschen".

Aber wenn man nach Plan vorgeht, so gelingt auch dieses. Und der Plan sieht erst mal so aus, gezeigt wird die Reihenfolge, wie die Felder geschrieben werden. Man sieht unten auch gleichzeitig, was passieren kann, wenn man anders vorgeht:

00010203
16171819
32333435
48495051
04050607
20212223
36373839
52535455
08091011
24252627
40414243
56575859
12131415
28293031
44454647
60616263
64656667
76777879
88899091
........
68697071
80818283
92939495
........
72737475
84858687
96979899
........
........
........
........
........
........
........
........
........
........
........
........
........


  // --- Erstellen der Dreiecksmatrix mit den inneren quadratischen Matrizen:

  // --- Index für die zu erstellenden Felder, Bildnamen, function-Parameter:
  k=0;

  for (j=0; j<n_kategorien; j++)
  {
    // --- Startindex der Auawahlmöglichkeiten innerhalb k_daten:
    startwert=(n_kategorien-j)*n_auswahlen;

    // --- Kategorienüberschrift linke Seite:
    t=t+'<tr><td class="trenner">';
    if (j==0) t=t+k_name; else t=t+k_vari[n_kategorien-j];

    // --- Schreiben einer Dreiecksmatrixzeile, Überschrift in Trennlinie:
    t=t+':</td><td colspan="'+(startwert+n_kategorien-j);
    t=t+'"class="trenner"> </td></tr>';

    // --- Dreiecksmatrixzeile, Auswahlwert:
    for (i=0; i<n_auswahlen; i++)
    { t=t+'<tr><td>';
      if (j==0) t=t+k_fest[i]; else t=t+k_daten[startwert+i];
      t=t+'</td>';

      // --- die restliche Tabellenzeile:
      for (i1=0; i1<n_kategorien-j; i1++)

      // --- eine Zeile der quadratische Matrizen:
      { for (i2=0; i2<n_auswahlen; i2++)
        { t=t+'<td><a href="javascript:klick('+k+')">';
          t=t+'<img src="marke_0.gif" width=16 height=16 alt="'+k;
          t=t+'" name="i_'+k+'" border=0></a></td>';
          f[k]=0;
          k++;
        }
        t=t+'<td class="trenner"> </td>';
      }

      t=t+'</tr>'; // --- Zeilenende
    }
  }

Die Dreiecksmatrix wird also erstellt mit dem Zeilenindex j, der von 0 bis n_kategorien-1 läuft, der Index i1 bedient die Spalten der Dreieckstabelle, er verringert sich jede Zeile um 1. Mathematisch ausgedrückt ist die Spaltenzahl einer bestimmten Reihe der Dreiecksmatrix dann n_kategorien - j.

Auch die Anordnung der Zuordnungen folgen einem bestimmten Schema, und zwar ist die letzte Spalten-Kategorie in der nächsten Zeile die Zeilen-Kategorie, mathematisch ist deren Index n_kategorien - j.

Eine Doppelschleife mit der Laufnummer i1 für die Dreiecksmatrixzeile und der Laufnumer i2 für die Zellen einer Zeile aus der quadratischen Untermatrix schreibt also die gesamte Dreiecksmatrixzeile.

Schwenkt da schon jemand die weisse Fahne? 5 Laufvariable zu kontrollieren ist kein Pappenstiel. Aber das ist jetzt alles, was wir an Mathematik brauchen. Die Untermatrixzellen bekommen ihren Inhalt in altgewohnter Weise, ein verweissensitive Image mit einem Namen, in dem die Reihenfolge der Erstellung zu erkennen ist (Laufvariable k), die function als Parameter die Laufvariable k, nach Erstellen einer solchen Einheit wird k um 1 erhöht.

Die gesamte Function nochmal auf einen Blick:


function gitter()
{ var i,i1,i2,j,k=0,startwert;
  var t='<table cellpadding=0 cellspacing=0 border=1><tr>';

// Hilfstext in die Tabellenzelle links oben, die sonst leer wäre:
  t=t+'<td rowspan="2">zum<br>Markieren<br>klicken:<br>';
  t=t+';<br>1x: -<br>2x: +<br>3x: leer</td>';

// --- obere Kategoriennamen, je einer in 5 Spalten,
// --- danach eine 2-zeilige Spalte zum Abtrennen, erhöht die Lesbarkeit:
  for (i=0; i<n_kategorien; i++)
  { t=t+'<td colspan="'+n_auswahlen+'">'+k_frage[i]+':</td>';
    t=t+'<td rowspan="2" class="trenner"> </td>';
  }
  t=t+'</tr>';

// --- Auswahlmöglichkeiten in Längsschrift,
// --- können hier noch hintereinanderweg geschrieben werden:
  t=t+'<tr>';
  for (i=0; i<k_daten.length; i++)
  { t=t+'<td valign="bottom" align="center" width="16">';
    t=t+laengsschrift(k_daten[i])+'</td>';
  }
  t=t+'</tr>';


  // --- Erstellen der Dreiecksmatrix mit den inneren quadratischen Matrizen:

  // --- Index für die zu erstellenden Felder, Bildnamen, function-Parameter:
  k=0;

  for (j=0; j<n_kategorien; j++)
  {
    // --- Startindex der Auawahlmöglichkeiten innerhalb k_daten:
    startwert=(n_kategorien-j)*n_auswahlen;

    // --- Kategorienüberschrift linke Seite:
    t=t+'<tr><td class="trenner">';
    if (j==0) t=t+k_name; else t=t+k_vari[n_kategorien-j];

    // --- Schreiben einer Dreiecksmatrixzeile, Überschrift in Trennlinie:
    t=t+':</td><td colspan="'+(startwert+n_kategorien-j);
    t=t+'"class="trenner"> </td></tr>';

    // --- Dreiecksmatrixzeile, Auswahlwert:
    for (i=0; i<n_auswahlen; i++)
    { t=t+'<tr><td>';
      if (j==0) t=t+k_fest[i]; else t=t+k_daten[startwert+i];
      t=t+'</td>';

      // --- die restliche Tabellenzeile:
      for (i1=0; i1<n_kategorien-j; i1++)

      // --- eine Zeile der quadratische Matrizen:
      { for (i2=0; i2<n_auswahlen; i2++)
        { t=t+'<td><a href="javascript:klick('+k+')">';
          t=t+'<img src="marke_0.gif" width=16 height=16 alt="'+k;
          t=t+'" name="i_'+k+'" border=0></a></td>';
          f[k]=0;
          k++;
        }
        t=t+'<td class="trenner"> </td>';
      }

      t=t+'</tr>'; // --- Zeilenende
    }
  }

  t=t+'</table>';
  return t;
}



zum Seitenanfang
zum Seitenende




Logelei-Bibliothek - Anwendungsbeispiel

Der Javascript-Teil, der für die Story spezifisch ist, packt man in eine Datei, z.B. k_logelei.js, den Teil, der für alle Logeleien gilt, in eine "Bibliotheksdatei", an der sich auch andere Logeleien bedienen können. Um Bibliotheksdateien von anderen Javascript-Dateien unterscheiden zu können, lasse ich deren Namen mit einem Unterstrich beginnen, so heisst diese _logelei.js. Sollten sich mal Spezifikationen ändern, so muss ich die Änderung nur in dieser Bibliothek durchführen statt 5 bis 50 Programme zu durchforsten.

Mit der Logelei-Bibliothek wurden die Katzen-, die Fische- und die Polizei-Logelei erstellt, weitere werden folgen, sobald mir wieder eine nette Geschichte dazu einfällt. Und findet man eine nette Logelei im Internet, die aber leider kein Hilfsgitter zur Verfügung stellt, so lässt sich durch "Klonen" und Anpassen der hilfsgitter.htm und der spezifisch.js schnell eins erstellen und ausdrucken:

Inhalt der hilfsgitter.htm

<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head><title>Logelei - Hilfsgitter</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<link rel="stylesheet" href="polizei.css">
<style type="text/css">
.trenner { background-color:#aabbaa; }
</style>
<script type="text/javascript" language="javascript" src="spezifisch.js"></script>
<script type="text/javascript" language="javascript" src="_logelei.js"></script>
</head>

<body>
<div align=center>

<script type="text/javascript" language="javascript">
  document.writeln(gitter());
</script>

<br clear=all>
<span class="button">
  <a href="javascript:resetten()"> Eingaben löschen </a>
</span><br clear=all><br>
<span class="button">
  <a href="javascript:window.close()">Fenster schließen</a></span>
<br clear=all>

</div>
</body>
</html>

Inhalt der spezifisch.js
// --- Logelei - Javascript-Teil --- uja 10/02  ---

n_kategorien=4;
n_auswahlen=6;
k_name='Zimmerfolge';

var k_fest =new Array('Zi.1','Zi.2','Zi.3','Zi.4','Zi.5','Zi.6');
var k_vari =new Array('Wissenschaftler','Lieblingsspiel','Haustier','Getränk');
var k_daten=new Array('Informatiker','Mathematiker','Physiker','Meteologe',
         'Wirtschaftsmathematiker','Bioinformatiker',
      'Go','Schach','Roborallye','Schafkopf','Roulette','Siedler',
      'Python,','Frosch','Windhund','Katze','Ratte','Schildkröte',
      'Kaffee','Wasser','Bier','Schnaps','Cola','Tee');

var k_ok   =new Array(1,2,1,1, 5,5,6,4, 4,2,2,4, 2,1,4,6, 3,3,3,3, 6,6,5,5);
// --- k_ok ist in für das Hilfsgitter allein ohne Bedeutung



zum Seitenanfang
zum Seitenende





zur Textauswahl
Gamecraft nachladen

©uja 2002 für www.gamecraft.de