Rumah IT - Rumah Teknologi Informasi: JavaScript
Trending
Loading...
Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

2/18/2026

9/12/2024

Auto Refresh Hanya Pada DIV Tertentu JQuery

Auto Refresh Hanya Pada DIV Tertentu JQuery

Auto Refresh Hanya Pada DIV Tertentu JQuery

Pada tutorial jQuery kali ini kita akan membuat script sederhana untuk melakukan auto refresh hanya pada div tertentu saja. Jadi ketika sebuah halaman web dibuka, elemen pada div tertentu akan melakukan auto refresh sesuai interval waktu yang kita tentukan tanpa harus refresh halaman web tersebut.

2/24/2024

Membuat Survey Kepuasan Gaji HRD Viral

Membuat Survey Kepuasan Gaji HRD Viral

Membuat Survey Kepuasan Gaji HRD Viral

Halo sobat, pernahkan kamu menemukan atau menonton video survey kepuasan gaji HRD yang viral ? Dimana ketika karyawan mencoba klik tombol Tidak maka tombol tersebut akan lari kemana-mana menghindari kursor. Pada akhirnya karyawan dipaksa untuk menekan tombol Ya meskipun tidak sesuai keinginan. Tentunya survey tersebut hanya dibuat untuk lucu-lucuan saja yah. Lalu bagaimana sih cara membuat survey yang nyeleneh seperti itu ?

11/06/2023

Membuat Form Kirim ke Whatsapp Menggunakan HTML JavaScript

Membuat Form Kirim ke Whatsapp Menggunakan HTML JavaScript

Membuat Form Kirim ke Whatsapp Menggunakan HTML JavaScript

Dalam posting ini, saya akan menjelaskan bagaimana kita bisa mengirimkan formulir HTML ke WhatsApp tanpa whatsapp gateway. Dengan menggunakan fungsi ini, data dari form akan dibawa ke antarmuka obrolan WhatsApp. Kita akan membuat contoh form yang ketika diisi datanya otomatis akan langsung kirim meggunakan whatsapp. Form ini hanya terdiri dari file HTML dan JavaScript saja tanpa API maupun gateway. Cocok digunakan sebagai kontak form pada sebuah website.

10/31/2023

Membuat Global Variable di Vue Js Vite

Membuat Global Variable di Vue Js Vite

Membuat Global Variable di Vue Js Vite

Pada aplikasi yang dibangun menggunakan Laravel sebagai backend dan Vue js sebagai frontend kita bisa membuat global variable yang nantinya akan diakses oleh komponen file vue. Sebagai contoh kita ingin membuat global variable untuk mendefinisikan nama aplikasi dengan variable appName yang mengembalikan nilai "Aplikasiku". Maka pada komponen file vue kita bisa panggil dengan menggunakan tag {{ appName }}.

9/30/2023

JQuery Show Hide Attribute

JQuery Show Hide Attribute

JQuery Show Hide Attribute

Bagaimana cara mendapatkan nilai dari atribut khusus untuk digunakan dalam kondisi if else? Saya ingin mengganti tombol antara tampilkan & sembunyikan. jika tombol tampilkan diklik maka akan disembunyikan dan tombol sembunyikan muncul. Dan hal yang sama juga terjadi pada hal yang berlawanan. Jadi saya bisa menampilkan sembunyikan untuk div saya.

8/02/2023

Mengatasi Request Ajax 403 di Hosting Cpanel

Mengatasi Request Ajax 403 di Hosting Cpanel

Mengatasi Request Ajax 403 di Hosting Cpanel

Sahabat Rumah IT yang sering bermain-main dengan hosting terutama yang menggunakan control Cpanel tentu pernah mengalami error 403 (forbidden) saat melakukan request ajax terutama menggunakan metode POST. Biasanya ini terjadi ketika kita mengisi sebuah form di halaman web kemudian pada saat submit form, sistem melakukan reques ajax dengan metode POST. Error tersebut kira-kira seperti gambar dibawah ini.

7/06/2023

Node.JS SyntaxError: Unexpected token '?'

Node.JS SyntaxError: Unexpected token '?'

Node.JS SyntaxError: Unexpected token '?'

Pada artikel kali ini saya akan membahas cara mengatasi SyntaxError: Unexpected token '?' saat menjalankan aplikasi node.js. Jadi saat menjalankan aplikasi wasender yang menggunakan nodejs, saya mengalami error tersebut yang tertuju pada file utama yaitu app.js .Kira-kira apa yang menyebabkan terjadinya erro tersebut ?

12/01/2022

Membuat Jam Digital Realtime Menggunakan JavaScript

Membuat Jam Digital Realtime Menggunakan JavaScript

 Membuat Jam Digital Realtime Menggunakan JavaScript

Berbicara mengenai JavaScript memang tidak ada habisnya. Bahasa pemrograman berbasis client scripting ini sering digunakan untuk membangun sebuah website yang indah bersama dengan pasangannya yaitu HTML dan CSS. Javascript inilah yang membuat tampilan website menjadi dinamis dan hidup.

10/22/2022

JavaScript Obfuscator dan Unobfuscator

JavaScript Obfuscator dan Unobfuscator

JavaScript Obfuscator dan Unobfuscator

Dalam bahasa pemrograman berbasis scripting misalnya JavaScript dan PHP, sangat penting untuk mengamankan sebuah kode yang ditulis untuk melindungi dari pihak lain. Salah satu metode untuk mengamankan script adalah dengan melakukan enkripsi terhadap isi kode tersebut. Jika kamu pernah mendownload source code dari website seperti Github dan kamu menemukan file javascript yang isinya aneh dan susah dibaca, maka pembuat kode telah mengamankan kode tersebut dengan melakukan enkripsi. Pada kode javascript ada beberapa metode enkripsi salah satunya adalah Obfuscator dan Base64. Namun yang akan kita bahas pada artikel ini adalah Obfuscator.

