您的位置:首页 > Web前端 > JavaScript

动手学Javascript(1)——PopStar

2013-12-12 12:14 435 查看
PopStar是一款很流行的手机游戏。它的基本规则是在某个方块上单击,如果该方块周围有和它颜色一样的方块,那么这些方块都被选中。之后在选中方块的某一个上再次单击,所有选中的方块就会消失。

如下图所示,7个绿色的方块被选中(选中的方块被白色的框包围):



在选中的方块再次单击,这些绿色的方块就会消失。如果这些方块的上方就其他方块,上方的方块会掉下来。如果某一列全被消失,那么右边的列会自动左移。7块选中的绿色方块消失之后的效果如下图所示:



HTML代码如下所示:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>PopStar</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="PopStar.js" type="text/javascript">
</script>
<link rel="stylesheet" type="text/css" href="PopStar.css" />
</head>
<body>
<h1>Welcome to PopStar</h1>
<div id="totalScore">Total Score: 0</div>
<div id="currentScore">Click to Select.</div>
<div id="mainCanvas">
</div>
<div id="notification">
<div id="message"></div>
</div>
</body>
</html>
从上述代码可以看出,我们将会用到JQuery及jQuery UI的相关功能。

CSS的代码如下所示:

#mainCanvas {
background-color: black;
width: 300px;
height: 300px;
}

.block {
position: fixed;
height: 28px;
width: 28px;
border-radius: 4px;
}

.selected {
height: 26px;
width: 26px;
border-color: white;
border-style: solid;
border-width: 1px;
}
CSS主要定义了游戏的背景,以及方块(选中或未选中)的外观。

游戏的功能主要用Javascript实现,如下所示:

