Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="game">
        <h1>
            <div class="cell two">2</div>
            <div class="cell large">0</div>
            <div class="cell four">4</div>
            <div class="cell eight">8</div>
        </h1>
        <h3>Mode:
            <button class="btn-selected mode-toggle" id="rapid-mode">Rapid</button>
            <button class="mode-toggle" id="normal-mode">Normal</button>
        </h3>
        <div class="scoring">
            <div class="scoreboard">Score
                <br />
                <span class="score">0</span>
            </div>
            <div class="scoreboard">Top Score
                <br />
                <span class="topscore">0</span>
            </div>
            <div>
                <button class="continue" id="newgame">New
                    <br />Game</button>
            </div>
        </div>
        <hr />
        <div class="board">
        </div>
        <div class="wrapper"></div>
    </div>
    <div class="alertbox">
        <div class="message"></div>
        <br/>
        <button class="continue" id="continue">Play Again</button>
    </div>
              
            
!

CSS

              
                .game {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.emptycell {
    position: absolute;
    z-index: 2;
    width: 100px;
    height: 100px;
    margin: 10px;
    background: darkgrey;
    border-radius: 15px;
}

.scoring {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
}

.scoreboard {
    background: #4A148C;
    color: white;
    padding: 10px 20px;
    border: 1px dotted greenyellow;
    border-radius: 10px;
    text-align: center;
    width: 90px;
    margin-right: 10px;
}

.wrapper {
    position: relative;
    width: 450px;
    height: 450px;
    z-index: 1;
    background: gray;
    margin-top: -465px;
    border-radius: 20px;
}

.cell {
    margin: 10px;
    width: 100px;
    height: 65px;
    padding-top: 35px;
    text-align: center;
    background: #FBE9E7;
    border: 1px solid #3E2723;
    border-radius: 15px;
    font-size: 30px;
    position: absolute;
    z-index: 10;
    box-shadow: 0px 0px 10px -2px black;
}

h1 {
    display: flex;
    flex-direction: row;
    margin: 5px;
    height: 60px;
}

h1 .cell {
    margin: 1px;
    position: relative;
    font-size: 35px;
    height: 48px;
    width: 60px;
    padding-top: 6px;
}

h3 {
    margin: 5px;
}

.board {
    width: 450px;
    height: 450px;
    border: 15px solid black;
    background: grey;
    border-radius: 20px;
}

.two {
    background: radial-gradient(#FBD7D7, #FCF8F8);
    font-size: 50px;
    height: 85px;
    padding-top: 15px;
}

.four {
    background: radial-gradient(#FBB797, #FCC8B1);
    font-size: 50px;
    height: 85px;
    padding-top: 15px;
}

.eight {
    background: radial-gradient(#FB9797, #FBA7A7);
    font-size: 50px;
    color: black;
    height: 85px;
    padding-top: 15px;
}

.sixteen {
    background: radial-gradient(#FB6957, #FB8767);
    color: #FBE9E7;
    font-size: 50px;
    height: 85px;
    padding-top: 15px;
}

.thirtyTwo {
    background: radial-gradient(#FB2727, #FB4036);
    color: #FBE9E7;
    font-size: 50px;
    height: 85px;
    padding-top: 15px;
}

.sixtyFour {
    background: radial-gradient(#aa1111, #ba3333);
    color: white;
    font-size: 50px;
    height: 85px;
    padding-top: 15px;
}

.oneTwentyEight {
    background: radial-gradient(yellow, rgb(243, 243, 110));
    font-size: 40px;
    height: 75px;
    padding-top: 25px;
}

.twoFiveSix {
    background: radial-gradient(orange, rgb(243, 187, 83));
    font-size: 40px;
    color: white;
    height: 75px;
    padding-top: 25px;
}

.fiveOneTwo {
    background: radial-gradient(rgb(190, 106, 50), rgb(223, 137, 79));
    font-size: 40px;
    color: white;
    height: 75px;
    padding-top: 25px;
}

.one024 {
    background: radial-gradient(rgb(175, 231, 19), rgb(193, 247, 45));
    font-size: 35px;
    height: 70px;
    padding-top: 30px;
}

.two048 {
    background: radial-gradient(green, rgb(11, 204, 11));
    font-size: 35px;
    color: #FBE9E7;
    height: 70px;
    padding-top: 30px;
}

.four096 {
    background: radial-gradient(indigo, rgb(107, 8, 177));
    font-size: 35px;
    color: #FBE9E7;
    height: 70px;
    padding-top: 30px;
}

.eight192 {
    background: radial-gradient(#4444cc, #4466ee);
    font-size: 35px;
    color: #FBE9E7;
    height: 70px;
    padding-top: 30px;
}

.large {
    background: radial-gradient(#99AAE7, #99CCF9);
}

.alertbox {
    background: rgba(20, 20, 90, 0.8);
    color: white;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    z-index: 10;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    visibility: hidden;
    position: absolute;
    font-size: 35px;
    text-align: center;
}

.mode-toggle {
    border-radius: 10px;
    padding: 5px 20px;
    font-size: 1em;
    background: grey;
    color: darkgray;
}

.btn-selected {
    background: #4444cc;
    color: white;
}

@keyframes showing {
    0% {
        visibility: visible;
        transform: scale(0.2);
    }
    100% {
        visibility: visible;
        transform: scale(1);
    }
}

.show {
    animation: showing .7s ease;
    animation-fill-mode: forwards;
}

.message {
    margin-bottom: 20px;
    visibility: hidden;
}

.continue {
    border: 1px solid #abc;
    border-radius: 15px;
    padding: 5px 25px;
    color: white;
    font-size: 18px;
    background: rgb(218, 48, 36);
}

#continue {
    visibility: hidden;
}

.continue:hover {
    border: 1px solid red;
    background: #aabbcc;
    color: indigo;
}

@media (max-width:500px) {
    .game {
        transform: scale(0.85);
        margin-top: -50px;
    }
    h1 {
        margin-bottom: 10px;
        font-size: 26px;
    }
}

@media (max-width:400px) {
    .game {
        transform: scale(0.7);
        margin-top: -70px;
    }
    h1 {
        margin-bottom: 10px;
        font-size: 24px;
    }
}

@media (max-width:330px) {
    .game {
        transform: scale(0.6);
        margin-top: -100px;
    }
    h1 {
        margin-bottom: 10px;
        font-size: 20px;
    }
}
              
            
!

JS

              
                $(document).ready(function () {
    //initilization with zero values for all cells
    var cells = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    var yloc = 0,
        xloc = 0;
    // retrieving scores & game mode from local storage
    var score = (localStorage.getItem("score") == undefined) ? 0 : Math.round(localStorage.getItem("score"));
    var topscore = (localStorage.getItem("topscore") == undefined) ? 0 : Math.round(localStorage.getItem("topscore"));
    var rapidmode = (localStorage.getItem("rapidmode") == undefined || localStorage.getItem("rapidmode") == "true") ? true : false;
    if (rapidmode == false) {
        $("#normal-mode").addClass("btn-selected");
        $("#rapid-mode").removeClass("btn-selected");
    }
    var won = false;
    //creating emptycells
    for (var i = 0; i < 16; i++) {
        var xloc = ((i) % 4) * 110;
        var yloc = Math.floor((i) / 4) * 110;
        $(".wrapper").append("<div class='emptycell emp" + i + "'></div>");
        $(".emp" + i).css("transform", "translate(" + xloc + "px," + yloc + "px)");
    }
    //Initialization function with 2 random cells with 2
    function init() {
        if (localStorage.getItem('cells') == undefined) {
            var a1 = randInt(1, 16),
                a2 = randInt(1, 16);
            while (a1 == a2) {
                a2 = randInt(1, 16);
            }
            cells[a1 - 1] = 2;
            cells[a2 - 1] = 2;
        } else {
            cells = JSON.parse(localStorage.getItem('cells'));
        }
        redrawAll(); //drawing initial board with stored cells value or starting new game
        $(".score").text(score); // display score
        $(".topscore").text(topscore); //display top score
    }

    init(); //initialize

    //Function for swipe handler using touchSwipe jquery framework
    $(window).swipe({
        //Generic swipe handler for all directions
        swipe: function (event, direction, distance, duration, fingerCount, fingerData) {
            if (direction == "left") {
                act(37);
            } else if (direction == "up") {
                act(38);
            } else if (direction == "right") {
                act(39);
            } else if (direction == "down") {
                act(40);
            }
        }
    });

    //Key Events function
    $(window).on("keydown", function (ev) {
        act(ev.which);
    });

    //Action function on keypress & swipe event
    function act(ev) {
        if (shift(ev)) { //check if any shift or movement happend in a direction or any cells merged
            setTimeout(function () {
                updateBoard();
            }, 150); //drawing new item & updating scores & storing values          
        }
    }
    //function to redraw the whole board based on cells array
    function redrawAll() {
        $(".board").html(""); //emptying the board
        for (var i = 0; i < cells.length; i++) {
            if (cells[i] != 0) {
                var index = i + 1;
                var xloc = ((index - 1) % 4) * 110; //calculating x pos
                var yloc = Math.floor((index - 1) / 4) * 110; //calculating y pos
                $(".board").append("<div class='cell " + index + " " + getcolorclass(cells[i]) + "'>" + cells[i] + "</div>"); //creating div
                $("." + index).css("transform", "translate(" + xloc + "px," + yloc + "px)"); //positioning the div
            }
        }
    }
    // Function to update score, new item & store values after each move
    function updateBoard() {
            //getting indices of zero values or empty cells of cells array into idx & selecting any random value
        var zeros = [];
        var idx = cells.indexOf(0);
        while (idx != -1) {
            zeros.push(idx);
            idx = cells.indexOf(0, idx + 1);
        }
        idx = zeros[Math.floor(Math.random() * zeros.length)];
        var chanceOf4 = Math.random(); //chance of appearing four
        if (chanceOf4 < 0.1) { //10% times create 4
            cells[idx] = 4;
        } else cells[idx] = 2; //90% times create new cell with 2  
        // drawing new item
        var xloc = (idx % 4) * 110; //calculating x pos
        var yloc = Math.floor(idx / 4) * 110; //calculating y pos
        $(".board").append("<div class='cell " + (idx + 1) + " " + getcolorclass(cells[idx]) + "'>" + cells[idx] + "</div>"); //creating div
        $(".cell." + (idx + 1)).css("transform", "translate(" + xloc + "px," + yloc + "px)"); //positioning the div
        // Updating scores
        $(".score").text(score);
        $(".topscore").text(topscore); //display score
        //storing info
        localStorage.setItem("score", score);
        localStorage.setItem("topscore", topscore);
        localStorage.setItem('cells', JSON.stringify(cells));
        //check if won
        if (won) {
            showalert("Congrats You win!!", "Continue");
        }
        //check for game over
        if (allFilled(1, 16) && noMatch()) { //conditions are all filled & nomatch for merging
            showalert("Game Over!!", "Play Again");
        }
    }
    //movement function
    function shift(ev) {
        var moved = false;
        if (ev == 40) { //shifting down
            var empty = 0;
            for (var i = 13; i <= 16; i++) { //iterating over columns
                var j = i;
                var combined = false;
                //function to go down
                function godown() {
                    for (var l = i; l >= i - 12; l -= 4) { //iterating over cells in a column
                        for (j = l; j >= i - 12 && isEmpty(j); j -= 4) { //checking empty cells below each non empty cell
                            empty++; //storing num of empty cells
                        }
                        if (j >= i - 12 && empty > 0 && empty < 4) { //if any empty cell
                            //move upto num of empty cell
                            transit(j + 4 * empty, j); //transition
                            moved = true; ////setting moved to true if movement happend
                        }
                        empty = 0;
                    }
                }
                do { //checking whether any cell have been merged then continue movement on that col
                    godown();
                    combined = combine(ev, i); //checking for merge possibility & merging
                    if (combined) moved = true; //setting moved to true if combined
                } while (combined & rapidmode);
                godown();
            }
        }
        if (ev == 38) { //shifting up in similar fasion
            var empty = 0;
            for (var i = 1; i <= 4; i++) {
                var j;
                var combined = false;
                //function to go up
                function goup() {
                    for (var l = i; l <= i + 12; l += 4) {
                        for (j = l; j <= i + 12 && isEmpty(j); j += 4) {
                            empty++;
                        }
                        if (j <= i + 12 && empty > 0 && empty < 4) {
                            transit(j - 4 * empty, j); //transition
                            moved = true;
                        }
                        empty = 0;
                    }
                }
                do {
                    goup();
                    combined = combine(ev, i);
                    if (combined) moved = true;
                } while (combined & rapidmode);
                goup();
            }
        }
        if (ev == 37) { //shifting left in similar fasion
            var empty = 0;
            for (var i = 1; i <= 13; i += 4) {
                var j;
                var combined = false;
                //function to go left
                function goleft() {
                    for (var l = i; l <= i + 3; l++) {
                        for (j = l; j <= i + 3 && isEmpty(j); j++) {
                            empty++;
                        }
                        if (j <= i + 3 && empty > 0 && empty < 4) {
                            transit(j - empty, j); //transition
                            moved = true;
                        }
                        empty = 0;
                    }
                }
                do {
                    goleft();
                    combined = combine(ev, i);
                    if (combined) moved = true;
                } while (combined & rapidmode);
                goleft();
            }
        }
        if (ev == 39) { //shifting right in similar fasion
            var empty = 0;
            for (var i = 4; i <= 16; i += 4) {
                var j;
                var combined = false;
                //function to go right
                function goright() {
                    for (var l = i; l >= i - 3; l--) {
                        for (j = l; j >= i - 3 && isEmpty(j); j--) {
                            empty++;
                        }
                        if (j >= i - 3 && empty > 0 && empty < 4) {
                            transit(j + empty, j); //transition
                            moved = true;
                        }
                        empty = 0;
                    }
                }
                do {
                    goright();
                    combined = combine(ev, i);
                    if (combined) moved = true;
                } while (combined & rapidmode);
                goright();
            }
        }
        return moved; //returning whether movement or merging has happened
    }
    //merging function
    function combine(ev, start) {
        if (ev == 40) { //combine down
            for (var i = start; i > start - 12; i -= 4) { //from start upwards
                if (cells[i - 1] != 0 && cells[i - 1] == cells[i - 5]) { //if cell & upper cell are equal
                    transitNCombine(i - 4, i); //combine 2 cells
                    return true; //return true on any merge
                }
            }
        } else if (ev == 38) { //combine up in similar fasion
            for (var i = start; i < start + 12; i += 4) {
                if (cells[i - 1] != 0 && cells[i - 1] == cells[i + 3]) {
                    transitNCombine(i + 4, i); //combine 2 cells
                    return true;
                }
            }
        } else if (ev == 37) { //combine left in similar fasion
            for (var i = start; i < start + 3; i++) {
                if (cells[i - 1] != 0 && cells[i - 1] == cells[i]) {
                    transitNCombine(i + 1, i); //combine 2 cells
                    return true;
                }
            }
        } else if (ev == 39) { //combine right in similar fasion
            for (var i = start; i > start - 3; i--) {
                if (cells[i - 1] != 0 && cells[i - 1] == cells[i - 2]) {
                    transitNCombine(i - 1, i); //combine 2 cells
                    return true;
                }
            }
        }
        return false; //return false if not merged
    }
    //function to check if a cell is empty or not
    function isEmpty(cellNo) {
        return cells[cellNo - 1] == 0;
    }
    //function to check if all cells are filled
    function allFilled(start, end) {
        for (var i = start; i <= end; i++) {
            if (cells[i - 1] == 0) {
                return false; //return false if any cell is empty
            }
        }
        return true;
    }
    // Function to transit one cell from sourceIndex to destinationIndex 
    function transit(destIndex, sourceIndex) {
        cells[destIndex - 1] = cells[sourceIndex - 1];
        cells[sourceIndex - 1] = 0;
        var xloc = ((destIndex - 1) % 4) * 110; //calculating x pos
        var yloc = Math.floor((destIndex - 1) / 4) * 110; //calculating y pos
        TweenMax.to(".cell." + sourceIndex, 0.15, {
            css: {
                transform: "translate(" + xloc + "px," + yloc + "px)"
            },
            ease: Power1.easeOut
        });
        $(".cell." + sourceIndex).addClass("" + destIndex).removeClass("" + sourceIndex);
    }
    // Function to combine two cells of sourceIndex and destinationIndex respectively
    function transitNCombine(sourceIndex, destIndex) {
        cells[sourceIndex - 1] = 0;
        var xloc = ((destIndex - 1) % 4) * 110; //calculating x pos
        var yloc = Math.floor((destIndex - 1) / 4) * 110; //calculating y pos
        TweenMax.to(".cell." + sourceIndex, 0.15, {
            css: {
                transform: "translate(" + xloc + "px," + yloc + "px)",
                opacity: 0.2
            },
            ease: Power1.easeOut
        });
        $(".cell." + destIndex).removeClass(getcolorclass(cells[destIndex - 1]));
        cells[destIndex - 1] *= 2; //doubling the original cell
        $(".cell." + destIndex).addClass(getcolorclass(cells[destIndex - 1]));
        $(".cell." + sourceIndex).addClass("removable");
        setTimeout(function () {
            $(".cell." + destIndex).text(cells[destIndex - 1]);
            $(".cell.removable").remove();
        }, 150);
        score += cells[destIndex - 1];
        topscore = (score > topscore) ? score : topscore;
        if (cells[destIndex - 1] == 2048) {
            won = true; //set won to true if 2048 is formed
        }
    }
    //function to check if there is no merge possible
    function noMatch() {
        for (var i = 0; i < 15; i++) {
            if (cells[i] != 0 && (((i + 1) % 4 != 0 && cells[i] == cells[i + 1]) || (i < 12 && cells[i] == cells[i + 4]))) {
                return false;
            }
        }
        return true;
    }
    //function to show alert on win or game over
    function showalert(message, btntxt) {
        $(".message").html(message);
        $("#continue").text(btntxt);
        $(".alertbox").addClass("show");
        $("#continue").addClass("show");
        $(".message").addClass("show");
    }
    //function for coninue button onlick
    $("#continue").click(function () {
        $(".alertbox").removeClass("show"); //hiding the alert box
        $("#continue").removeClass("show");
        $(".message").removeClass("show");
        if (won) {
            won = false; //continue playing on win
            $("#continue").text("New Game");
        } else {
            restart();
        }
    });
    //Function for mode toggle
    $(".mode-toggle").click(function () {
        $(this).addClass("btn-selected");
        if ($(this).attr("id") == "normal-mode") {
            rapidmode = false;
            $("#rapid-mode").removeClass("btn-selected");
        } else if ($(this).attr("id") == "rapid-mode") {
            rapidmode = true;
            $("#normal-mode").removeClass("btn-selected");
        }
        localStorage.setItem("rapidmode", JSON.stringify(rapidmode));
    });
    $("#newgame").click(function () {
        restart();
    });
    //function to get colors & font class
    function getcolorclass(cell) {
        var cclass = "large";
        if (cell == 2) {
            cclass = "two";
        } else if (cell == 4) {
            cclass = "four";
        } else if (cell == 8) {
            cclass = "eight";
        } else if (cell == 16) {
            cclass = "sixteen";
        } else if (cell == 32) {
            cclass = "thirtyTwo";
        } else if (cell == 64) {
            cclass = "sixtyFour";
        } else if (cell == 128) {
            cclass = "oneTwentyEight";
        } else if (cell == 256) {
            cclass = "twoFiveSix";
        } else if (cell == 512) {
            cclass = "fiveOneTwo";
        } else if (cell == 1024) {
            cclass = "one024";
        } else if (cell == 2048) {
            cclass = "two048";
        } else if (cell == 4096) {
            cclass = "four096";
        } else if (cell == 8192) {
            cclass = "eight192";
        }
        return cclass;
    }

    function restart() {
        cells = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; //if try again on game over setting all cells empty
        yloc = 0, xloc = 0;
        score = 0;
        localStorage.removeItem("cells");
        localStorage.removeItem("score");
        init(); //calling the initialize funtion
    }
    //function to generate random integer in a range
    function randInt(from, to) {
        return Math.floor(Math.random() * (to - from)) + from;
    }
});
              
            
!
999px

Console