Logo Banner
Navigation DeutschEnglish

Sliding Tiles Puzzle
Tic Tac Toe
Lights Out
Cool Stuff
Team - Misel
Team - LX
JS-Games FAQ


Memory − Misel

Source Code

General idea:
  1. Randomize image positions
  2. let user click on one card
  3. let him click on another card
  4. compare images
  5. if equal let them stay open, if not wait a moment and put them back
  6. Do that until all fields are uncovered

The program gets its settings by its window.name. Changes to the name are made in the form at the end.
<SCRIPT type="text/javascript"> var variable = window.name; if (variable=='') { var num_rows = 4; var num_columns = 4; } else {
The name consists of c for columns and the number directly behind it and r for rows and the according number. This part of the code "decrypts" the string and sets the preferences.
var temp1=variable.lastIndexOf("c"); var num_rows=variable.slice(1,temp1); var num_columns=variable.slice(temp1+1,variable.length); }
Assigments of all necessary global variables.
number of the shown cards
var num_fields=num_rows * num_columns;
number of image pairs
var num_pics=num_rows * num_columns/2;
number of already uncovered pairs
var opened_pics=0;
Is that the first click of the game?
var firstclick=0;
the image that is clicked on in each first move
var pic1;
the image that is clicked on in each second move
var pic2;
time of the beginning
var start_time;
time of the ending
var end_time;
toggles between first (0) and second (1) move
var firstimage=0;
the image ID of the last image that was clicked
var image_number;
the image ID of the pic in the first move.
var first_clicked_image=0;
the number of moves already done
var attempts=0;
variable that helps to prevent clicks before wrong pairs are covered again.
var allow_click=1;
The image that is displayed when a field is covered.
var covered=new Image; covered.src="covered.gif";
The following part defines the images. I made an array of image pairs. It's a little more difficult but also more flexible. This way I can define 2 different images as a pair. I originally made this game as an avatar quiz for the 3D Realms Bulletin Board and so a pair consisted of the nick and the avatar of a member (that's also the reason why each pair consists of nick and avatar).
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";
This array is the important thing "behind the scenes". It must be initialized at the beginning or it won't work.
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; }
The next part randomizes the image positions. The temp_numbers[] array is only there for simplicity. It would work with image_numbers[('M'+t)]["zahl"] as well.
var temp_numbers= new Array(); function init() {
for (var t=0; t < num_fields; t++) { temp_numbers[('M'+t)]=t; }
This algorithm gets a random number from the specified array. The trick is that it only changes the numbers within the image_numbers[] array and doesn't put new ones in and out and so the numbers and therefore the image-positions are mixed.
for (var t=0; t < num_fields; t++) { do { random_number = Math.round(Math.random() * (num_fields)); } while (random_number > (num_fields-1));
the changing part
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)]; } }
This function closes the the two pictures if the the pair doesn't match. It changes the status of the field back to 0 (uncovered), changes the images and allows clicks again.
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; }
Now we come to the core of the game, the "game engine" ;-). This is the function that reacts to the mouseclicks of the player. It uses 2 coordinates to estimate which card is clicked.
function look(x,y) {
The game starts when the player clicks on a field for the first time. It saves the start time and sets firstclick=1 so that the game knows that the game has started.
if (firstclick==0) { start_time=new Date(); firstclick=1; }
Translates the coordinates of the image into the image ID for the image-array and the image-changing function.
When it's the first click AND the image is not uncovered yet...
if ((firstimage==0) && (image_numbers[image_number]["status"]<10)) {
  • don't allow more clicks
  • tell the game that one image is now open
  • check which part of the pair is to display (only useful when using 2 different images as one pair)
  • set the field status so that the game knows that this field is uncovered
  • allow more clicks
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; }
When it's the second click AND the image is not uncovered yet ...
else if ((firstimage==1) && (image_numbers[image_number]["status"]<3)) {
  • don't allow more clicks
  • tell the game that one image is now open
  • check which part of the pair is to display (only useful when using 2 different images as one pair)
  • set the field status so that the game knows that this field is uncovered
  • check if the images belong together
  • if no cover them after half a second (500ms)
  • if yes:
    • increase the number of the already opened pairs
    • allow more clicks
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; }
If the number of the open pairs equals the number of all image pairs then get the ending time.
if (opened_pics==num_pics) end_time=new Date(); }
This calculates and displays the timespan after the player has won.
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!"); } }
The game code is complete now - except of what needs to be placed directly into the BODY.
The following code is for the different skill settings, where the rows and columns of the game will be stored.
var game;
This function defines the window name and refreshes the page to apply the new settings.
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>
Now to the part which belongs in the BODY.
<SCRIPT type="text/javascript">
initializes the game
This builds the actual game field. If clicks are allowed the onclick-function opens the look()-function with the coordinates of the current field.
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>
This is the form to change the game settings. The onclick-eventhandler is used here because one cannot use a javascript as the form's action.
<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>