tami: Optimierung von Code (Spiel 2048)

hi,

aus Lerngründen würde ich gerne folgenden von mir verfassten Code optimieren. Ich hatte bereits versucht, mehrere Funktionen innerhalb andere Funktionen (zB. init) zu deklarierern, weil sie nur dort benötigt werden, aber da schmierte mir der Browser ab. Ich vermute, dass er sich da mit dem Speicher und den closures verhaspelt hat.

Habe jetzt alle Funktionen in einem Objekt gehängt, um den globalen Scope nicht zu verschmutzen. Auch wenn die Funktionen teilweise nur innerhalb einer anderen Funktion einmal benutzt werden. Habe aber auch Funktionen innerhalb von Funktionen (allerdings nur einfach verschachtelt) defniniert, weil sie eben nur da gebraucht werden.

Für Tipps und Tricks (aus Gründen des allgemeinen Verständnisses) wäre ich dankbar. Hier der code:

  
<html>  
<head>  
<style type="text/css">
table, td {  
    border: 1px solid black;  
    margin: auto;  
    font-weight: bold;  
    color: white;  
    font-size: 2em;  
    font-family: arial;	  
}  
td {  
    height: 100px;  
    width: 100px;  
    vertical-align: center;  
    text-align: center;  
}
</style>  
</head>  
<body id="body">  
<div id="div2048"></div>  
<script>
var MyColors = ["white", "red", "green", "blue", "pink", "brown", "purple", "yellow", "orange", "pink", "cyan", "crimson"];  
var My2048 = {  
    "cells" : [],  
    "htmlCells" : [],  
    "tmpTr" : [],  
    "calcRow" : function (row) {  
        "use strict";  
        var tmpRow = [],  
            calc2,  
            i;  
        // calc two cells if equal - tmpRow is read- and writeCell2Htmlable within function  
        calc2 = function (calcPos) {  
            if (tmpRow[calcPos] === tmpRow[calcPos - 1]) {  
                tmpRow[calcPos - 1] *= 2;  
                tmpRow.splice(calcPos, 1);  
            }  
        };  
        //delete empty cells - copy to tmpRow array  
        for (i = 0; i < row.length; i += 1) {  
            if (row[i] !== 1) {  
                tmpRow.push(row[i]);  
            }  
        }  
        // walk through array to call "calc two cells if equal"  
        for (i = 1; i < tmpRow.length; i += 1) {  
            calc2(i);  
        }  
        // fill up with empty cells at the end for return  
        while (tmpRow.length < 4) {  
            tmpRow.push(1);  
        }  
        return tmpRow;  
    },  
    "iterate2Dim" : function (callBack, res) {  
        "use strict";  
        var i,  
            j;  
        for (i = 0; i < 4; i += 1) {  
            for (j = 0; j < 4; j += 1) {  
                callBack(i, j, res);  
            }  
        }  
        return res;  
    },  
    "setNewNumber" : function () {  
        "use strict";  
        var tmpArray = [],  
            collectEmptyCellIndices,  
            myRand;  
        collectEmptyCellIndices = function (i, j, res) {  
            if (My2048.cells[i][j] === 1) {  
                res.push([i, j]);  
            }  
        };  
        tmpArray = My2048.iterate2Dim(collectEmptyCellIndices, tmpArray);  
        if (tmpArray.length === 0) {  
            alert("game over");  
        } else {  
            myRand = Math.floor((Math.random() * tmpArray.length));  
            My2048.cells[tmpArray[myRand][0]][tmpArray[myRand][1]] = 2;  
        }  
    },  
    "writeCell2Html" : function (i, j) {  
        "use strict";  
        My2048.htmlCells[i][j].innerHTML = My2048.cells[i][j];  
        My2048.htmlCells[i][j].style.backgroundColor = MyColors[Math.log(My2048.cells[i][j]) / Math.log(2)];  
    },  
    "move" : function (keyCode) {  
        "use strict";  
        var flipMyCells,  
            i,  
            tmpRow = [],  
            tmpTable = [];  
        flipMyCells = function () {  
            var j,  
                cache;  
            for (i = 0; i < 3; i += 1) {  
                for (j = i + 1; j < 4; j += 1) {  
                    cache = My2048.cells[i][j];  
                    My2048.cells[i][j] = My2048.cells[j][i];  
                    My2048.cells[j][i] = cache;  
                }  
            }  
        };  
        if (keyCode === 38 || keyCode === 40) {  
            flipMyCells();  
        }  
        tmpTable = My2048.cells;  
        for (i = 0; i < 4; i += 1) {  
            tmpRow = tmpTable[i];  
            if (keyCode === 39 || keyCode === 40) {  
                tmpRow.reverse();  
            }  
            tmpRow = My2048.calcRow(tmpRow);  
            if (keyCode === 39 || keyCode === 40) {  
                tmpRow.reverse();  
            }  
            tmpTable[i] = tmpRow;  
            tmpRow = [];  
        }  
        if (keyCode === 38 || keyCode === 40) {  
            flipMyCells();  
        }  
        My2048.cells = tmpTable;  
    },  
    "init" : function () {  
        "use strict";  
        var div2048 = document.getElementById("div2048"),  
            myTable = document.createElement("table"),  
            i,  
            fillCellsAndBuildTable = function (i, j) {  
                var tmpHtmlTd;  
                My2048.cells[i][j] = 1;  
                tmpHtmlTd = document.createElement("td");  
                My2048.tmpTr[i].appendChild(tmpHtmlTd);  
                My2048.htmlCells[i].push(tmpHtmlTd);  
            };  
        div2048.appendChild(myTable);  
        for (i = 0; i < 4; i += 1) {  
            My2048.tmpTr[i] = document.createElement("tr");  
            myTable.appendChild(My2048.tmpTr[i]);  
            My2048.cells[i] = [];  
            My2048.htmlCells[i] = [];  
        }  
        document.getElementsByTagName("body")[0].onkeydown = function (event) {  
            event = event || window.event;  
            if (36 < event.keyCode && event.keyCode < 41) {  
                My2048.move(event.keyCode);  
                My2048.setNewNumber();  
                My2048.iterate2Dim(My2048.writeCell2Html);  
            }  
        };  
        My2048.iterate2Dim(fillCellsAndBuildTable, myTable);  
        My2048.setNewNumber();  
        My2048.iterate2Dim(My2048.writeCell2Html);  
    }  
};  
My2048.init();
</script>  
</body>  