7/21/2021

Alasan Mengapa Kamu Harus Mempelajari dan Menggunakan Vue.JS

Alasan Mengapa Kamu Harus Mempelajari dan Menggunakan Vue.JS

Alasan Mengapa Kamu Harus Mempelajari dan Menggunakan Vue.JS

Menurut situs web mereka Vue (diucapkan /vjuː/, seperti view) adalah framework progresif untuk membangun antarmuka pengguna. Tidak seperti kerangka kerja monolitik lainnya, Vue dirancang dari bawah ke atas agar dapat diadopsi secara bertahap. Pustaka inti difokuskan hanya pada lapisan tampilan dan mudah diambil dan diintegrasikan dengan pustaka lain atau proyek yang sudah ada. Di sisi lain, Vue juga sangat mampu menjalankan Aplikasi Satu Halaman (single page application) yang canggih saat digunakan dalam kombinasi dengan perkakas modern dan pustaka pendukung.

2/12/2021

5 Framework JavaScript Terbaik Tahun 2021

5 Framework JavaScript Terbaik Tahun 2021



Belakangan ini dunia programming dihadirkan dengan banyaknya kerangka kerja (framework) JavaScript. Sebagian besar dari framework JS tersebut menawarkan pengembangan dari sisi front-end atau back-end, beberapa yang lain adalah isomorfik yaitu memungkinkan pengembangan di kedua sisi atau istilah lainnya Full-Stack Development. Dari sekian banyaknya kerangka kerja JS, kita tidak bisa menyebutnya sebagai salah satu yang terbaik. Karena masing-masing dari Framework JS memiliki kelebihan dan kekurangan masing-masing.

8/26/2020

4/04/2020

Mengatur Ukuran Font dan Gaya Font di DataTables

Mengatur Ukuran Font dan Gaya Font di DataTables

Mengatur Ukuran Font dan Gaya Font di DataTables

Rumahit.ID - DataTables adalah plug-in untuk pustaka Javascript jQuery. DataTables merupakan tool yang sangat fleksibel, dibangun di atas dasar peningkatan progresif, yang menambahkan semua fitur canggih ini ke tabel HTML apa pun. plug-in ini banyak digunakan untuk projek pengembangan aplikasi berbasis web baik skala besar maupun sekala kecil.

Saya yakin, hampir 99% programmer menggunakan plug-in ini dalam menampilkan data didalam tabel. Keunggulan datatables yang paling utama adalah kecepatan dan responsifitas dalam menampilkan data termasuk auto-paging. Jadi kita tidak perlu membuat coding khusus untuk pagination (halaman) karena datatables sudah menyediakan fitur bawaan untuk auto-paging nya.

1/15/2020

Membuat Filter Data Dengan Datatable Date Range

Membuat Filter Data Dengan Datatable Date Range

Membuat Filter Data Dengan Datatable Date Range

Rumahit.ID - Dalam kasus ini kita memiliki tabel data besar yang berisi informasi perjalanan. Setiap baris memiliki waktu mulai dan waktu akhir dari format berikut (yyyy-mm-hh HH: mm: dd). Bagaimana kita bisa menggunakan datepicker untuk menetapkan rentang filter di datatable? Kita ingin memiliki datepicker yang hanya memilih satu hari dan bukan waktu. Kita telah mencari di mana-mana untuk jawaban yang tepat tetapi saya tidak dapat menemukannya.
Misalnya kita ingin melihat semua baris Juli dengan memilih (01-07-2016 - 31-07-2016).

Untuk kasus diatas, sederhananya adalah kita bisa memanfaatkan fungsi callback filter ke array $ .fn.dataTable.ext.search . Fungsi tersebut sudah tersedia dalam paket JQuery Datatables. Bagaimana caranya kita memanggil Callback tersebut ? Berikut adalah cara untuk Membuat Filter Data Dengan Datatable Date Range. 

2/25/2019

Membuat Game Tetris Menggunakan JavaScript

Membuat Game Tetris Menggunakan JavaScript

Membuat Game Tetris Menggunakan JavaScript

Buat kalian generasi 90-an pasti hafal dengan permainan tetris yang sangat populer ini. Permainan ini biasanya ditemukan pada game bot atau bisa kita temukan di konsol nintendo. Permainan tetris adalah permainan menyusun balok , setiap balok terdiri dari 4 kotak dengan bentuk berbeda dan dimunculkan secara acak atau random. Anda diharuskan menyusun setiap balok yang muncul dari atas kebawah supaya simetris (tidak bolong). Jika baris paling bawah ada balok yang sejajar minimal satu, maka anda akan mendapat satu skor. Jika maksimal tumpukan balok terpenuhi sampai ujung atas, maka permainan di anggap selesai (game over).

Dalam tutorial kali ini, kita akan membuat game tetris menggunakan JavaScript. JavaScript memang banyak digunakan oleh para developer game untuk membuat game mereka dari mulai yang sederhana sampai yang kompleks. Disini kita akan membuat game sederhana menggunakan JavaScript untuk membuat permainan legendaris yaitu tetris.

Struktur File :

Buat Folder js , isi filenya :
1. ai.js
2. game_manager.js
3. grid.js
4. piece.js
5. polyfill.js
6. random_piece_generator.js
7. stopwatch.js
8. timer.js
9. tuner.js

Buat Folder style, isi filenya :
1. main.css

Buat satu file index.html diluar folder.

Kemudian isi kode berikut pada setiap filenya.

1. index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Tetris AI</title>
    <link href="style/main.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="fb-root"></div>
