Banner
{ Deutsch | English }
Memory

Memory − Misel



Quellcode


Vorbetrachtung:
  1. Positionen der Bilder zufällig bestimmen
  2. Spieler auf eine Karte klicken lassen
  3. ihn auf eine weitere Karte klicken lassen
  4. Bilder vergleichen
  5. wenn sie gleich sind, bleiben sie aufgedeckt, ansonsten werden sie nach einer kurzen Pause wieder verdeckt
  6. wiederholen bis alle Karten aufgedeckt sind

Das Programm erhält seine Einstellungen via window.name. Änderungen daran werden im Formular am Ende getätigt.
<SCRIPT type="text/javascript"> var variable = window.name; if (variable=='') { var num_rows = 4; var num_columns = 4; } else {
Der Name besteht aus c für Spalten und der Zahl direkt dahinter und r für Zeilen und der zugehörigen Nummer. Dieser Abschnitt "entschlüsselt" die Zeichenkette und setzt die Spieleinstellungen.
var temp1=variable.lastIndexOf("c"); var num_rows=variable.slice(1,temp1); var num_columns=variable.slice(temp1+1,variable.length); }
Zuweisungen für die nötigen globalen Variablen.
Anzahl der angezeigten Karten
var num_fields=num_rows * num_columns;
Anzahl der Bildpaare
var num_pics=num_rows * num_columns/2;
Anzahl der bereits aufgedeckten Paare
var opened_pics=0;
Ist dies der erste Klick in diesem Spiel?
var firstclick=0;
das Bild, auf das in einem Zug als erstes geklickt wurde
var pic1;
das Bild, auf das in einem Zug als zweites geklickt wurde
var pic2;
Startzeit
var start_time;
Endzeit
var end_time;
wechselt zwischen dem ersten (0) und zweiten (1) Klick
var firstimage=0;
die Bild-ID des letzten Bildes, auf das geklickt wurde
var image_number;
die Bild-ID des Bildes, auf das zuerst geklickt wurde
var first_clicked_image=0;
die Anzahl der bereits benötigten Züge
var attempts=0;
Variable, die hilft zu verhindern, dass der Spieler in dem Zeitraum klickt, den falsche Karten noch aufgedeckt bleiben
var allow_click=1;
Das Bild, welches angezeigt wird, wenn eine Karte verdeckt ist.
var covered=new Image; covered.src="covered.gif";
Der folgende Abschnitt definiert die Bilder. Ich habe einen Array von Bildpaaren erstellt. Das ist zwar etwas schwieriger, aber auch flexibler. Auf diese Weise können auch 2 verschiedene Bilder als Paar definiert werden. Ich habe das Spiel ursprünglich als Avatar-Quiz für das 3D Realms Bulletin Board erstellt und ein Paar bestand aus dem Nickname und dem Avatar eines Mitglieds (das ist auch der Grund, weswegen jedes Paar aus nick und avatar besteht).
var bild=new Array(); bild[0]=new Array(2); bild[0]["nick"]=new Image; bild[0]["nick"].src="00.gif"; bild[0]["avatar"]=new Image; bild[0]["avatar"].src="00.gif"; . . . bild[17]=new Array(2); bild[17]["nick"]=new Image; bild[17]["nick"].src="17.gif"; bild[17]["avatar"]=new Image; bild[17]["avatar"].src="17.gif";
Dieser Array is das wichtigste "hinter den Kulissen". Er muss am Anfang initialisiert werden, ansonsten läuft das Spiel nicht.
var image_numbers = new Array(); for (var t=0; t < num_fields; t++) { image_numbers[('M'+t)]=new Array(); image_numbers[('M'+t)]["zahl"]=t; image_numbers[('M'+t)]["status"]=0; }
Der nächste Teil bestimmt die zufälligen Positionen der Karten. Der temp_numbers[]-Array existiert nur zur Vereinfachung. Es würde auch mit image_numbers[('M'+t)]["zahl"] funktionieren.
var temp_numbers= new Array(); function init() {
Initialisierung
for (var t=0; t < num_fields; t++) { temp_numbers[('M'+t)]=t; }
Dieser Algorithmus erzeugt eine Zufallszahl aus dem spezifizierten Array. Der Trick dabei ist, dass nur die Zahlen im image_numbers[]-Array ausgetauscht werden und nicht neue Zahlen ein- und aussortiert werden. Audf diese Weise werden die Zahlen und damit die Bilder gemischt.
for (var t=0; t < num_fields; t++) { do { random_number = Math.round(Math.random() * (num_fields)); } while (random_number > (num_fields-1));
der Austausch-Teil
var temp=temp_numbers[('M'+t)]; temp_numbers[('M'+t)]=temp_numbers[('M'+random_number)]; temp_numbers[('M'+random_number)]=temp; } for (t=0; t < num_fields; t++) { image_numbers[('M'+t)]["zahl"]=temp_numbers[('M'+t)]; } }
Diese Funktion verdeckt 2 Bildern, wenn sie kein Paar bilden. Sie ändert den Status des Feldes zurück auf 0 (verdeckt), ändert die Grafiken und erlaubt wieder Mausklicks.
function close(pic1,pic2) { window.document.images[pic1].src=covered.src; image_numbers[pic1]["status"]=0; window.document.images[pic2].src=covered.src; image_numbers[pic2]["status"]=0; allow_click=1; }
Nun kommen wir zum Kern des Spiels, der "Spielengine" ;-). Dies ist die Funktion, die auf die Mausklicks des Spielers reagiert. Es werden 2 Koordinaten benutzt um festzustellen, auf welche Karte geklickt wurde.
function look(x,y) {
Das Spiel startet, wenn der Spieler auf die erste Karte klickt. Der Zeitpunkt wird gespeichert und firstclick=1 gesetzt, sodass festgestellt wird, dass das Spiel begonnen hat.
if (firstclick==0) { start_time=new Date(); firstclick=1; }
Übersetzt die Koordinaten des Bildes in die Bild-ID für den Bilder-Array und die Bildwechsel-Funktion.
image_number='M'+(x*num_columns+y);
Wenn dies der erste Klick ist UND das Bild noch nicht aufgedeckt wurde...
if ((firstimage==0) && (image_numbers[image_number]["status"]<10)) {
  • erlaube keine weiteren Klicks
  • sage dem Spiel, dass eine Karte nun aufgedeckt ist
  • prüfe, welcher Teil eines Paares angezeigt werden soll (nur sinnvoll, wenn 2 verschiedene Bilder als ein Paar definiert werden)
  • setze den Feldstatus, sodass das Spiel weiß, welche Karte aufgedeckt wurde
  • erlaube weitere Klicks
allow_click=0; firstimage=1; pic1=Math.floor(image_numbers[image_number]["zahl"]/2); if ((image_numbers[image_number]["zahl"] % 2)==0) window.document.images[image_number].src=bild[pic1]["avatar"].src; else window.document.images[image_number].src=bild[pic1]["nick"].src; image_numbers[image_number]["status"]=10; first_clicked_image=image_number; allow_click=1; }
Wenn dies der zweite Klick ist UND das Bild noch nicht aufgedeckt wurde ...
else if ((firstimage==1) && (image_numbers[image_number]["status"]<3)) {
  • erlaube keine weiteren Klicks
  • sage dem Spiel, dass diese Karte nun aufgedeckt ist
  • prüfe, welcher Teil eines Paares angezeigt werden soll (nur sinnvoll, wenn 2 verschiedene Bilder als ein Paar definiert werden)
  • setze den Feldstatus, sodass das Spiel weiß, welche Karte aufgedeckt wurde
  • prüfe, ob die Bilder zusammengehören
  • wenn nicht, verdecke die Karten nach einer halben Sekunde (400ms) wieder
  • wenn doch:
    • erhöhe die Anzahl bereits geöffneter Paare
    • erlaube weitere Klicks
allow_click=0; firstimage=0; attempts++; pic2=Math.floor(image_numbers[image_number]["zahl"]/2); if ((image_numbers[image_number]["zahl"] % 2)==0) window.document.images[image_number].src=bild[pic2]["avatar"].src; else window.document.images[image_number].src=bild[pic2]["nick"].src; image_numbers[image_number]["status"]=10; if (pic1!=pic2) window.setTimeout("close(first_clicked_image,image_number)",500); else { opened_pics++; allow_click=1; }
Wenn die Anzahl der aufgedeckten Paare der Gesamtzahl der Paare entspricht, bestimme die Endzeit.
if (opened_pics==num_pics) end_time=new Date(); }
Hier wird die Zeitspanne berechnet und ausgegeben, in der der Spieler das Spiel gelöst hat.
if (opened_pics==num_pics) { var seconds=Math.floor(eval( ( (end_time.getTime() - start_time.getTime()) ) / 1000)); alert("Congratulations, you won the game in "+attempts+" turns and "+seconds+" seconds!"); } }
Der Code des Spiels ist jetzt komplett - mit Ausnahme der Teile, die in den BODY gehören.
Der folgende Code bestimmt die verschiedenen Schwierigkeitsgrade, in denen die Zeilen- und Spaltenanzahl abgelegt werden.
var game;
Diese Funktion setzt den Fensternamen und aktualisiert die Seite, um die geänderten Einstellungen zu übernehmen.
function loadmemory() { var start=0; if (document.spiel.settings[0].checked == true) { game="r4c4"; start=1; } if (document.spiel.settings[1].checked == true) { game="r4c6"; start=1; } if (document.spiel.settings[2].checked == true) { game="r6c6"; start=1; } window.name=game; location.reload(); } </SCRIPT>
Nun zu dem Teil, der in den BODY gehört.
<SCRIPT type="text/javascript">
initialisiert das Spiel
init();
Dieser Abschnitt erzeugt das Spielfeld. Wenn Klicks erlaubt werden, so ruft der onClick-Eventhandler die look()-Funktion mit den Koordinaten des aktuellen Feldes auf.
for (var i=0; i < num_rows; i++) { for (var j=0; j < num_columns; j++) { document.write('<IMG src="'+covered.src+'" onClick="if (allow_click==1) look('+i+','+j+')" name="M'+(i*num_columns+j)+'">'); } document.write('<BR>'); } </SCRIPT>
Dieses Formular ändert die Spieleinstellungen. Der onClick-Eventhandler wird hier benutzt, da kein JavaScript im action-Attribut des Formulars verwendet werden darf.
<FORM name="spiel" action=""> <INPUT type="radio" name="settings" id="s1" value="rookie"> <LABEL for="s1">Rookie</LABEL> <BR> <INPUT type="radio" name="settings" id="s2" value="advanced"> <LABEL for="s2">Advanced</LABEL> <BR> <INPUT type="radio" name="settings" id="s3" value="professional"> <LABEL for="s3">Professional</LABEL> <BR> <BR> <BR> <INPUT type="button" value="New Game" onClick="loadmemory()"> </FORM>