bzw. http://html-ag.wvs-berlin.de/Javascript/2048.js.html.

Mit den Pfeiltasten rauf/runter/rechts/links kann man spielen ;-).

(ach so, der Code ist jslint-konform, ist so ein tick von mir)

mfg

tami

  1. @@tami:

    nuqneH

    Du hast einen Progammierfehler drin. In deiner Version kann man auch in eine Richtung schieben, wenn es gar nichts zusammenzuschieben gibt. Dann wird einfach ein neues Teil erzeugt.

    Bei http://gabrielecirulli.github.io/2048/ sind solch ungültige Züge nicht möglich.

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. hi,

      @@tami:

      nuqneH

      Du hast einen Progammierfehler drin. In deiner Version kann man auch in eine Richtung schieben, wenn es gar nichts zusammenzuschieben gibt. Dann wird einfach ein neues Teil erzeugt.

      Bei http://gabrielecirulli.github.io/2048/ sind solch ungültige Züge nicht möglich.

      Cool ;-). Ich wusste doch, dass da was nicht stimmt ...;

      mfg

      tami

    2. hi,

      @@tami:

      nuqneH

      Du hast einen Progammierfehler drin. In deiner Version kann man auch in eine Richtung schieben, wenn es gar nichts zusammenzuschieben gibt. Dann wird einfach ein neues Teil erzeugt.

      Bei http://gabrielecirulli.github.io/2048/ sind solch ungültige Züge nicht möglich.

      Jetzt aber http://html-ag.wvs-berlin.de/Javascript/2048_korr1.js.html

      <html>  
      <head>  
      <style type="text/css">
      
      table, td {  
          border: 1px solid black;  
          margin: auto;  
          font-weight: bold;  
          color: white;  
          font-size: 2em;  
          font-family: arial;	  
      }  
      td {  
          height: 100px;  
          width: 100px;  
          vertical-align: center;  
          text-align: center;  
      }
      
      </style>  
      </head>  
      <body id="body">  
      <div id="div2048"></div>  
      <script>
      ~~~~~~javascript
        
      var MyColors = ["white", "red", "green", "blue", "pink", "brown", "purple", "yellow", "orange", "pink", "cyan", "crimson"];  
      var My2048 = {  
          cells : [],  
          htmlCells : [],  
          tmpTr : [],  
          moved : false,  
          calcRow : function (row) {  
              "use strict";  
              var tmpRow = [],  
                  calc2,  
                  i;  
              // calc two cells if equal - tmpRow is read- and writeCell2Htmlable within function  
              calc2 = function (calcPos) {  
                  if (tmpRow[calcPos] === tmpRow[calcPos - 1]) {  
                      tmpRow[calcPos - 1] *= 2;  
                      tmpRow.splice(calcPos, 1);  
                      My2048.moved = true;  
                  }  
              };  
              //delete empty cells - copy to tmpRow array  
              for (i = 0; i < row.length; i += 1) {  
                  if (row[i] !== 1) {  
                      tmpRow.push(row[i]);  
                  }  
              }  
              // walk through array to call "calc two cells if equal"  
              for (i = 1; i < tmpRow.length; i += 1) {  
                  calc2(i);  
              }  
              // fill up with empty cells at the end for return  
              while (tmpRow.length < 4) {  
                  tmpRow.push(1);  
              }  
              return tmpRow;  
          },  
          iterate2Dim : function (callBack, res) {  
              "use strict";  
              var i,  
                  j;  
              for (i = 0; i < 4; i += 1) {  
                  for (j = 0; j < 4; j += 1) {  
                      callBack(i, j, res);  
                  }  
              }  
              return res;  
          },  
          setNewNumber : function () {  
              "use strict";  
              var tmpArray = [],  
                  collectEmptyCellIndices,  
                  myRand;  
              collectEmptyCellIndices = function (i, j, res) {  
                  if (My2048.cells[i][j] === 1) {  
                      res.push([i, j]);  
                  }  
              };  
              tmpArray = My2048.iterate2Dim(collectEmptyCellIndices, tmpArray);  
              if (tmpArray.length === 0) {  
                  alert("game over");  
              } else {  
                  myRand = Math.floor((Math.random() * tmpArray.length));  
                  My2048.cells[tmpArray[myRand][0]][tmpArray[myRand][1]] = 2;  
              }  
          },  
          writeCell2Html : function (i, j) {  
              "use strict";  
              My2048.htmlCells[i][j].innerHTML = My2048.cells[i][j];  
              My2048.htmlCells[i][j].style.backgroundColor = MyColors[Math.log(My2048.cells[i][j]) / Math.log(2)];  
          },  
          move : function (keyCode) {  
              "use strict";  
              var flipMyCells,  
                  equalRows,  
                  i,  
                  tmpRow = [],  
                  controlRow = [],  
                  tmpTable = [];  
              flipMyCells = function () {  
                  var j,  
                      cache;  
                  for (i = 0; i < 3; i += 1) {  
                      for (j = i + 1; j < 4; j += 1) {  
                          cache = My2048.cells[i][j];  
                          My2048.cells[i][j] = My2048.cells[j][i];  
                          My2048.cells[j][i] = cache;  
                      }  
                  }  
              };  
              equalRows = function (row1, row2) {  
                  var j;  
                  for (j = 0; j < 4; j += 1) {  
                      if (row1[j] !== row2[j]) {  
                          return false;  
                      }  
                  }  
                  return true;  
        
              };  
              if (keyCode === 38 || keyCode === 40) {  
                  flipMyCells();  
              }  
              tmpTable = My2048.cells;  
              for (i = 0; i < 4; i += 1) {  
                  tmpRow = tmpTable[i];  
                  controlRow = tmpTable[i];  
                  if (keyCode === 39 || keyCode === 40) {  
                      tmpRow.reverse();  
                  }  
                  tmpRow = My2048.calcRow(tmpRow);  
                  if (!equalRows(controlRow, tmpRow)) {  
                      My2048.moved = true;  
                  }  
                  if (keyCode === 39 || keyCode === 40) {  
                      tmpRow.reverse();  
                  }  
                  tmpTable[i] = tmpRow;  
                  controlRow = [];  
                  tmpRow = [];  
              }  
              if (keyCode === 38 || keyCode === 40) {  
                  flipMyCells();  
              }  
              My2048.cells = tmpTable;  
          },  
          init : function () {  
              "use strict";  
              var div2048 = document.getElementById("div2048"),  
                  myTable = document.createElement("table"),  
                  i,  
                  fillCellsAndBuildTable = function (i, j) {  
                      var tmpHtmlTd;  
                      My2048.cells[i][j] = 1;  
                      tmpHtmlTd = document.createElement("td");  
                      My2048.tmpTr[i].appendChild(tmpHtmlTd);  
                      My2048.htmlCells[i].push(tmpHtmlTd);  
                  };  
              div2048.appendChild(myTable);  
              for (i = 0; i < 4; i += 1) {  
                  My2048.tmpTr[i] = document.createElement("tr");  
                  myTable.appendChild(My2048.tmpTr[i]);  
                  My2048.cells[i] = [];  
                  My2048.htmlCells[i] = [];  
              }  
              document.getElementsByTagName("body")[0].onkeydown = function (event) {  
                  event = event || window.event;  
                  if (36 < event.keyCode && event.keyCode < 41) {  
                      My2048.move(event.keyCode);  
                      if (My2048.moved === true) {  
                          My2048.setNewNumber();  
                      }  
                      My2048.iterate2Dim(My2048.writeCell2Html);  
                      My2048.moved = false;  
                  }  
              };  
              My2048.iterate2Dim(fillCellsAndBuildTable, myTable);  
              My2048.setNewNumber();  
              My2048.iterate2Dim(My2048.writeCell2Html);  
              My2048.moved = true;  
          }  
      };  
      My2048.init();
      ~~~~~~html
        
      </script>  
      </body>  
      
      

      mfg

      tami