<div class="container">
    <h1 class="header">Tetris JavaScript</h1>

    <div class="game-container">
        <canvas width="200px" height="400px" id="grid-canvas" class="grid"></canvas>
        <div class="controls-container">
            <div id="score-container" class="score-container">0</div>
            <div id="next-container" class="next-container">
                <canvas id="next-canvas" class="next-canvas" width="80px" height="80px"></canvas>
            </div>
            <a id="ai-button" class="start-ai-button">Auto</a>
            <a id="reset-button" class="reset-button">Reset</a>
        </div>
    </div>
    <hr>
    <div class="footer">
        <p> </p>
    </div>
</div>

<script src="js/polyfill.js"></script>
<script src="js/grid.js"></script>
<script src="js/piece.js"></script>
<script src="js/timer.js"></script>
<script src="js/stopwatch.js"></script>
<script src="js/game_manager.js"></script>
<script src="js/random_piece_generator.js"></script>
<script src="js/ai.js"></script>
<script src="js/tuner.js"></script>
<script>
    var manager = new GameManager();
</script>
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-68147157-4', 'auto');
  ga('send', 'pageview');
</script>
</body>
</html>

2. main.css

body
{
    background-color: #FCFCFC;
}

a
{
    color: #0000FF;
    font-weight: bold;
    text-decoration: underline;
}

a:hover
{
    cursor: pointer
}

hr
{
    border: none;
    border-bottom: 1px solid #C8C8C8;
}

.container
{
    width:350px;
    margin: 0 auto;
}

.header
{
    text-align: center;
    font-family: Verdana;
    color:#0000FF;
}

.game-container
{
    height:400px;
    margin-top:10px;
}

.grid
{
    float:left;
    background-color: #FFFFFF;
    box-shadow: 0 0 10px 2px #EEEEEE;
    border:1px solid #CCCCCC;
}

.next-canvas
{
}

.controls-container
{
    width:130px;
    float:right;
    height:100%;
}

.score-container
{
    background-color: #FFFFFF;
    box-shadow: 0 0 10px 2px #EEEEEE;
    text-align: center;
    color: #FF0000;
    font-size:25px;
    border:1px solid #CCCCCC;
    font-weight: bold;
    padding:5px;
}

.score-container::before
{
    content: "Score";
    width:100%;
    float:right;
    color: #BBBBBB;
    font-size:15px;
    font-weight: normal;
}

.next-container
{
    background-color: #FFFFFF;
    box-shadow: 0 0 10px 2px #EEEEEE;
    text-align: center;
    color: #FF0000;
    font-size:25px;
    border:1px solid #CCCCCC;
    font-weight: bold;
    padding:5px;
    margin-top: 10px;
}

.next-container::before
{
    content: "Next Piece";
    width:100%;
    float:right;
    color: #BBBBBB;
    font-size:15px;
    font-weight: normal;
}

.start-ai-button, .reset-button {
    -moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
    -webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
    box-shadow:inset 0px 1px 0px 0px #ffffff;
    background-color:#f9f9f9;
    -webkit-border-top-left-radius:3px;
    -moz-border-radius-topleft:3px;
    border-top-left-radius:3px;
    -webkit-border-top-right-radius:3px;
    -moz-border-radius-topright:3px;
    border-top-right-radius:3px;
    -webkit-border-bottom-right-radius:3px;
    -moz-border-radius-bottomright:3px;
    border-bottom-right-radius:3px;
    -webkit-border-bottom-left-radius:3px;
    -moz-border-radius-bottomleft:3px;
    border-bottom-left-radius:3px;
    text-indent:0;
    border:1px solid #dcdcdc;
    display:inline-block;
    color:#666666;
    font-family:Arial;
    font-size:15px;
    font-weight:bold;
    font-style:normal;
    height:40px;
    line-height:40px;
    width:100%;
    text-decoration:none;
    text-align:center;
    text-shadow:1px 1px 0px #ffffff;
}

.start-ai-button:hover, .reset-button:hover {
    background-color:#e9e9e9;
}

.start-ai-button:active, .reset-button:active {
     position:relative;
     top:1px;
 }

.start-ai-button{
    margin-top: 15px;
}

.reset-button{
    margin-top: 10px;
}

.footer
{
    font-family: Verdana;
    color:#000000;
    font-size: 12px;
}

.fb-like {
    vertical-align: top;
}
.fb_iframe_widget span {
    vertical-align: text-top !important;
}

3. ai.js

function AI(heightWeight, linesWeight, holesWeight, bumpinessWeight){
    this.heightWeight = heightWeight;
    this.linesWeight = linesWeight;
    this.holesWeight = holesWeight;
    this.bumpinessWeight = bumpinessWeight;
};

AI.prototype._best = function(grid, workingPieces, workingPieceIndex){
    var best = null;
    var bestScore = null;
    var workingPiece = workingPieces[workingPieceIndex];

    for(var rotation = 0; rotation < 4; rotation++){
        var _piece = workingPiece.clone();
        for(var i = 0; i < rotation; i++){
            _piece.rotate(grid);
        }

        while(_piece.moveLeft(grid));

        while(grid.valid(_piece)){
            var _pieceSet = _piece.clone();
            while(_pieceSet.moveDown(grid));

            var _grid = grid.clone();
            _grid.addPiece(_pieceSet);

            var score = null;
            if (workingPieceIndex == (workingPieces.length - 1)) {
                score = -this.heightWeight * _grid.aggregateHeight() + this.linesWeight * _grid.lines() - this.holesWeight * _grid.holes() - this.bumpinessWeight * _grid.bumpiness();
            }else{
                score = this._best(_grid, workingPieces, workingPieceIndex + 1).score;
            }

            if (score > bestScore || bestScore == null){
                bestScore = score;
                best = _piece.clone();
            }

            _piece.column++;
        }
    }

    return {piece:best, score:bestScore};
};

AI.prototype.best = function(grid, workingPieces){
    return this._best(grid, workingPieces, 0).piece;
};

4. game_manager.js

