You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
7.3 KiB
299 lines
7.3 KiB
var score = 0;
|
|
var bestScore = 0;
|
|
var gridSize = 4;
|
|
var cellValues;
|
|
var availableCells;
|
|
//var labels = "PRC";
|
|
var labels = "2048";
|
|
var labelFunc;
|
|
var targetLevel = 11;
|
|
var checkTargetFlag = true;
|
|
|
|
switch (labels) {
|
|
case "2048":
|
|
labelFunc = function(n) {
|
|
return Math.pow(2, n).toString();
|
|
};
|
|
break;
|
|
case "PRC":
|
|
labelFunc = function(n) {
|
|
var dynasties = ["商", "周", "秦", "汉", "唐", "宋", "元", "明", "清", "ROC", "PRC"];
|
|
return dynasties[n-1];
|
|
};
|
|
break;
|
|
}
|
|
|
|
|
|
function startupFunction() {
|
|
// Initialize variables
|
|
score = 0;
|
|
checkTargetFlag = true;
|
|
var i;
|
|
var j;
|
|
|
|
cellValues = new Array(gridSize);
|
|
for (i = 0; i < gridSize; i++) {
|
|
cellValues[i] = new Array(gridSize);
|
|
for (j = 0; j < gridSize; j++)
|
|
cellValues[i][j] = 0;
|
|
}
|
|
|
|
updateAvailableCells();
|
|
refreshCellViews(2);
|
|
updateScore();
|
|
console.log("Started a new game");
|
|
}
|
|
|
|
function moveKey(event) {
|
|
if ((event.key == Qt.Key_Q) && (event.modifiers & Qt.ControlModifier)) {
|
|
Qt.quit();
|
|
}
|
|
|
|
var isMoved = false;
|
|
var i, j, v, v2;
|
|
var oldScore = score;
|
|
switch (event.key) {
|
|
case Qt.Key_Left:
|
|
for (i = 0; i < gridSize; i++) {
|
|
v = cellValues[i];
|
|
v2 = mergeVector(v);
|
|
if (! arraysIdentical(v,v2)) {
|
|
isMoved = true;
|
|
cellValues[i] = v2;
|
|
}
|
|
}
|
|
break;
|
|
case Qt.Key_Right:
|
|
for (i = 0; i < gridSize; i++) {
|
|
v = cellValues[i].slice();
|
|
v.reverse();
|
|
v2 = mergeVector(v);
|
|
if (! arraysIdentical(v,v2)) {
|
|
isMoved = true;
|
|
v2.reverse();
|
|
cellValues[i] = v2;
|
|
}
|
|
}
|
|
break;
|
|
case Qt.Key_Up:
|
|
for (i = 0; i < gridSize; i++) {
|
|
v = cellValues.map(function(row) {return row[i];});
|
|
v2 = mergeVector(v);
|
|
if (! arraysIdentical(v,v2)) {
|
|
isMoved = true;
|
|
for (j = 0; j < gridSize; j++) {
|
|
cellValues[j][i] = v2[j];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case Qt.Key_Down:
|
|
for (i = 0; i < gridSize; i++) {
|
|
v = cellValues.map(function(row) {return row[i];});
|
|
v.reverse();
|
|
v2 = mergeVector(v);
|
|
if (! arraysIdentical(v,v2)) {
|
|
isMoved = true;
|
|
v2.reverse();
|
|
for (j = 0; j < gridSize; j++) {
|
|
cellValues[j][i] = v2[j];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (isMoved) {
|
|
updateAvailableCells();
|
|
refreshCellViews(1);
|
|
if (oldScore !== score) {
|
|
if (bestScore < score) {
|
|
bestScore = score;
|
|
}
|
|
updateScore();
|
|
if (checkTargetFlag && maxTileValue() >= targetLevel) {
|
|
winMessage.open();
|
|
}
|
|
}
|
|
} else {
|
|
if (isDead()) {
|
|
deadMessage.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
function ind2sub(ind) {
|
|
var sub = [0, 0];
|
|
sub[0] = Math.floor(ind / gridSize);
|
|
sub[1] = ind % gridSize;
|
|
return sub;
|
|
}
|
|
|
|
function mergeVector(v0) {
|
|
// Pass 1: remove zero elements
|
|
var v = v0.slice();
|
|
var i = v.length;
|
|
while (i--) {
|
|
if (v[i] === 0) {
|
|
v.splice(i, 1);
|
|
}
|
|
}
|
|
// Pass 2: merge same elements
|
|
var v2 = [];
|
|
while (v.length > 0) {
|
|
if (v.length > 1 && v[0] === v[1]) {
|
|
v2.push(v[0] + 1);
|
|
score += parseInt(Math.pow(2, v[0]+1));
|
|
v.splice(0, 2);
|
|
} else {
|
|
v2.push(v[0]);
|
|
v.splice(0, 1);
|
|
}
|
|
}
|
|
|
|
// Fill the gaps with zeros
|
|
for (i = v2.length; i < v0.length; i++)
|
|
v2[i] = 0;
|
|
|
|
return v2;
|
|
}
|
|
|
|
function removeElementsWithValue(arr, val) {
|
|
var i = arr.length;
|
|
while (i--) {
|
|
if (arr[i] === val) {
|
|
arr.splice(i, 1);
|
|
}
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
function arraysIdentical(a, b) {
|
|
var i = a.length;
|
|
if (i !== b.length) return false;
|
|
while (i--) {
|
|
if (a[i] !== b[i]) return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
function updateAvailableCells() {
|
|
availableCells = [];
|
|
for (var i = 0; i < gridSize; i++) {
|
|
for (var j = 0; j < gridSize; j++) {
|
|
if (cellValues[i][j] === 0) {
|
|
availableCells.push(i * gridSize + j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function refreshCellViews(n) {
|
|
var i, sub;
|
|
|
|
// Popup a new number
|
|
for (i = 0; i < n; i++) {
|
|
var oneOrTwo = Math.random() < 0.9 ? 1: 2;
|
|
var randomCellId = availableCells[Math.floor(Math.random() * availableCells.length)];
|
|
|
|
sub = ind2sub(randomCellId);
|
|
cellValues[sub[0]][sub[1]] = oneOrTwo;
|
|
|
|
// Mark this cell as unavailable
|
|
var idx = availableCells.indexOf(randomCellId);
|
|
availableCells.splice(idx, 1);
|
|
}
|
|
|
|
// Refresh the cell views
|
|
for (i = 0; i < cells.count; i++) {
|
|
sub = ind2sub(i);
|
|
var cv = cellValues[sub[0]][sub[1]];
|
|
var sty = computeTileStyle(cv);
|
|
if ( cv === 0) {
|
|
cells.itemAt(i).tileText = "";
|
|
} else {
|
|
cells.itemAt(i).tileText = labelFunc(cv);
|
|
}
|
|
cells.itemAt(i).color = sty.bgColor;
|
|
cells.itemAt(i).tileColor = sty.fgColor;
|
|
cells.itemAt(i).tileFontSize = sty.fontSize;
|
|
}
|
|
|
|
}
|
|
|
|
function updateScore() {
|
|
scoreBoard.itemAt(0).scoreText = MyScript.score.toString();
|
|
scoreBoard.itemAt(1).scoreText = MyScript.bestScore.toString();
|
|
}
|
|
|
|
function isDead() {
|
|
var dead = true;
|
|
for (var i = 0; i < gridSize; i++) {
|
|
for (var j = 0; j < gridSize; j++) {
|
|
if (cellValues[i][j] === 0) {
|
|
dead = false;
|
|
}
|
|
if (i > 0) {
|
|
if (cellValues[i-1][j] === cellValues[i][j]) {
|
|
dead = false;
|
|
}
|
|
}
|
|
if (j > 0) {
|
|
if (cellValues[i][j-1] === cellValues[i][j]) {
|
|
dead = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return dead;
|
|
}
|
|
|
|
function computeTileStyle(n) {
|
|
var fgColors = ["#776E62", "#F9F6F2"];
|
|
var bgColors = ["#EEE4DA", "#EDE0C8", "#F2B179", "#F59563", "#F67C5F", "#F65E3B", "#EDCF72", "#EDCC61", "#EDC850", "#EDC53F", "#EDC22E", "#3C3A32"];
|
|
var sty = {bgColor: helper.myColors.bggray,
|
|
fgColor: fgColors[0],
|
|
fontSize: 55 };
|
|
if (n > 0) {
|
|
if (n > 2)
|
|
sty.fgColor = fgColors[1];
|
|
if (n <= bgColors.length)
|
|
sty.bgColor = bgColors[n-1];
|
|
else
|
|
sty.bgColor = bgColors[bgColors.length-1];
|
|
}
|
|
|
|
if (labels === "2048") {
|
|
/* Adjust font size according to size of the number
|
|
[2, 100): 55
|
|
[100, 1000): 45
|
|
[1000, 2048]: 35
|
|
> 2048: 30
|
|
*/
|
|
var pv = Math.pow(2, n);
|
|
if (pv >= 100 && pv < 1000)
|
|
sty.fontSize = 45;
|
|
else if (pv >= 1000 && pv <= 2048)
|
|
sty.fontSize = 35;
|
|
else if (pv > 2048)
|
|
sty.fontSize = 30;
|
|
|
|
}
|
|
|
|
return sty;
|
|
}
|
|
|
|
function maxTileValue() {
|
|
var mv = 0;
|
|
for (var i = 0; i < gridSize; i++) {
|
|
for (var j = 0; j < gridSize; j++) {
|
|
var cv = cellValues[i][j];
|
|
if ( mv < cv) {
|
|
mv = cv;
|
|
}
|
|
}
|
|
}
|
|
return mv;
|
|
}
|