Banner
{ Deutsch | English }
Sliding Tiles Puzzle

Sliding Tiles Puzzle − LX



Source Code


This is neccessary, because all tiles are on a DIV and each tile has a size of 100×100 pixels.
<STYLE type="text/css"> div { width:100px; height:100px; } </STYLE>
Now to the actual script. At first the usual declarations for global variables.
<SCRIPT type="text/javascript">
the game field
var Spielfeld = new Array();
counters for loops
var i,j;
O is the position of a tile in pixels from the top, L the position in pixels from the left.
var O,L;
Those two variables are used for making the tiles slide in several steps, instead of just flipping on the empty space.
var blah,Funktion;
another counter
var Zaehler;
This variable is 1 when a move is over and 0 when a move is in progress (otherwise you could click on many tiles at once and would create a mess in sliding the tiles above each other, so now you can only slide one tile at once).
var fertig = 1;
This is an array with 2 elements which contains the position of the empty space. At the beginning it is 3 | 3.
var Feld = [3,3];
for checking if all the tiles are in the right order or not
var gewonnen;
An array for all the images. You can have several image sets for this game, so I store them all in an array.
var Bilder = new Array();
Initializes the graphics. i in this case stands for the number of the theme that is chosen. Depending on this number the images are either in GIF or in JPG format, this is also checked in this loop. blah in this case is the file extension.
for (i = 0; i < 5; i++) { if ((i == 3) || (i == 4)) blah = '.gif'; else blah = '.jpg'; Bilder[i] = new Array(); for (Zaehler = 0; Zaehler < 17; Zaehler++) { Bilder[i][Zaehler] = new Image; Bilder[i][Zaehler].src = i + '/' + (Zaehler + 1) + blah; } }
This function shuffles all the tiles by moving them around randomly. This is done because every situation should have a solution. If I'd just put all the tiles in random order there may be situations where you can't win the game.
'T33' is the lower right tile, the one that's taken out to create an empty space.
function mischen() { var dasselbe;
This part determines where the empty space is at the moment.
for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (Spielfeld[i][j] == 'T33') { Feld[0] = i; Feld[1] = j; } } }
In this case the computer makes 30 random moves to shuffle. You can also vary this number.
for (Zaehler = 0; Zaehler < 30; Zaehler++) {
Again the use of blah, this time as the container for a random number. I know it's sloppy to use the same variable for so many different purposes but JavaScript allows it... so who cares? ;)
Also note: dasselbe checks that the computer doesn't revert its own moves (that it doesn't slide back a tile it just moved).
blah = Math.random(); if ((dasselbe != 1) && (blah < 1/4) && (Feld[0] < 3)) { Spielfeld[(Feld[0])][(Feld[1])] = Spielfeld[(Feld[0] + 1)][(Feld[1])]; Spielfeld[(Feld[0] + 1)][(Feld[1])] = 'T33'; Feld[0]++; dasselbe = 0; } else if ((dasselbe != 0) && (blah < 1/2) && (Feld[0] > 0)) { Spielfeld[(Feld[0])][(Feld[1])] = Spielfeld[(Feld[0] - 1)][(Feld[1])]; Spielfeld[(Feld[0] - 1)][(Feld[1])] = 'T33'; Feld[0]--; dasselbe = 1; } else if ((dasselbe != 3) && (blah < 3/4) && (Feld[1] < 3)) { Spielfeld[(Feld[0])][(Feld[1])] = Spielfeld[(Feld[0])][(Feld[1] + 1)]; Spielfeld[(Feld[0])][(Feld[1] + 1)] = 'T33'; Feld[1]++; dasselbe = 2; } else if ((dasselbe != 2) && (Feld[1] > 0)) { Spielfeld[(Feld[0])][(Feld[1])] = Spielfeld[(Feld[0])][(Feld[1] - 1)]; Spielfeld[(Feld[0])][(Feld[1] - 1)] = 'T33'; Feld[1]--; dasselbe = 3; } else continue; }
This part adjusts the tiles in the right positions and hides the last tile.
for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { window.document.getElementById(Spielfeld[i][j]).style.top = eval(i * 100) + 'px'; window.document.getElementById(Spielfeld[i][j]).style.left = eval(j * 100) + 'px'; } } document.getElementById('T33').style.visibility = 'hidden'; }
To change the image set this function is called.
function ChangeTheme(Theme) { for (Zaehler = 0; Zaehler < 17; Zaehler++) { window.document.images[Zaehler].src = Bilder[Theme][Zaehler].src; } }
The usual initialization function called at the beginning. It writes the appropriate tiles into the Spielfeld array and calls the shuffle function afterwards.
function init() { for (i = 0; i < 4; i++) { Spielfeld[i] = new Array(); for (j = 0; j < 4; j++) { Spielfeld[i][j] = 'T' + i.toString() + j.toString(); } } mischen(); }
This function is for horizontal sliding of tiles. ID is the tile to be moved and Richtung defines if it's moved either to the right or to the left. The movement has 10 steps, each by 10 pixels.
function horizontal(ID,Richtung) { if (Zaehler < 10) { if (Richtung == 'l') document.getElementById(ID).style.left = parseInt(document.getElementById(ID).style.left) - 10 + 'px'; else document.getElementById(ID).style.left = parseInt(document.getElementById(ID).style.left) + 10 + 'px'; Zaehler++;
The function calls itself after 40 milliseconds to make the next step of the movement.
Funktion = "horizontal('" + ID + "','" + Richtung +"')"; blah = setTimeout(Funktion,40); } else fertig = 1; }
See horizontal but this time for vertical movement.
function vertikal(ID,Richtung) { if (Zaehler < 10) { if (Richtung == 'u') document.getElementById(ID).style.top = parseInt(document.getElementById(ID).style.top) - 10 + 'px'; else document.getElementById(ID).style.top = parseInt(document.getElementById(ID).style.top) + 10 + 'px'; Zaehler++; Funktion = "vertikal('" + ID + "','" + Richtung +"')"; blah = setTimeout(Funktion,40); } else fertig = 1; }
Now finally the function that is called when you click on a tile.
function move(ID) {
This part checks where the clicked tile is situated.
O = parseInt(document.getElementById(ID).style.top) / 100; L = parseInt(document.getElementById(ID).style.left) / 100;
This is for the sliding movement of the tile.
Zaehler = 0;
The following part checks if the empty space is somewhere next to the clicked tile and calls the appropriate function if this is the case. If not nothing happens and it just returns waiting for another click.
if ((O < 3) && (Spielfeld[O+1][L] == 'T33')) { vertikal(ID,'d'); Spielfeld[O+1][L] = Spielfeld[O][L]; } else if ((O > 0) && (Spielfeld[O-1][L] == 'T33')) { vertikal(ID,'u'); Spielfeld[O-1][L] = Spielfeld[O][L]; } else if ((L < 3) && (Spielfeld[O][L+1] == 'T33')) { horizontal(ID,'r'); Spielfeld[O][L+1] = Spielfeld[O][L]; } else if ((L > 0) && (Spielfeld[O][L-1] == 'T33')) { horizontal(ID,'l'); Spielfeld[O][L-1] = Spielfeld[O][L]; } else { fertig = 1; return true; }
Now it's checked if all the tiles are in the right order. If a tile is on its right position gewonnen is increased.
gewonnen = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (Spielfeld[i][j] == ('T' + i + j)) gewonnen++; } }
Now if 15 tiles were in the right order (all the tiles you can slide) the last tile is positioned at the right place and it's made visible.
if (gewonnen == 15) { document.getElementById('T33').style.top = 300; document.getElementById('T33').style.left = 300; document.getElementById('T33').style.visibility = 'visible'; } Spielfeld[O][L] = 'T33'; return true; } </SCRIPT>
Now we still need the HTML part of the script. Each tile is situated on its own DIV. If you click on a DIV it's checked if the current move is already finished (fertig should be 1 in this case) and if so it calls the move() function with the current tile as parameter.
<DIV id="T00" style="position:absolute" onMouseUp="if (fertig) {fertig = 0; move('T00')}"> <IMG src="" alt="" height="100" width="100"> </DIV> <DIV id="T01" style="position:absolute" onMouseUp="if (fertig) {fertig = 0; move('T01')}"> <IMG src="" alt="" height="100" width="100"> </DIV> . . . <DIV id="T32" style="position:absolute" onMouseUp="if (fertig) {fertig = 0; move('T32')}"> <IMG src="" alt="" height="100" width="100"> </DIV> <DIV id="T33" style="position:absolute; visibility:hidden"> <IMG src="" alt="" height="100" width="100"> </DIV>
Also we need a preview of the whole picture. This is stored in the 17.gif or 17.jpg file.
<IMG src="" alt="Preview" height="200" width="200">
Now the part that calls the initialization.
<SCRIPT type="text/javascript"> ChangeTheme(4); init(); </SCRIPT>
To call different image sets I use a drop down menu. Each entry has a number associated with it, which is checked in the ChangeTheme() function. The default entry is selected. The theme entries here are for my current image sets. You can also implement your own ones.
<SELECT onChange="ChangeTheme(this.value)"> <OPTION value="3">Basic</OPTION> <OPTION value="2">DaVinci</OPTION> <OPTION value="0">Dopefish</OPTION> <OPTION value="4" selected>JS-Games</OPTION> <OPTION value="1">Tower</OPTION> </SELECT>