function GameManager(){
    var gridCanvas = document.getElementById('grid-canvas');
    var nextCanvas = document.getElementById('next-canvas');
    var scoreContainer = document.getElementById("score-container");
    var resetButton = document.getElementById('reset-button');
    var aiButton = document.getElementById('ai-button');
    var gridContext = gridCanvas.getContext('2d');
    var nextContext = nextCanvas.getContext('2d');
    document.addEventListener('keydown', onKeyDown);

    var grid = new Grid(22, 10);
    var rpg = new RandomPieceGenerator();
    var ai = new AI(0.510066, 0.760666, 0.35663, 0.184483);
    var workingPieces = [null, rpg.nextPiece()];
    var workingPiece = null;
    var isAiActive = true;
    var isKeyEnabled = false;
    var gravityTimer = new Timer(onGravityTimerTick, 500);
    var score = 0;

    // Graphics
    function intToRGBHexString(v){
        return 'rgb(' + ((v >> 16) & 0xFF) + ',' + ((v >> 8) & 0xFF) + ',' + (v & 0xFF) + ')';
    }

    function redrawGridCanvas(workingPieceVerticalOffset = 0){
        gridContext.save();

        // Clear
        gridContext.clearRect(0, 0, gridCanvas.width, gridCanvas.height);

        // Draw grid
        for(var r = 2; r < grid.rows; r++){
            for(var c = 0; c < grid.columns; c++){
                if (grid.cells[r][c] != 0){
                    gridContext.fillStyle= intToRGBHexString(grid.cells[r][c]);
                    gridContext.fillRect(20 * c, 20 * (r - 2), 20, 20);
                    gridContext.strokeStyle="#FFFFFF";
                    gridContext.strokeRect(20 * c, 20 * (r - 2), 20, 20);
                }
            }
        }

        // Draw working piece
        for(var r = 0; r < workingPiece.dimension; r++){
            for(var c = 0; c < workingPiece.dimension; c++){
                if (workingPiece.cells[r][c] != 0){
                    gridContext.fillStyle = intToRGBHexString(workingPiece.cells[r][c]);
                    gridContext.fillRect(20 * (c + workingPiece.column), 20 * ((r + workingPiece.row) - 2) + workingPieceVerticalOffset, 20, 20);
                    gridContext.strokeStyle="#FFFFFF";
                    gridContext.strokeRect(20 * (c + workingPiece.column), 20 * ((r + workingPiece.row) - 2) + workingPieceVerticalOffset, 20, 20);
                }
            }
        }

        gridContext.restore();
    }

    function redrawNextCanvas(){
        nextContext.save();

        nextContext.clearRect(0, 0, nextCanvas.width, nextCanvas.height);
        var next = workingPieces[1];
        var xOffset = next.dimension == 2 ? 20 : next.dimension == 3 ? 10 : next.dimension == 4 ? 0 : null;
        var yOffset = next.dimension == 2 ? 20 : next.dimension == 3 ? 20 : next.dimension == 4 ? 10 : null;
        for(var r = 0; r < next.dimension; r++){
            for(var c = 0; c < next.dimension; c++){
                if (next.cells[r][c] != 0){
                    nextContext.fillStyle = intToRGBHexString(next.cells[r][c]);
                    nextContext.fillRect(xOffset + 20 * c, yOffset + 20 * r, 20, 20);
                    nextContext.strokeStyle = "#FFFFFF";
                    nextContext.strokeRect(xOffset + 20 * c, yOffset + 20 * r, 20, 20);
                }
            }
        }

        nextContext.restore();
    }

    function updateScoreContainer(){
        scoreContainer.innerHTML = score.toString();
    }

    // Drop animation
    var workingPieceDropAnimationStopwatch = null;

    function startWorkingPieceDropAnimation(callback = function(){}){
        // Calculate animation height
        animationHeight = 0;
        _workingPiece = workingPiece.clone();
        while(_workingPiece.moveDown(grid)){
            animationHeight++;
        }

        var stopwatch = new Stopwatch(function(elapsed){
            if(elapsed >= animationHeight * 20){
                stopwatch.stop();
                redrawGridCanvas(20 * animationHeight);
                callback();
                return;
            }

            redrawGridCanvas(20 * elapsed / 20);
        });

        workingPieceDropAnimationStopwatch = stopwatch;
    }

    function cancelWorkingPieceDropAnimation(){
        if(workingPieceDropAnimationStopwatch === null){
            return;
        }
        workingPieceDropAnimationStopwatch.stop();
        workingPieceDropAnimationStopwatch = null;
    }

    // Process start of turn
    function startTurn(){
        // Shift working pieces
        for(var i = 0; i < workingPieces.length - 1; i++){
            workingPieces[i] = workingPieces[i + 1];
        }
        workingPieces[workingPieces.length - 1] = rpg.nextPiece();
        workingPiece = workingPieces[0];

        // Refresh Graphics
        redrawGridCanvas();
        redrawNextCanvas();

        if(isAiActive){
            isKeyEnabled = false;
            workingPiece = ai.best(grid, workingPieces);
            startWorkingPieceDropAnimation(function(){
                while(workingPiece.moveDown(grid)); // Drop working piece
                if(!endTurn()){
                    alert('Game Over!');
                    return;
                }
                startTurn();
            })
        }else{
            isKeyEnabled = true;
            gravityTimer.resetForward(500);
        }
    }

    // Process end of turn
    function endTurn(){
        // Add working piece
        grid.addPiece(workingPiece);

        // Clear lines
        score += grid.clearLines();

        // Refresh graphics
        redrawGridCanvas();
        updateScoreContainer();

        return !grid.exceeded();
    }

    // Process gravity tick
    function onGravityTimerTick(){
        // If working piece has not reached bottom
        if(workingPiece.canMoveDown(grid)){
            workingPiece.moveDown(grid);
            redrawGridCanvas();
            return;
        }

        // Stop gravity if working piece has reached bottom
        gravityTimer.stop();

        // If working piece has reached bottom, end of turn has been processed
        // and game cannot continue because grid has been exceeded
        if(!endTurn()){
            isKeyEnabled = false;
            alert('Game Over!');
            return;
        }

        // If working piece has reached bottom, end of turn has been processed
        // and game can still continue.
        startTurn();
    }

    // Process keys
    function onKeyDown(event){
        if(!isKeyEnabled){
            return;
        }
        switch(event.which){
            case 32: // spacebar
                isKeyEnabled = false;
                gravityTimer.stop(); // Stop gravity
                startWorkingPieceDropAnimation(function(){ // Start drop animation
                    while(workingPiece.moveDown(grid)); // Drop working piece
                    if(!endTurn()){
                        alert('Game Over!');
                        return;
                    }
                    startTurn();
                });
                break;
            case 40: // down
                gravityTimer.resetForward(500);
                break;
            case 37: //left
                if(workingPiece.canMoveLeft(grid)){
                    workingPiece.moveLeft(grid);
                    redrawGridCanvas();
                }
                break;
            case 39: //right
                if(workingPiece.canMoveRight(grid)){
                    workingPiece.moveRight(grid);
                    redrawGridCanvas();
                }
                break;
            case 38: //up
                workingPiece.rotate(grid);
                redrawGridCanvas();
                break;
        }
    }

    aiButton.onclick = function(){
        if (isAiActive){
            isAiActive = false;
            aiButton.style.backgroundColor = "#f9f9f9";
        }else{
            isAiActive = true;
            aiButton.style.backgroundColor = "#e9e9ff";

            isKeyEnabled = false;
            gravityTimer.stop();
            startWorkingPieceDropAnimation(function(){ // Start drop animation
                while(workingPiece.moveDown(grid)); // Drop working piece
                if(!endTurn()){
                    alert('Game Over!');
                    return;
                }
                startTurn();
            });
        }
    }

    resetButton.onclick = function(){
        gravityTimer.stop();
        cancelWorkingPieceDropAnimation();
        grid = new Grid(22, 10);
        rpg = new RandomPieceGenerator();
        workingPieces = [null, rpg.nextPiece()];
        workingPiece = null;
        score = 0;
        isKeyEnabled = true;
        updateScoreContainer();
        startTurn();
    }

    aiButton.style.backgroundColor = "#e9e9ff";
    startTurn();
}

5. grid.js

function Grid(rows, columns){
    this.rows = rows;
    this.columns = columns;

    this.cells = new Array(rows);
    for (var r = 0; r < this.rows; r++) {
        this.cells[r] = new Array(this.columns);
        for(var c = 0; c < this.columns; c++){
            this.cells[r][c] = 0;
        }
    }
};

Grid.prototype.clone = function(){
    var _grid = new Grid(this.rows, this.columns);
    for (var r = 0; r < this.rows; r++) {
        for(var c = 0; c < this.columns; c++){
            _grid.cells[r][c] = this.cells[r][c];
        }
    }
    return _grid;
};

Grid.prototype.clearLines = function(){
    var distance = 0;
    var row = new Array(this.columns);
    for(var r = this.rows - 1; r >= 0; r--){
        if (this.isLine(r)){
            distance++;
            for(var c = 0; c < this.columns; c++){
                this.cells[r][c] = 0;
            }
        }else if (distance > 0){
            for(var c = 0; c < this.columns; c++){
                this.cells[r + distance][c] = this.cells[r][c];
                this.cells[r][c] = 0;
            }
        }
    }
    return distance;
};

Grid.prototype.isLine = function(row){
    for(var c = 0; c < this.columns; c++){
        if (this.cells[row][c] == 0){
            return false;
        }
    }
    return true;
};

Grid.prototype.isEmptyRow = function(row){
    for(var c = 0; c < this.columns; c++){
        if (this.cells[row][c] != 0){
            return false;
        }
    }
    return true;
};

Grid.prototype.exceeded = function(){
    return !this.isEmptyRow(0) || !this.isEmptyRow(1);
};

Grid.prototype.height = function(){
    var r = 0;
    for(; r < this.rows && this.isEmptyRow(r); r++);
    return this.rows - r;
};

Grid.prototype.lines = function(){
    var count = 0;
    for(var r = 0; r < this.rows; r++){
        if (this.isLine(r)){
            count++;
        }
    }
    return count;
};

Grid.prototype.holes = function(){
    var count = 0;
    for(var c = 0; c < this.columns; c++){
        var block = false;
        for(var r = 0; r < this.rows; r++){
            if (this.cells[r][c] != 0) {
                block = true;
            }else if (this.cells[r][c] == 0 && block){
                count++;
            }
        }
    }
    return count;
};

Grid.prototype.blockades = function(){
    var count = 0;
    for(var c = 0; c < this.columns; c++){
        var hole = false;
        for(var r = this.rows - 1; r >= 0; r--){
            if (this.cells[r][c] == 0){
                hole = true;
            }else if (this.cells[r][c] != 0 && hole){
                count++;
            }
        }
    }
    return count;
}

Grid.prototype.aggregateHeight = function(){
    var total = 0;
    for(var c = 0; c < this.columns; c++){
        total += this.columnHeight(c);
    }
    return total;
};

Grid.prototype.bumpiness = function(){
    var total = 0;
    for(var c = 0; c < this.columns - 1; c++){
        total += Math.abs(this.columnHeight(c) - this.columnHeight(c+ 1));
    }
    return total;
}

Grid.prototype.columnHeight = function(column){
    var r = 0;
    for(; r < this.rows && this.cells[r][column] == 0; r++);
    return this.rows - r;
};

Grid.prototype.addPiece = function(piece) {
    for(var r = 0; r < piece.cells.length; r++) {
        for (var c = 0; c < piece.cells[r].length; c++) {
            var _r = piece.row + r;
            var _c = piece.column + c;
            if (piece.cells[r][c] != 0 && _r >= 0){
                this.cells[_r][_c] = piece.cells[r][c];
            }
        }
    }
};

