Skip to content

Instantly share code, notes, and snippets.

@kwatch
Created December 16, 2015 00:14
Show Gist options
  • Select an option

  • Save kwatch/0567d934fd4c503cefc4 to your computer and use it in GitHub Desktop.

Select an option

Save kwatch/0567d934fd4c503cefc4 to your computer and use it in GitHub Desktop.
15puzzle.js
/// coding: utf-8
///
/// for 15puzzle
///
var Util = {
init: function() {
}
, numbers: function(start, end) {
var arr = [];
for (var i = start; i <= end; i++) {
arr.push(i);
}
return arr;
}
, shuffle: function(arr) {
for (var len = arr.length, i = len; i > 0; i--) {
var pos = Math.floor(Math.random() * i);
var tmp = arr[i-1];
arr[i-1] = arr[pos];
arr[pos] = tmp;
}
return arr;
}
};
var Model = {
cells: [] // ex: [3, 1, 4, 5, 15, ...., 9, 7, null]
, init: function() {
this.reset();
}
, isCompleted: function() {
var cells = this.cells;
for (var i = 0, len = cells.length; i < len; i++) {
if (cells[i] !== i+1) {
return false;
}
}
return true;
}
, reset: function() {
var arr = Util.numbers(1, 15);
arr.push(null);
Util.shuffle(arr);
this.cells = arr;
}
, _validateIndex: function(index) {
if (! (1 <= index && index <= 16)) {
throw ""+index+": invalid index";
}
}
, valueAt: function(index) {
this._validateIndex(index);
return this.cells[index-1];
}
, isEmptyCell: function(index) {
return this.valueAt(index) == null;
}
, indexOfSpace: function() {
var cells = this.cellls;
for (var i = 0, len = cells.length; i < len; i++) {
if (cells[i] === null) {
return i+1;
}
}
}
, north: function(index) {
return index <= 4 ? null : index - 4;
}
, east: function(index) {
return index % 4 === 0 ? null : index + 1;
}
, south: function(index) {
return index >= 13 ? null : index + 4;
}
, west: function(index) {
return index % 4 === 1 ? null : index - 1;
}
, moveFrom: function(index) {
this._validateIndex(index);
var new_index = this._moveTo(index);
if (new_index !== null) {
this.swap(index, new_index);
return new_index;
}
return null;
}
, _moveTo: function(index) {
var n = this.north(index);
if (n !== null && this.isEmptyCell(n)) { return n; }
var s = this.south(index);
if (s !== null && this.isEmptyCell(s)) { return s; }
var w = this.west(index);
if (w !== null && this.isEmptyCell(w)) { return w; }
var e = this.east(index);
if (e !== null && this.isEmptyCell(e)) { return e; }
return null;
}
, swap: function(index1, index2) {
var cells = this.cells;
var tmp = cells[index1-1];
cells[index1-1] = cells[index2-1];
cells[index2-1] = tmp;
}
};
var Action = {
init: function() {
View.renderCells(Model.cells);
$(document)
.on('click', '.cell', Action.onClickCell)
.on('mouseover', '.cell', Action.onMouseOverCell)
.on('mouseout', '.cell', Action.onMouseOutCell)
.on('click', '[data-click]', Action.onClick)
;
}
, onClick: function(ev) {
var name = $(this).data('click');
var func = Action[name];
return Function.call(func, Action, this, ev);
}
, onClickCell: function(event) {
var pair = $(this).attr('id').split('-');
var index = +pair[1];
var new_index = Model.moveFrom(index);
if (new_index !== null) {
View.swapCells(index, new_index);
if (Model.isCompleted()) {
View.completed("Conguratulation!");
}
}
}
, onMouseOverCell: function(event) {
$(this).addClass('mouseOver');
}
, onMouseOutCell: function(event) {
$(this).removeClass('mouseOver');
}
}
var View = {
init: function() {
}
, renderCells: function(cells) {
for (var i = 0, len = cells.length; i < len; i++) {
var selector = "#cell-" + (i+1);
var num = cells[i];
$(selector).text(num === null ? '' : num);
}
}
, swapCells: function(index1, index2) {
var cell1 = $('#cell-'+index1), cell2 = $('#cell-'+index2);
var tmp = cell1.text();
cell1.text(cell2.text());
cell2.text(tmp);
}
, completed: function(message) {
alert(message);
}
}
$(function() {
Util.init();
Model.init();
Action.init();
View.init();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment