'Is the conversion of tiles wrong?
I'm working on an version of 15 puzzle game and for some reason, clicking the tiles works 90% of the time, but sometimes clicking a tile to move to the adjacent white (empty) tile doesn't work/do anything.
The design is to treat the grid like an array then convert to coordinates when needed. The problem is the conversion but not sure what/which part exactly exactly.
Here is the HTML, CSS, and JavaScript:
Html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<center>
<div id="table" style="display: table;">
<div id="row0" style="display: table-row;">
<div id="cell0" class="tile0" onClick="clickTile(0);"></div>
<div id="cell1" class="tile1" onClick="clickTile(1);"></div>
<div id="cell2" class="tile2" onClick="clickTile(2);"></div>
<div id="cell3" class="tile3" onClick="clickTile(3);"></div>
</div>
<div id="row1" style="display: table-row;">
<div id="cell4" class="tile4" onClick="clickTile(4);"></div>
<div id="cell5" class="tile5" onClick="clickTile(5);"></div>
<div id="cell6" class="tile6" onClick="clickTile(6);"></div>
<div id="cell7" class="tile7" onClick="clickTile(7);"></div>
</div>
<div id="row2" style="display: table-row;">
<div id="cell8" class="tile8" onClick="clickTile(8);"></div>
<div id="cell9" class="tile9" onClick="clickTile(9);"></div>
<div id="cell10" class="tile10" onClick="clickTile(10);"></div>
<div id="cell11" class="tile11" onClick="clickTile(11);"></div>
</div>
<div id="row" style="display: table-row;">
<div id="cell12" class="tile12" onClick="clickTile(12);"></div>
<div id="cell13" class="tile13" onClick="clickTile(13);"></div>
<div id="cell14" class="tile14" onClick="clickTile(14);"></div>
<div id="cell15" class="tile15" onClick="clickTile(15);"></div>
</div>
</div>
<br>
</center>
<script src="./script.js"></script>
</body>
</html>
CSS:
.tile0, .tile1, .tile2, .tile3, .tile4, .tile5, .tile6, .tile7, .tile8, .tile9, .tile10, .tile11, .tile12, .tile13, .tile14, .tile15, .tile16 {
display: table-cell;
width: 120px;
height: 120px;
border: 1px solid white;
background-color: darkcyan;
cursor: pointer;
}
.tile0:after {background-position: 0px 0px; content:"0";}
.tile1:after {background-position: -90px 0px; content:"1";}
.tile2:after {background-position: -180px 0px; content:"2";}
.tile3:after {background-position: -270px 0px; content:"3";}
.tile4:after {background-position: 0px -90px; content:"4";}
.tile5:after {background-position: -90px -90px; content:"5";}
.tile6:after {background-position: -180px -90px; content:"6";}
.tile7:after {background-position: -270px -90px; content:"7";}
.tile8:after {background-position: 0px -180px; content:"8";}
.tile9:after {background-position: -90px -180px; content:"9";}
.tile10:after {background-position: -180px -180px; content:"10";}
.tile11:after {background-position: -270px -180px; content:"11";}
.tile12:after {background-position: 0px -270px; content:"12";}
.tile13:after {background-position: -90px -270px; content:"13";}
.tile14:after {background-position: -180px -270px; content:"14";}
.tile15 {background: white; cursor: default;}
JavaScript code:
let moves = 0; // Tracks number of moves
function swapTiles(cell1, cell2) {
try {
let tempTile = document.getElementById(cell1).className;
document.getElementById(cell1).className = document.getElementById(cell2).className;
document.getElementById(cell2).className = tempTile;
} catch(err){
console.log(err)
}
}
function clickTile(cellID) {
// Derive (X,Y) coords
let row = ((cellID-1) % 4);
let column = Math.ceil((cellID-1) / 4);
// Get the tile that is in the cell
let tile = document.getElementById("cell"+cellID).className;
if(tile != "tile15") {
//check if the empty tile is on the right
if(column < 3) {
if(document.getElementById("cell"+(cellID+1)).className=="tile15") {
swapTiles("cell"+cellID, "cell"+(cellID+1));
// Incriment move count
moves = moves += 1;
return;
}
}
//check if the empty tile is on the left
if(column > 0) {
if(document.getElementById("cell"+(cellID-1)).className=="tile15") {
swapTiles("cell"+cellID,"cell"+(cellID-1));
// Incriment move count
moves = moves += 1;
return;
}
}
//check if the empty tile is above
if(row > 0) {
if(document.getElementById("cell"+(cellID-4)).className=="tile15") {
swapTiles("cell"+cellID, "cell"+(cellID-4));
// Increment move count
moves = moves += 1;
return;
}
}
//check if the empty tile is below
if(row < 3) {
if(document.getElementById("cell"+(cellID+4)).className=="tile15") {
swapTiles("cell"+cellID, "cell"+(cellID+4));
// Incriment move count
moves = moves += 1;
return;
}
}
}
}
Is it possible because of let? It can't be though since it's scoped to the function, and it's working for the most part anyway.
Solution 1:[1]
The way you calculate the values for row and column is wrong:
- You should not subtract 1, as indeed the least
cellIDvalue is 0 in your HTML, not 1. - You need to
floor, notceil rowandcolumnshould be reversed
It should be:
let column = cellID % 4;
let row = Math.floor(cellID / 4);
Solution 2:[2]
Your row and column formulas are wrong. See below for corrected code.
let moves = 0; // Tracks number of moves
function swapTiles(cell1, cell2) {
try {
let tempTile = document.getElementById(cell1).className;
document.getElementById(cell1).className = document.getElementById(cell2).className;
document.getElementById(cell2).className = tempTile;
} catch(err){
console.log(err)
}
}
function clickTile(cellID) {
// Derive (X,Y) coords
let row = Math.floor((cellID) / 4);
let column = (cellID) % 4;
console.log(row, column)
// Get the tile that is in the cell
let tile = document.getElementById("cell"+cellID).className;
if(tile != "tile15") {
//check if the empty tile is on the right
if(column < 3) {
if(document.getElementById("cell"+(cellID+1)).className=="tile15") {
swapTiles("cell"+cellID, "cell"+(cellID+1));
// Incriment move count
moves = moves += 1;
return;
}
}
//check if the empty tile is on the left
if(column > 0) {
if(document.getElementById("cell"+(cellID-1)).className=="tile15") {
swapTiles("cell"+cellID,"cell"+(cellID-1));
// Incriment move count
moves = moves += 1;
return;
}
}
//check if the empty tile is above
if(row > 0) {
if(document.getElementById("cell"+(cellID-4)).className=="tile15") {
swapTiles("cell"+cellID, "cell"+(cellID-4));
// Increment move count
moves = moves += 1;
return;
}
}
//check if the empty tile is below
if(row < 3) {
if(document.getElementById("cell"+(cellID+4)).className=="tile15") {
swapTiles("cell"+cellID, "cell"+(cellID+4));
// Incriment move count
moves = moves += 1;
return;
}
}
}
}
.tile0, .tile1, .tile2, .tile3, .tile4, .tile5, .tile6, .tile7, .tile8, .tile9, .tile10, .tile11, .tile12, .tile13, .tile14, .tile15, .tile16 {
display: table-cell;
width: 120px;
height: 120px;
border: 1px solid white;
background-color: darkcyan;
cursor: pointer;
}
.tile0:after {background-position: 0px 0px; content:"0";}
.tile1:after {background-position: -90px 0px; content:"1";}
.tile2:after {background-position: -180px 0px; content:"2";}
.tile3:after {background-position: -270px 0px; content:"3";}
.tile4:after {background-position: 0px -90px; content:"4";}
.tile5:after {background-position: -90px -90px; content:"5";}
.tile6:after {background-position: -180px -90px; content:"6";}
.tile7:after {background-position: -270px -90px; content:"7";}
.tile8:after {background-position: 0px -180px; content:"8";}
.tile9:after {background-position: -90px -180px; content:"9";}
.tile10:after {background-position: -180px -180px; content:"10";}
.tile11:after {background-position: -270px -180px; content:"11";}
.tile12:after {background-position: 0px -270px; content:"12";}
.tile13:after {background-position: -90px -270px; content:"13";}
.tile14:after {background-position: -180px -270px; content:"14";}
.tile15 {background: white; cursor: default;}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<center>
<div id="table" style="display: table;">
<div id="row0" style="display: table-row;">
<div id="cell0" class="tile0" onClick="clickTile(0);"></div>
<div id="cell1" class="tile1" onClick="clickTile(1);"></div>
<div id="cell2" class="tile2" onClick="clickTile(2);"></div>
<div id="cell3" class="tile3" onClick="clickTile(3);"></div>
</div>
<div id="row1" style="display: table-row;">
<div id="cell4" class="tile4" onClick="clickTile(4);"></div>
<div id="cell5" class="tile5" onClick="clickTile(5);"></div>
<div id="cell6" class="tile6" onClick="clickTile(6);"></div>
<div id="cell7" class="tile7" onClick="clickTile(7);"></div>
</div>
<div id="row2" style="display: table-row;">
<div id="cell8" class="tile8" onClick="clickTile(8);"></div>
<div id="cell9" class="tile9" onClick="clickTile(9);"></div>
<div id="cell10" class="tile10" onClick="clickTile(10);"></div>
<div id="cell11" class="tile11" onClick="clickTile(11);"></div>
</div>
<div id="row" style="display: table-row;">
<div id="cell12" class="tile12" onClick="clickTile(12);"></div>
<div id="cell13" class="tile13" onClick="clickTile(13);"></div>
<div id="cell14" class="tile14" onClick="clickTile(14);"></div>
<div id="cell15" class="tile15" onClick="clickTile(15);"></div>
</div>
</div>
<br>
</center>
<script src="./script.js"></script>
</body>
</html>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | trincot |
| Solution 2 | Samson |