Grid.prototype.valid = function(piece){
    for(var r = 0; r < piece.cells.length; r++){
        for(var c = 0; c < piece.cells[r].length; c++){
            var _r = piece.row + r;
            var _c = piece.column + c;
            if (piece.cells[r][c] != 0){
                if(_r < 0 || _r >= this.rows){
                    return false;
                }
                if(_c < 0 || _c >= this.columns){
                    return false;
                }
                if (this.cells[_r][_c] != 0){
                    return false;
                }
            }
        }
    }
    return true;
};

6. piece.js

function Piece(cells){
    this.cells = cells;

    this.dimension = this.cells.length;
    this.row = 0;
    this.column = 0;
};

Piece.fromIndex = function(index){
    var piece;
    switch (index){
        case 0:// O
            piece = new Piece([
                [0x0000AA, 0x0000AA],
                [0x0000AA, 0x0000AA]
            ]);
            break;
        case 1: // J
            piece = new Piece([
                [0xC0C0C0, 0x000000, 0x000000],
                [0xC0C0C0, 0xC0C0C0, 0xC0C0C0],
                [0x000000, 0x000000, 0x000000]
            ]);
            break;
        case 2: // L
            piece = new Piece([
                [0x000000, 0x000000, 0xAA00AA],
                [0xAA00AA, 0xAA00AA, 0xAA00AA],
                [0x000000, 0x000000, 0x000000]
            ]);
            break;
        case 3: // Z
            piece = new Piece([
                [0x00AAAA, 0x00AAAA, 0x000000],
                [0x000000, 0x00AAAA, 0x00AAAA],
                [0x000000, 0x000000, 0x000000]
            ]);
            break;
        case 4: // S
            piece = new Piece([
                [0x000000, 0x00AA00, 0x00AA00],
                [0x00AA00, 0x00AA00, 0x000000],
                [0x000000, 0x000000, 0x000000]
            ]);
            break;
        case 5: // T
            piece = new Piece([
                [0x000000, 0xAA5500, 0x000000],
                [0xAA5500, 0xAA5500, 0xAA5500],
                [0x000000, 0x000000, 0x000000]
            ]);
            break;
        case 6: // I
            piece = new Piece([
                [0x000000, 0x000000, 0x000000, 0x000000],
                [0xAA0000, 0xAA0000, 0xAA0000, 0xAA0000],
                [0x000000, 0x000000, 0x000000, 0x000000],
                [0x000000, 0x000000, 0x000000, 0x000000]
            ]);
            break;

    }
    piece.row = 0;
    piece.column = Math.floor((10 - piece.dimension) / 2); // Centralize
    return piece;
};

Piece.prototype.clone = function(){
    var _cells = new Array(this.dimension);
    for (var r = 0; r < this.dimension; r++) {
        _cells[r] = new Array(this.dimension);
        for(var c = 0; c < this.dimension; c++){
            _cells[r][c] = this.cells[r][c];
        }
    }

    var piece = new Piece(_cells);
    piece.row = this.row;
    piece.column = this.column;
    return piece;
};

Piece.prototype.canMoveLeft = function(grid){
    for(var r = 0; r < this.cells.length; r++){
        for(var c = 0; c < this.cells[r].length; c++){
            var _r = this.row + r;
            var _c = this.column + c - 1;
            if (this.cells[r][c] != 0){
                if (!(_c >= 0 && grid.cells[_r][_c] == 0)){
                    return false;
                }
            }
        }
    }
    return true;
};

Piece.prototype.canMoveRight = function(grid){
    for(var r = 0; r < this.cells.length; r++){
        for(var c = 0; c < this.cells[r].length; c++){
            var _r = this.row + r;
            var _c = this.column + c + 1;
            if (this.cells[r][c] != 0){
                if (!(_c >= 0 && grid.cells[_r][_c] == 0)){
                    return false;
                }
            }
        }
    }
    return true;
};


Piece.prototype.canMoveDown = function(grid){
    for(var r = 0; r < this.cells.length; r++){
        for(var c = 0; c < this.cells[r].length; c++){
            var _r = this.row + r + 1;
            var _c = this.column + c;
            if (this.cells[r][c] != 0 && _r >= 0){
                if (!(_r < grid.rows && grid.cells[_r][_c] == 0)){
                    return false;
                }
            }
        }
    }
    return true;
};

Piece.prototype.moveLeft = function(grid){
    if(!this.canMoveLeft(grid)){
        return false;
    }
    this.column--;
    return true;
};

Piece.prototype.moveRight = function(grid){
    if(!this.canMoveRight(grid)){
        return false;
    }
    this.column++;
    return true;
};

Piece.prototype.moveDown = function(grid){
    if(!this.canMoveDown(grid)){
        return false;
    }
    this.row++;
    return true;
};

Piece.prototype.rotateCells = function(){
      var _cells = new Array(this.dimension);
      for (var r = 0; r < this.dimension; r++) {
          _cells[r] = new Array(this.dimension);
      }

      switch (this.dimension) { // Assumed square matrix
          case 2:
              _cells[0][0] = this.cells[1][0];
              _cells[0][1] = this.cells[0][0];
              _cells[1][0] = this.cells[1][1];
              _cells[1][1] = this.cells[0][1];
              break;
          case 3:
              _cells[0][0] = this.cells[2][0];
              _cells[0][1] = this.cells[1][0];
              _cells[0][2] = this.cells[0][0];
              _cells[1][0] = this.cells[2][1];
              _cells[1][1] = this.cells[1][1];
              _cells[1][2] = this.cells[0][1];
              _cells[2][0] = this.cells[2][2];
              _cells[2][1] = this.cells[1][2];
              _cells[2][2] = this.cells[0][2];
              break;
          case 4:
              _cells[0][0] = this.cells[3][0];
              _cells[0][1] = this.cells[2][0];
              _cells[0][2] = this.cells[1][0];
              _cells[0][3] = this.cells[0][0];
              _cells[1][3] = this.cells[0][1];
              _cells[2][3] = this.cells[0][2];
              _cells[3][3] = this.cells[0][3];
              _cells[3][2] = this.cells[1][3];
              _cells[3][1] = this.cells[2][3];
              _cells[3][0] = this.cells[3][3];
              _cells[2][0] = this.cells[3][2];
              _cells[1][0] = this.cells[3][1];

              _cells[1][1] = this.cells[2][1];
              _cells[1][2] = this.cells[1][1];
              _cells[2][2] = this.cells[1][2];
              _cells[2][1] = this.cells[2][2];
              break;
      }

      this.cells = _cells;
};

