渡一教育公开课web前端开发JavaScript精英课学习笔记(三十一)JavaScript消灭小星星游戏
JavaScript消灭小星星游戏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>消灭小星星</title>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
width: 100%;
}
#pop-star {
width: 500px;
height: 100%;
margin: 0 auto;
background-color: darkcyan;
position: relative;
}
.now-score {
width: 100%;
text-align: center;
line-height: 50px;
font-size: 20px;
color: #fff;
}
.select-score {
width: 100%;
text-align: center;
line-height: 50px;
font-size: 20px;
color: #fff;
opacity: 0.1;
transition: all 0.5s;
}
</style>
</head>
<body>
<div id='pop-star'>
</div>
</body>
<script>
var table = document.getElementById('pop-star');//游戏容器
var selectScore;//当前选定方块所得分数
var nowScore;//游戏得分
var squareWidth = 50;//小方块宽和高
var boardWidth = 10;//小方块行和列数
var squareSet = [];//小方块格子
var choose = [];//相连小方块集合
var styleMaxNum = 4;//小方块颜色最多多少种--8
var color = ['orange', 'green', 'red', 'blue', 'yellow','brown', 'darkmagenta', 'midnightblue'];//小方块颜色种类
var timer;//小方块闪烁定时器
var baseScore = 20;//消除小方块基础分数
var stepScore = 5;//每多消除一个小方块所得分数
var totalScore = 0;//总分数
// 创建小方块
function createSquare(style, row, col) {
var tempSquare = document.createElement('div');
tempSquare.style.width = squareWidth + 'px';
tempSquare.style.height = squareWidth + 'px';
tempSquare.style.display = "inlien-block";
tempSquare.style.position = 'absolute';
tempSquare.style.borderRadius = '12px';
tempSquare.style.boxSizing = 'border-box';
tempSquare.style.border = '3px solid #bfefff';
tempSquare.style.textAlign = 'center';
tempSquare.style.lineHeight = '44px';
tempSquare.style.transition = 'left 0.5s,bottom 0.5s';
tempSquare.num = style;
tempSquare.row = row;//行坐标,也就是 left
tempSquare.col = col;//列坐标,也就是 bottom
tempSquare.innerHTML = row + ',' + col;
return tempSquare;
}
// 重新设置小方块位置
function refresh() {
for (var i = 0; i < squareSet.length; i++) {
for (var j = 0; j < squareSet[i].length; j++) {
if (squareSet[i][j] == null) {
continue;
}
squareSet[i][j].row = i;
squareSet[i][j].col = j;
squareSet[i][j].style.left = squareSet[i][j].row * squareWidth + 'px';
squareSet[i][j].style.bottom = squareSet[i][j].col * squareWidth + 'px';
squareSet[i][j].style.backgroundColor = color[squareSet[i][j].num];
}
}
}
// 鼠标移入小方块事件
function mouseOver(obj) {
// 恢复小方块样式
goBack();
// 相连的小方块暂存数组
choose = [];
// 查找相连的小方块
checkLinked(obj, choose);
if (choose.length <= 1) {
choose = null;
// 隐藏得分提示
selectScore.style.transition = 'all 0.5s';
selectScore.style.opacity = 0;
} else {
// 可以消掉的小方块闪烁
flicker(choose);
// 计算可得分数
var score = computeScore(choose);
// 显示提示分数
selectScore.style.transition = null;
selectScore.innerHTML = '可消除 ' + choose.length + ' 块,得 ' + score + ' 分';
selectScore.style.opacity = 1;
}
}
// 计算分数
function computeScore(arr) {
var score = baseScore;
for (var i = 0; i < arr.length; i++) {
score += i * stepScore;
}
return score;
}
// 使相连的小方块闪烁
function flicker(arr) {
var num = 0;
timer = setInterval(function () {
for (var i = 0; i < arr.length; i++) {
arr[i].style.border = '3px solid #bfefff';
arr[i].style.transform = 'scale(' + (0.9 + 0.05 * Math.pow(-1, num)) + ')';
}
num++;
}, 300);
}
// 小方块恢复初始样式
function goBack() {
if (timer != null) {
clearInterval(timer);
}
for (var i = 0; i < squareSet.length; i++) {
for (var j = 0; j < squareSet[i].length; j++) {
if (squareSet[i][j] != null) {
squareSet[i][j].style.border = '3px solid #bfefff';
squareSet[i][j].style.transform = 'scale(1)';
}
}
}
}
// 查询相连的同色小方块,保存的数组中
function checkLinked(square, arr) {
if (square == null) {
return;
}
arr.push(square);
// 判断上下左右是否有同样的星星
if (square.col > 0
&& squareSet[square.row][square.col - 1]
&& squareSet[square.row][square.col - 1].num == square.num
&& arr.indexOf(squareSet[square.row][square.col - 1]) == -1) {
checkLinked(squareSet[square.row][square.col - 1], arr)
}
if (square.col < squareSet[0].length - 1
&& squareSet[square.row][square.col + 1]
&& squareSet[square.row][square.col + 1].num == square.num
&& arr.indexOf(squareSet[square.row][square.col + 1]) == -1) {
checkLinked(squareSet[square.row][square.col + 1], arr)
}
if (square.row > 0
&& squareSet[square.row - 1][square.col]
&& squareSet[square.row - 1][square.col].num == square.num
&& arr.indexOf(squareSet[square.row - 1][square.col]) == -1) {
checkLinked(squareSet[square.row - 1][square.col], arr)
}
if (square.row < squareSet.length - 1
&& squareSet[square.row + 1][square.col]
&& squareSet[square.row + 1][square.col].num == square.num
&& arr.indexOf(squareSet[square.row + 1][square.col]) == -1) {
checkLinked(squareSet[square.row + 1][square.col], arr)
}
}
function isGameOver() {
for (var i = 0; i < squareSet.length; i++) {
for (var j = 0; j < squareSet[i].length; j++) {
if (squareSet[i][j] != null) {
let tempArr = [];
checkLinked(squareSet[i][j], tempArr);
if (tempArr.length > 1) {
console.log('false');
return false;
}
}
}
}
console.log('true');
return true;
}
function moveSquare() {
// 比较笨的方法 不使用中间变量,使用for循环变量累加
// for (var i = 0; i < squareSet.length; i++) {
// for (var j = 0; j < squareSet[i].length; j++) {
// if (squareSet[i][j] == null) {
// //如果 j 的位置为空,就以 J 为基准,向上查找不为空的方块,并移动到 j 的位置
// for (var k = j + 1; k < boardWidth; k++) {
// if (squareSet[i][k] != null) {
// squareSet[i][j] = squareSet[i][k];
// squareSet[i][j].col = j;
// squareSet[i][k] = null;
// break;
// }
// }
// }
// }
// }
// 使用讲师的方法
for (var i = 0; i < squareSet.length; i++) {
var currentPoint = 0;//记录为空的位置,初始从最下面开始找。
for (var j = 0; j < squareSet[i].length; j++) {
if (squareSet[i][j] != null) {
// 如果j 等于 currentPoint 说明是同一个方块,不做处理。
if (j != currentPoint) {
squareSet[i][currentPoint] = squareSet[i][j];
squareSet[i][currentPoint].col = currentPoint;
squareSet[i][j] = null;
}
currentPoint++;//当前位置不为空,就向上提一个位置。
}
}
}
// 移除空列
for (var m = 0; m < squareSet.length;) {
if (squareSet[m][0] == null) {
// 移除数组中为空列的项
squareSet.splice(m, 1);
} else {
// 不在 for 循环里累加的作用,就是在移除当前列后,移除列的下一列变成当前列(序号 m 指向新的列),而这一列还没有做判断,所有序号不能累加。
m++;
}
}
refresh();
console.log('moveSquare');
if (isGameOver()) {
alert("Game over !");
init();
}
}
function mouseClick(square) {
let chooseSquare = [];
checkLinked(square, chooseSquare);
if (chooseSquare.length <= 1) {
return;
}
// 计算分数
totalScore += computeScore(chooseSquare);
nowScore.innerHTML = '当前分数:' + totalScore;
// 移除小方块 挨个移除。
for (var i = 0; i < chooseSquare.length; i++) {
(function (i) {
setTimeout(() => {
table.removeChild(chooseSquare[i]);
squareSet[chooseSquare[i].row][chooseSquare[i].col] = null;
}, i * 100);
})(i)
}
//小方块向下掉落
setTimeout(() => {
moveSquare();
}, i * 100);
}
function bindEvents(square) {
square.onmouseover = function () {
mouseOver(this);
};
// 在小方块上点击鼠标
square.onclick = function () {
mouseClick(this)
}
}
function init() {
table.innerHTML = '';
nowScore = document.createElement('div');
selectScore = document.createElement('div');
nowScore.className = 'now-score';
nowScore.innerHTML = '当前分数:' + totalScore;
selectScore.className = 'select-score';
table.appendChild(nowScore);
table.appendChild(selectScore);
squareSet = [];
for (var i = 0; i < boardWidth; i++) {
squareSet[i] = new Array();
for (var j = 0; j < boardWidth; j++) {
squareSet[i][j] = createSquare(Math.floor(Math.random() * styleMaxNum), i, j);
bindEvents(squareSet[i][j]);
table.appendChild(squareSet[i][j]);
}
}
refresh();
}
window.onload = function () {
init();
}
</script>
</html>