Optimierung von Code (Spiel 2048)
tami
- javascript
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
@@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'
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
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