Piece.prototype.computeRotateOffset = function(grid){
    var _piece = this.clone();
    _piece.rotateCells();
    if (grid.valid(_piece)) {
        return { rowOffset: _piece.row - this.row, columnOffset: _piece.column - this.column };
    }

    // Kicking
    var initialRow = _piece.row;
    var initialCol = _piece.column;

    for (var i = 0; i < _piece.dimension - 1; i++) {
        _piece.column = initialCol + i;
        if (grid.valid(_piece)) {
            return { rowOffset: _piece.row - this.row, columnOffset: _piece.column - this.column };
        }

        for (var j = 0; j < _piece.dimension - 1; j++) {
            _piece.row = initialRow - j;
            if (grid.valid(_piece)) {
                return { rowOffset: _piece.row - this.row, columnOffset: _piece.column - this.column };
            }
        }
        _piece.row = initialRow;
    }
    _piece.column = initialCol;

    for (var i = 0; i < _piece.dimension - 1; i++) {
        _piece.column = initialCol - i;
        if (grid.valid(_piece)) {
            return { rowOffset: _piece.row - this.row, columnOffset: _piece.column - this.column };
        }

        for (var j = 0; j < _piece.dimension - 1; j++) {
            _piece.row = initialRow - j;
            if (grid.valid(_piece)) {
                return { rowOffset: _piece.row - this.row, columnOffset: _piece.column - this.column };
            }
        }
        _piece.row = initialRow;
    }
    _piece.column = initialCol;

    return null;
};

Piece.prototype.rotate = function(grid){
    var offset = this.computeRotateOffset(grid);
    if (offset != null){
        this.rotateCells(grid);
        this.row += offset.rowOffset;
        this.column += offset.columnOffset;
    }
};

7. polyfill.js

// Credits: https://gist.github.com/paulirish/1579671

(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

8. random_piece_generator.js

function RandomPieceGenerator(){
    Math.seed
    this.bag = [0, 1, 2, 3, 4, 5, 6];
    this.shuffleBag();
    this.index = -1;
};

RandomPieceGenerator.prototype.nextPiece = function(){
    this.index++;
    if (this.index >= this.bag.length){
        this.shuffleBag();
        this.index = 0;
    }
    return Piece.fromIndex(this.bag[this.index]);
};

RandomPieceGenerator.prototype.shuffleBag = function() {
    var currentIndex = this.bag.length
        , temporaryValue
        , randomIndex
        ;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;

        // And swap it with the current element.
        temporaryValue = this.bag[currentIndex];
        this.bag[currentIndex] = this.bag[randomIndex];
        this.bag[randomIndex] = temporaryValue;
    }
};

9. stopwatch.js

function Stopwatch(callback) {
    var isStopped = false;
    var startDate = null;
    var self = this;

    var onAnimationFrame = function(){
        if(isStopped){
            return;
        }
        callback(Date.now() - startDate);
        requestAnimationFrame(onAnimationFrame);
    };

    this.stop = function() {
        isStopped = true;
    }

    startDate = Date.now();
    requestAnimationFrame(onAnimationFrame);
}

10. timer.js

function Timer(callback, delay) {
    var lastUpdate = null;
    var isRunning = false;

    var loop = function(){
        requestAnimationFrame(function(){
            var now = Date.now();
            if(!isRunning){
                lastUpdate = now;
                loop();
            }else{
                var elapsed = now - lastUpdate;
                if(lastUpdate === null || elapsed > delay){
                    callback();
                    lastUpdate = now - (elapsed % delay);
                }
                loop();
            }
        });
    };

    this.start = function() {
        if(isRunning){
            return;
        }
        lastUpdate = Date.now();
        isRunning = true;
    }

    this.stop = function() {
        isRunning = false;
    }

    this.reset = function(newDelay) {
        lastUpdate = Date.now();
        this.start();
    }

    this.resetForward = function(newDelay){
        callback();
        delay = newDelay;
        lastUpdate = Date.now();
        this.start();
    }

    loop();
}

11. tuner.js

function Tuner(){
    function randomInteger(min, max){
        return Math.floor(Math.random() * (max - min) + min);
    }

    function normalize(candidate){
        var norm = Math.sqrt(candidate.heightWeight * candidate.heightWeight + candidate.linesWeight * candidate.linesWeight + candidate.holesWeight * candidate.holesWeight + candidate.bumpinessWeight * candidate.bumpinessWeight);
        candidate.heightWeight /= norm;
        candidate.linesWeight /= norm;
        candidate.holesWeight /= norm;
        candidate.bumpinessWeight /= norm;
    }

    function generateRandomCandidate(){
        var candidate = {
            heightWeight: Math.random() - 0.5,
            linesWeight: Math.random() - 0.5,
            holesWeight: Math.random() - 0.5,
            bumpinessWeight: Math.random() - 0.5
        };
        normalize(candidate);
        return candidate;
    }

    function sort(candidates){
        candidates.sort(function(a, b){
            return b.fitness - a.fitness;
        });
    }

    function computeFitnesses(candidates, numberOfGames, maxNumberOfMoves){
        for(var i = 0; i < candidates.length; i++){
            var candidate = candidates[i];
            var ai = new AI(candidate.heightWeight, candidate.linesWeight, candidate.holesWeight, candidate.bumpinessWeight);
            var totalScore = 0;
            for(var j = 0; j < numberOfGames; j++){
                var grid = new Grid(22, 10);
                var rpg = new RandomPieceGenerator();
                var workingPieces = [rpg.nextPiece(), rpg.nextPiece()];
                var workingPiece = workingPieces[0];
                var score = 0;
                var numberOfMoves = 0;
                while((numberOfMoves++) < maxNumberOfMoves && !grid.exceeded()){
                    workingPiece = ai.best(grid, workingPieces);
                    while(workingPiece.moveDown(grid));
                    grid.addPiece(workingPiece);
                    score += grid.clearLines();
                    for(var k = 0; k < workingPieces.length - 1; k++){
                        workingPieces[k] = workingPieces[k + 1];
                    }
                    workingPieces[workingPieces.length - 1] = rpg.nextPiece();
                    workingPiece = workingPieces[0];
                }
                totalScore += score;
            }
            candidate.fitness = totalScore;
        }
    }

    function tournamentSelectPair(candidates, ways){
        var indices = [];
        for(var i = 0; i <  candidates.length; i++){
            indices.push(i);
        }

        /*
            Note that the following assumes that the candidates array is
            sorted according to the fitness of each individual candidates.
            Hence it suffices to pick the least 2 indexes out of the random
            ones picked.
        */
        var fittestCandidateIndex1 = null;
        var fittestCanddiateIndex2 = null;
        for(var i = 0; i < ways; i++){
            var selectedIndex = indices.splice(randomInteger(0, indices.length), 1)[0];
            if(fittestCandidateIndex1 === null || selectedIndex < fittestCandidateIndex1){
                fittestCanddiateIndex2 = fittestCandidateIndex1;
                fittestCandidateIndex1 = selectedIndex;
            }else if (fittestCanddiateIndex2 === null || selectedIndex < fittestCanddiateIndex2){
                fittestCanddiateIndex2 = selectedIndex;
            }
        }
        return [candidates[fittestCandidateIndex1], candidates[fittestCanddiateIndex2]];
    }

    function crossOver(candidate1, candidate2){
        var candidate = {
            heightWeight: candidate1.fitness * candidate1.heightWeight + candidate2.fitness * candidate2.heightWeight,
            linesWeight: candidate1.fitness * candidate1.linesWeight + candidate2.fitness * candidate2.linesWeight,
            holesWeight: candidate1.fitness * candidate1.holesWeight + candidate2.fitness * candidate2.holesWeight,
            bumpinessWeight: candidate1.fitness * candidate1.bumpinessWeight + candidate2.fitness * candidate2.bumpinessWeight
        };
        normalize(candidate);
        return candidate;
    }

    function mutate(candidate){
        var quantity = Math.random() * 0.4 - 0.2; // plus/minus 0.2
        switch(randomInteger(0, 4)){
            case 0:
                candidate.heightWeight += quantity;
                break;
            case 1:
                candidate.linesWeight += quantity;
                break;
            case 2:
                candidate.holesWeight += quantity;
                break;
            case 3:
                candidate.bumpinessWeight += quantity;
                break;
        }
    }

    function deleteNLastReplacement(candidates, newCandidates){
        candidates.slice(-newCandidates.length);
        for(var i = 0; i < newCandidates.length; i++){
            candidates.push(newCandidates[i]);
        }
        sort(candidates);
    }

    /*
        Population size = 100
        Rounds per candidate = 5
        Max moves per round = 200
        Theoretical fitness limit = 5 * 200 * 4 / 10 = 400
    */
    this.tune = function(){
        var candidates = [];

        // Initial population generation
        for(var i = 0; i < 100; i++){
            candidates.push(generateRandomCandidate());
        }

        console.log('Computing fitnesses of initial population...');
        computeFitnesses(candidates, 5, 200);
        sort(candidates);

        var count = 0;
        while(true){
            var newCandidates = [];
            for(var i = 0; i < 30; i++){ // 30% of population
                var pair = tournamentSelectPair(candidates, 10); // 10% of population
                //console.log('fitnesses = ' + pair[0].fitness + ',' + pair[1].fitness);
                var candidate = crossOver(pair[0], pair[1]);
                if(Math.random() < 0.05){// 5% chance of mutation
                    mutate(candidate);
                }
                normalize(candidate);
                newCandidates.push(candidate);
            }
            console.log('Computing fitnesses of new candidates. (' + count + ')');
            computeFitnesses(newCandidates, 5, 200);
            deleteNLastReplacement(candidates, newCandidates);
            var totalFitness = 0;
            for(var i = 0; i < candidates.length; i++){
                totalFitness += candidates[i].fitness;
            }
            console.log('Average fitness = ' + (totalFitness / candidates.length));
            console.log('Highest fitness = ' + candidates[0].fitness + '(' + count + ')');
            console.log('Fittest candidate = ' + JSON.stringify(candidates[0]) + '(' + count + ')');
            count++;
        }
    };
}

Download Source Code

Game Play :


  1. Untuk mode permainan ada dua tipe, yaitu manual dan auto. Mode auto jika kita ingin memainkan tetris secara otomatis (jalan sendiri).
  2. Gunakan tombol panah atas pada keyboard untuk mengubah jenis balok, tombol panah kiri dan kanan untuk menggeser balok dan tombol pana bawah untuk menurunkan balok.
  3. Tekan menu reset untuk memulai permainan baru jika sudah game over.
  4. Untuk memainkan game tetris ini, klik kanan pada file index.html dan buka dengan browser.

Rumah IT

Windows

[Windows][recentbylabel]
Notification
Welcome to Rumah IT . Please share this article to your favorite social media .
Done