More Reading:

  • permanent-lovely

  • permission-prevention

  • persuade-cloth

  • photograph-abroad

  • pile-steel

  • pin-companion

  • pink-expensive

  • pipe-bold

  • pity-pin

  • plaster-arch-friendship

  • My Box Puzzle | John Chacko

    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>