$(document).ready(function () {
var sharedData;
initGame();
startGame();

function initGame() {
sharedData = {};
sharedData.size = 10;

var canvas = $('#mainCanvas');
var width = parseInt(canvas.css('width'));
var height = parseInt(canvas.css('height'));
if (width != height) {
alert('the canvas should be a square.');
}
sharedData.canvas = canvas;
sharedData.blockLength = width / sharedData.size;
sharedData.matrix = initMatrix();

$('#notification').dialog({
width: 400,
resizable: false,
modal: true,
buttons: [{ text: "Ok", click: function () { $(this).dialog("close"); location.reload(); } }]
});
}

function startGame() {
sharedData.size = 10;
sharedData.status = 0; // possible values: 0, 1
sharedData.totalScore = 0;

clearMatrix();

initBlocks(sharedData);
moveBlocks();

clearCurrentScore();
clearTotalScore();
hideNotification();

if (isGameOver()) {
showNotification();
}
}

function initBlocks(data) {
var size = data.size;
var row, col, value;
var singleColor = size * size / 4;
var divString;
var newRow, newCol, index;

$('.block').each(function () {
$(this).remove();
});

var randomArray = getRandomArray(data.size);

for (row = 0; row < size; ++row) {
for (col = 0; col < size; ++col) {
if (row * size + col < singleColor) {
value = 1;
}
else if (row * size + col < singleColor * 2) {
value = 2;
}
else if (row * size + col < singleColor * 3) {
value = 3;
}
else {
value = 4;
}

index = randomArray[row * size + col];
newRow = Math.floor(index / size);
newCol = index % size;

divString = '<div class="block" currow="0" curcol="0" nextrow="' + newRow.toString()
+ '" nextcol="' + newCol.toString() + '" value="' + value.toString() + '"></div>';
$('#mainCanvas').append(divString);
}
}
}

function getRandomArray(size) {
var total = size * size;
var array = new Array(total);
var i, index, temp;

for (i = 0; i < array.length; ++i) {
array[i] = i;
}

for (i = array.length - 1; i > 0; --i) {
index = Math.floor(Math.random() * total);

temp = array[i];
array[i] = array[index];
array[index] = temp;
}

return array;
}

function moveBlocks() {
$('.block').each(function () {
var nextRow = $(this).attr('nextrow');
var nextCol = $(this).attr('nextcol');
var value = $(this).attr('value');
var parentPos = $(this).parent().offset();
var top = parseInt(nextRow) * sharedData.blockLength + parentPos.top + 1;
var left = parseInt(nextCol) * sharedData.blockLength + parentPos.left + 1;
var cssTop = top.toString() + 'px';
var cssLeft = left.toString() + 'px';
var colors = ['#aaaaaa', '#3333cc', '#33cc33', '#cc3333', '#cccc33'];

$(this).animate({
top: cssTop,
left: cssLeft
},
500);

$(this).css({
'background-color': colors[parseInt(value)]
});

$(this).attr('currow', nextRow);
$(this).attr('curcol', nextCol);
});
}

$('.block').click(function () {
var clickedBlock = getClickedBlockPos($(this));
var sameColorBlocks;

clearMatrix();
sameColorBlocks = getBlocksWithSameColor(clickedBlock.row, clickedBlock.col);
updateStatus(clickedBlock.row, clickedBlock.col, sameColorBlocks);
});

function updateStatus(row, col, sameColorBlocks) {
if (sameColorBlocks.length > 1) {
if (sharedData.status == 0) {
sharedData.status = 1;
setSelectedBlocks(sameColorBlocks);
}
else {
if (isClickAgain(row, col, sameColorBlocks)) {
moveMatrix(sharedData.matrix, sameColorBlocks);
sharedData.status = 0;
updateTotalScore(sharedData, sameColorBlocks.length);
clearSelectedBlocks();
moveBlocks();

clearMatrix();
if (isGameOver()) {
showNotification();
}
}
else {
setSelectedBlocks(sameColorBlocks);
}
}
}
else if (sharedData.status == 1) {
sharedData.status = 0;
clearSelectedBlocks();
}
}

function moveMatrix(matrix, sameColorBlocks) {
moveMatrixDown(matrix, sameColorBlocks);
moveMatrixLeft(matrix);
deleteBlocks();
updateBlockPosition();
}

function updateBlockPosition() {
$('.block').each(function () {
var curRow = parseInt($(this).attr('currow'));
var curCol = parseInt($(this).attr('curcol'));

var moveDown = sharedData.matrix[curRow][curCol].moveDown;
var moveLeft = sharedData.matrix[curRow][curCol].moveLeft;

var nextRow = curRow + moveDown;
var nextCol = curCol - moveLeft;

$(this).attr('nextrow', nextRow.toString());
$(this).attr('nextcol', nextCol.toString());
});
}

function deleteBlocks() {
$('.block').each(function () {
var curRow = parseInt($(this).attr('currow'));
var curCol = parseInt($(this).attr('curcol'));

if (sharedData.matrix[curRow][curCol].value == 0) {
$(this).remove();
}
});
}

function moveMatrixDown(matrix, toBeDeleted) {
var i, j;

toBeDeleted.sort(sortPosition);

for (i = 0; i < toBeDeleted.length; ++i) {
matrix[toBeDeleted[i].row][toBeDeleted[i].col].value = 0;

for (j = toBeDeleted[i].row ; j >= 0; --j) {
matrix[j][toBeDeleted[i].col].moveDown += 1;
}
}
}

function moveMatrixLeft(matrix) {
for (i = 0; i < matrix.length; ++i) {
if (isColumnBlank(matrix, i)) {
moveColumnsLeft(matrix, i);
}
}
}

function moveColumnsLeft(matrix, col) {
var i, j;
for(i = 0; i < matrix.length; ++i) {
for (j = col + 1; j < matrix.length; ++j)
matrix[i][j].moveLeft += 1;
}
}

function isColumnBlank(matrix, col) {
var row;
for (row = 0; row < matrix.length; ++row) {
if (matrix[row][col].value != 0)
return false;
}

return true;
}

function sortPosition(pos1, pos2) {
if ((pos1.col < pos2.col) || (pos1.col == pos2.col && pos1.row > pos2.row))
return -1;
if (pos1.col == pos2.col && pos1.row == pos2.row)
return 0;
return 1;
}

function setSelectedBlocks(sameColorBlocks) {
$('.block').each(function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
}
});

$('.block').each(function () {
var curRow = parseInt($(this).attr('currow'));
var curCol = parseInt($(this).attr('curcol'));

if(isSelected(sameColorBlocks, curRow, curCol) && !$(this).hasClass('selected')) {
$(this).addClass('selected');
}
});

setCurrentScore(sameColorBlocks.length);
}

function isSelected(sameColorBlocks, row, col) {
for (var i = 0; i < sameColorBlocks.length; ++i) {
if (sameColorBlocks[i].row == row && sameColorBlocks[i].col == col) {
return true;
}
}

return false;
}

function clearSelectedBlocks() {
$('.block').each(function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
}
});

clearCurrentScore();
}

function getClickedBlockPos(block) {
var curRow = parseInt(block.attr('currow'));
var curCol = parseInt(block.attr('curcol'));

return {
row: curRow,
col: curCol
};
}

function initMatrix() {
var i, j;
var size = sharedData.size;
var rows = new Array(size);

for (i = 0; i < size; ++i) {
rows[i] = new Array(size);
for (j = 0; j < size; ++j) {
rows[i][j] = {
value: 0,
moveDown: 0,
moveLeft: 0
};
}
}

return rows;
}

function clearMatrix() {
var i, j;
var size = sharedData.size;
var matrix = sharedData.matrix;

for (i = 0; i < size; ++i) {
for (j = 0; j < size; ++j) {
matrix[i][j] = {
value: 0,
moveDown: 0,
moveLeft: 0
};
}
}

$('.block').each(function () {
var value = parseInt($(this).attr('value'));
var curRow = parseInt($(this).attr('currow'));
var curCol = parseInt($(this).attr('curcol'));
sharedData.matrix[curRow][curCol].value = value;
});
}

function getBlocksWithSameColor(row, col) {
var matrix = sharedData.matrix;
var value = matrix[row][col].value, curValue;
var matrixSize = matrix[0].length;
var visited = new Array();
var top, curRow, curCol, preRow, preCol;
var sameColor = new Array();
var i;

var flag = new Array(matrixSize * matrixSize);
for (i = 0; i < flag.length; ++i) {
flag[i] = false;
}

addBlockWithSameColor(matrix, visited, sameColor, flag, row, col);

while (visited.length > 0) {
top = visited.pop();

// left
curRow = top.row;
curCol = top.col - 1;
addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);

// right
curRow = top.row;
curCol = top.col + 1;
addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);

// up
curRow = top.row - 1;
curCol = top.col;
addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);

// down
curRow = top.row + 1;
curCol = top.col;
addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);
}

return sameColor;
}

function addBlockWithSameColor(matrix, visited, sameColor, flag, row, col) {
var cell = {
row: row,
col: col
};

visited.push(cell);
sameColor.push(cell);
flag[row * matrix[0].length + col] = true;
}

function addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol) {
var matrixSize = matrix.length;
var isOnBoundaryOrDiffColor = curRow >= 0 && curRow < matrixSize &&
curCol >= 0 && curCol < matrixSize &&
matrix[curRow][curCol].value == value;
if (isOnBoundaryOrDiffColor && !flag[curRow * matrixSize + curCol]) {
addBlockWithSameColor(matrix, visited, sameColor, flag, curRow, curCol);
}
}

function isClickAgain(row, col, sameColor) {
var result = false;

$('.block').each(function () {
var curRow = parseInt($(this).attr('currow'));
var curCol = parseInt($(this).attr('curcol'));

if(isSelected(sameColor, curRow, curCol) && $(this).hasClass('selected')) {
result = true;
}
});

return result;
}

function setCurrentScore(num) {
var score = getScore(num);
$('#currentScore').html('Selection Score: ' + score.toString());
}

function clearCurrentScore() {
$('#currentScore').html('Click to Slect.');
}

function clearTotalScore() {
$('#totalScore').html('Total Score: 0');
}

function getScore(num) {
return 5 * num * num;
}

function updateTotalScore(data, num) {
var score = getScore(num);
data.totalScore += score;
$('#totalScore').html('Total Score: ' + data.totalScore.toString());
}

function hideNotification() {
$('#notification').dialog('close');
}

function showNotification() {
$('#message').html('Game over. Click Ok to restart.');
$('#notification').dialog('open');
}

function isGameOver() {
var over = true;
var curRow, curCol;
var sameColor;

$('.block').each(function () {
if (over) {
curRow = parseInt($(this).attr('currow'));
curCol = parseInt($(this).attr('curcol'));

sameColor = getBlocksWithSameColor(curRow, curCol);
if (sameColor.length > 1) {
over = false;
}
}
});

return over;
}
});
如果你对上述代码感兴趣,也可以到http://download.csdn.net/detail/haitaohe/6702475处下载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: