Last active
May 19, 2016 17:40
-
-
Save bbrewer97202/cc1c9b7b7d6eca934dd788b75db91f2f to your computer and use it in GitHub Desktop.
15 puzzle in javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title></title> | |
</head> | |
<body> | |
<div class="container" id="container"></div> | |
<style type="text/css"> | |
.container { | |
width: 200px; | |
height: 200px; | |
background-color: black; | |
border: solid 10px black; | |
} | |
button { | |
display: block; | |
float: left; | |
width: 50px; | |
height: 50px; | |
-webkit-appearance: none; | |
-moz-appearance: none; | |
appearance: none; | |
margin: 0; | |
padding: 0; | |
border: 0; | |
background-color: red; | |
color: gold; | |
font-weight: bold; | |
font-size: 1em; | |
text-shadow: 1px 1px 2px black; | |
-webkit-box-shadow: inset 1px 0px 2px 0px rgba(0,0,0,0.25); | |
-moz-box-shadow: inset 1px 0px 2px 0px rgba(0,0,0,0.25); | |
box-shadow: inset 1px 0px 2px 0px rgba(0,0,0,0.25); | |
} | |
button.odd { | |
background-color: white; | |
} | |
.empty { | |
float: left; | |
width: 50px; | |
height: 50px; | |
background-color: black; | |
} | |
</style> | |
<script type="text/javascript"> | |
const size = 4; | |
let positions = createInitialPositions(size); | |
render(positions); | |
document.getElementById('container').addEventListener('click', onButtonClick); | |
function createInitialPositions(count) { | |
let length = (count * count); | |
let values = []; | |
let initialPositions = []; | |
//fill initial values | |
for (let c = 0; c < length; c++) { | |
values.push(c); | |
} | |
//shuffle values | |
for (let i = length; i; i -= 1) { | |
let j = Math.floor(Math.random() * i); | |
let x = values[i - 1]; | |
values[i - 1] = values[j]; | |
values[j] = x; | |
} | |
//put values into multidimensional list | |
for (let c = 0, k = -1; c < length; c++) { | |
if (c % count === 0) { | |
k++; | |
initialPositions[k] = []; | |
} | |
initialPositions[k].push(values[c]); | |
} | |
return initialPositions; | |
} | |
function onButtonClick(e) { | |
e.preventDefault(); | |
if (e.target.nodeName.toLowerCase() === 'button') { | |
let id = parseInt(e.target.getAttribute('data-number'), 10); | |
let selected = getTilePosition(positions, id); | |
let empty = getTilePosition(positions, 0); | |
//to the left or right | |
if (selected.row === empty.row) { | |
//re-order the row | |
let reorderedRow = positions[empty.row].slice(); | |
reorderedRow.splice(empty.col, 1); | |
reorderedRow.splice(selected.col, 0, 0); | |
//format updated changes | |
let changedList = reorderedRow.map((value, index) => { | |
return { | |
row: empty.row, | |
col: index, | |
value | |
} | |
}); | |
//notify changes | |
appyChanges(positions, changedList); | |
//above or below | |
} else if (selected.col === empty.col) { | |
let changedList = []; | |
if (empty.row > selected.row) { | |
while (empty.row > selected.row) { | |
empty.row--; | |
changedList.push({ | |
row: empty.row + 1, | |
col: empty.col, | |
value: positions[empty.row][empty.col] | |
}); | |
} | |
} else if (selected.row > empty.row) { | |
while (selected.row > empty.row) { | |
empty.row++; | |
changedList.push({ | |
row: empty.row - 1, | |
col: empty.col, | |
value: positions[empty.row][empty.col] | |
}); | |
} | |
} | |
changedList.push({ | |
row: selected.row, | |
col: empty.col, | |
value: 0 | |
}); | |
//notify changes | |
appyChanges(positions, changedList); | |
} | |
} | |
} | |
function appyChanges(state, listOfChanges) { | |
//copy existing positions | |
let newState = state.map(row => row.slice()); | |
//apply changes to newState | |
listOfChanges.map(update => newState[update.row][update.col] = update.value); | |
//re-render | |
render(newState); | |
} | |
function render(state) { | |
let container = document.getElementById('container'); | |
//empty container | |
while (container.firstChild) { | |
container.removeChild(container.firstChild); | |
} | |
//redraw state | |
for (let i = 0; i < size; i++) { | |
for (let j = 0; j < size; j++) { | |
if (state[i][j] === 0) { | |
let empty = document.createElement('div'); | |
empty.className = 'empty'; | |
container.appendChild(empty); | |
} else { | |
let button = document.createElement('button'); | |
button.setAttribute('data-number', state[i][j]); | |
button.className = (state[i][j] % 2 === 0) ? 'even' : 'odd'; | |
button.appendChild(document.createTextNode(state[i][j])); | |
container.appendChild(button); | |
} | |
} | |
} | |
// console.table(state); | |
//update state, normally do not do this or use globals but state store | |
positions = state.map(row => row.slice()); | |
} | |
function getTilePosition(grid, id) { | |
let pos = {}; | |
grid.forEach(function(element, index) { | |
let i = element.indexOf(id); | |
if (i !== -1) { | |
pos.row = index; | |
pos.col = i; | |
} | |
}); | |
return pos; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment