Almost 14 years back I came across a simple puzzle game in Visual Basic which I later successfully done using JavaScript.

Those where the days of IE & Netscape, where I done a version for IE using div’s and for Netscape using layer’s.

Later I came across javascriptsource.com and submitted the code to the site. I was so thrilled when it got published as ‘Box Puzzle’ in the site in 14 Nov 2000 and was copied by several websites during that time.

http://www.javascriptsource.com/games/box-puzzle.html ( This was an IE only version, doesn’t seem’s to be working now).

Here is a version of Box Puzzle done using ‘canvas’, without using jQuery. (A non canvas version for non supported browsers).

Its a silly one when considering amazing games in JavaScript now, but still proud of my Box Puzzle.

boxpuzzle.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/> 
<style>
#clock
{
    margin:0 5px 0 5px;
    color: Blue;
}
</style>
</head> 
<body onload="init(4,4)">Boxpuzzle: 
<select onchange="changeMode(this)" id="mode">
    <option>Level - 1 (3x3)</option>
    <option selected="true">Level - 2 (4x4)</option>
    <option>Level - 3 (5x5)</option>
    <option>Level - 4 (6x6)</option>
    <option>Level - 5 (10x10)</option>
</select>
<div>Timer:<span id="clock">0</span> seconds<input type="button" value="reset" onclick="reset()" /> </div>
<div id="container"></div>  
<div id="winner"></div>
 
 
<script>
    var timerMS = 0, timer; 
    function isCanvasSupported() {//return false;
        var elem = document.createElement('canvas');
        return !!(elem.getContext && elem.getContext('2d'));
    }
    var randomSort2 = function (a, b) {
        // Get a random number between 0 and 10
        var temp = parseInt(Math.random() * 10);
 
        // Get 1 or 0, whether temp is odd or even
        var isOddOrEven = temp % 2;
 
        // Get +1 or -1, whether temp greater or smaller than 5
        var isPosOrNeg = temp > 5 ? 1 : -1;
 
        // Return -1, 0, or +1
        return (isOddOrEven * isPosOrNeg);
    }
 
    function fixEvent(e) {
        if (!e.hasOwnProperty('offsetX')) {
            var curleft = curtop = 0;
            if (e.offsetParent) {
                var obj = e;
                do {
                    curleft += obj.offsetLeft;
                    curtop += obj.offsetTop;
                } while (obj = obj.offsetParent);
            }
            e.offsetX = e.layerX - curleft;
            e.offsetY = e.layerY - curtop;
        }
        return e;
    }
 
    function tickTimer() {
        timerMS++;
        clock.innerHTML = timerMS;
    }
    function changeMode(select) {
        var cols = 4, rows = 4;
        
 
        switch (select.selectedIndex) {
            case 0:
                cols = 3;
                rows = 3;
                break;
            case 1:
                cols = 4;
                rows = 4;
                break;
            case 2:
                cols = 5;
                rows = 5;
                break;
            case 3:
                cols = 6;
                rows = 6;
                break;
            case 4:
                cols = 10;
                rows = 10;
                break;
        }
        var iiframe = parent.window.document.getElementById("iiframe");
        if (iiframe) {
            parent.window.document.getElementById("iiframe").width = (cols * rows) * 50 + "px";
            parent.window.document.getElementById("iiframe").height = 50 + (cols * rows) * 50 + "px";
        }
 
        init(cols, rows);
 
    }
 
    function reset() {
        changeMode(document.getElementById("mode"));
    }
    function init(rows,cols) {
        if (!isCanvasSupported()) {
            //redirect
            self.location.href = "boxpuzzle.html";
            return;
        }
 
        var canvas = document.getElementById("boxPuzzle");
        if (canvas) {
            canvas.parentNode.removeChild(canvas);
            if (timer) {
                timerMS = 0;
                clearTimeout(timer);
                clock.innerHTML = 0;
                timer = null;
            }
        }
 
        var boxes = [], i, indexes = [], width = 50, height = 50, border = 1,
         x, y, box, ctx, row, col;
 
 
        canvas = document.createElement('canvas'); 
        canvas.id = "boxPuzzle";
        canvas.width = (width * cols) + (cols + 1) * border;
        canvas.height = (height * rows) + (rows + 1) * border;  
        canvas.style.border = border+ "px solid #d3d3d3";
 
 
        document.getElementById("container").appendChild(canvas);
 
 
        for (i = 0; i < (rows*cols); i++) {
            indexes.push(i);
        }
 
        indexes.sort(randomSort2);
 
 
        for (i = 0; i < indexes.length; i++) {
 
            row = parseInt(i / rows);
            col = i - (row * rows);
 
            x = (width * col) + (border * (col + 1));
            y = (height * row) + (border * (row + 1));
 
            boxes.push({
                "x": x,
                "y": y,
                "i": i,
                "number": indexes[i]
            });
        }
        ctx = canvas.getContext("2d");
 
        for (i = 0, ctx; i < boxes.length; i++) {
            box = boxes[i]; 
            
            ctx.fillStyle = box.number == 0 ? "#F0F0F0" : "#C0C0C0";
            ctx.fillRect(box.x, box.y, width, height);
 
            if (box.number > 0) {
                ctx.font = "20px Arial";
                ctx.fillStyle = "#000000";
                ctx.fillText(box.number, box.number<10?(box.x + (width / 2) - 5):(box.x + (width / 2) - 10), box.y + ((height / 2) + 5));
            }
        }
 
        canvas.addEventListener("click", function (e) {
            fixEvent(e);
            var offsetX = e.offsetX, offsetY = e.offsetY;
            //which is clicked????
            var box, clickedBox, emptyBox, ctx;
            for (var i = 0; i < boxes.length; i++) {
                box = boxes[i];
                if (!clickedBox && offsetX > box.x && offsetX < (box.x + width) && offsetY > box.y && offsetY < (box.y + height)) {
                    clickedBox = box;
                }
                if (box.number === 0) {
                    emptyBox = box;
                }
            }
 
            if (!clickedBox || !emptyBox) {
                return;
            }
 
            //check this box can move left/right/up/down
 
            if (((clickedBox.i + cols) === emptyBox.i) || ((clickedBox.i + 1) === emptyBox.i) || ((clickedBox.i - cols) === emptyBox.i) || ((clickedBox.i - 1) === emptyBox.i)) {
                if (!timer) {
                    timer = setInterval(tickTimer, 1000);
                }
                //clear both
                ctx = canvas.getContext("2d");
                ctx.clearRect(clickedBox.x, clickedBox.y, width, height);
 
                ctx.clearRect(emptyBox.x, emptyBox.y, width, height);
 
 
                //swap -
                emptyBox.number = clickedBox.number;
                clickedBox.number = 0;
                // redraw - remember clickedBox is now emptybox and viceversa
 
                ctx.fillStyle = "#F0F0F0";
                ctx.fillRect(clickedBox.x, clickedBox.y, width, height);
 
 
                ctx.fillStyle = "#C0C0C0";
                ctx.fillRect(emptyBox.x, emptyBox.y, width, height);
                ctx.font = "20px Arial";
                ctx.fillStyle = "#000000";
                ctx.fillText(emptyBox.number, emptyBox.x + 20, emptyBox.y + 30);
 
 
 
                //loop and see if everything in order.
                var win = true;
 
                for (i = 0; i < boxes.length; i++) {
                    if (boxes[i].number > 0) {
                        if (boxes[i].number != (i + 1)) {
                            win = false;
                            break;
                        }
                    }
                }
                if (win) {
                    clearTimeout(timer);
                    clock.innerHTML = 0;
                    timer = null;
                    alert("Congratulations\nYou took " + timerMS + " Seconds to finish.\n\nClick 'reset' to play again.");
                    timerMS = 0;
                }
 
            }
 
        }, false);
    }
 
</script>
 
</body>
</html>