js實現(xiàn)消滅星星(web簡易版)
昨天看視頻之后,整理思路,自己完成了簡易版消滅星星
思路:
模塊1:初始化
- 初始化總分?jǐn)?shù)、當(dāng)前分?jǐn)?shù)、背景圖、選擇的星星分?jǐn)?shù)
- 初始化星星(生成二維數(shù)組,對二維數(shù)組的每一個對象設(shè)置樣式(長、寬、背景圖),生成二維數(shù)組個div元素節(jié)點插入到游戲面板中)
模塊2:預(yù)判
判斷:
鼠標(biāo)移動到某一個方塊,判斷上下左右是否有連接著的小方塊(采用遞歸方法),然后將其存儲到數(shù)組choose[],移到其他方塊時,choose置為空
閃爍:
將已選中的小方塊設(shè)置樣式(縮放)
顯示選擇分?jǐn)?shù):
設(shè)置初始分?jǐn)?shù)和遞增分?jǐn)?shù),根據(jù)選中的塊數(shù)算出選中的分?jǐn)?shù)
模塊3:點擊
消失:
點擊已選中的小方塊,將連著的所有小方塊在二維數(shù)組的位置設(shè)置為空,清空choose數(shù)組
移動:
下移:設(shè)置一個指針,指向最下面的行。每當(dāng)行+1,若遇到不為空的方塊,則pointer++,若遇到該列某行為空,則將pointer的行數(shù)設(shè)為i
左移:最底部的一行若有一列為空,將右邊的所有方塊的列-1
判斷:
每次點擊完成之后判斷游戲是否結(jié)束
代碼部分
html
html結(jié)構(gòu)很簡單
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./index.js"></script> <link rel="stylesheet" href="index.css" > </head> <body> <div id="pop_star"> <div id="target_score">目標(biāo)分?jǐn)?shù):2000</div> <div id="now_score">當(dāng)前分?jǐn)?shù):0</div> <div id="select_score">0塊 0分</div> </div> </body> </html>
CSS
css布局也很簡單,相信不用我來說
* {
margin: 0px;
padding: 0px;
}
html, body {
height: 100%;
width: 100%;
}
#pop_star {
width: 500px;
height: 100%;
background: url("./pic/background.png");
margin-left: auto;
margin-right: auto;
position: relative;
background-size: cover;
font-size: 0px;
}
#target_score {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
color: white;
font-size: 20px;
position: relative;
}
#now_score {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
color: white;
font-size: 20px;
position: relative;
}
#select_score {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
color: white;
font-size: 20px;
position: relative;
opacity: 0;
}
JS
/*
創(chuàng)建二維數(shù)組
*
*
* */
var table ;
var suqareWidth = 50 ; //一個星星/方塊邊長
var boardWidth = 10 ; //橫豎方塊個數(shù)
var squareSet = [];//小方塊的集合,二維數(shù)組
var choose = [];//有相鄰的小方塊,將其放到這個數(shù)組
var timer = null ;
var baseScore = 5 ;
var stepScore = 10 ;
var totalScore = 0 ;
var targetScore = 1500;
var flag = true ;
var tempSquare = null;//在處理鼠標(biāo)動作過程中,動作被屏蔽,導(dǎo)致事件處理完成,有不連貫現(xiàn)象
function createSquare(value , row , col){
//創(chuàng)建小方塊節(jié)點
var blocks = document.createElement('div');
//設(shè)置樣式
blocks.style.width = suqareWidth + 'px';
blocks.style.height = suqareWidth + 'px';
blocks.style.display = 'inline-block';
blocks.style.boxSizing = 'border-box';
blocks.style.position = 'absolute';
blocks.style.borderRadius = "12px";
//小方塊的行和列,小方塊的num.jpg
blocks.num = value ;
blocks.row = row ;
blocks.col = col ;
return blocks;
}
function refresh(){
for(var i = 0 ; i < squareSet.length ; i ++){
for (var j = 0 ; j < squareSet[i].length ; j++) {
//嚴(yán)謹(jǐn)判斷
if (squareSet[i][j] == null) {
continue;
}
//將二維數(shù)組里面的小方塊對應(yīng)面板的行和列顯示
squareSet[i][j].row = i;
squareSet[i][j].col = j;
//列*方塊長度
squareSet[i][j].style.transition = "left 0.3s, bottom 0.3s";
squareSet[i][j].style.left = squareSet[i][j].col * suqareWidth + 'px';
squareSet[i][j].style.bottom = squareSet[i][j].row * suqareWidth + 'px';
//背景圖
squareSet[i][j].style.backgroundImage = "url('img/" + squareSet[i][j].num + ".png')";
squareSet[i][j].style.backgroundSize = 'cover';
squareSet[i][j].style.transform = 'scale(0.95)';//是圖片縮小至原來的0.95倍
}
}
}
function checkLinked(square , arr){
//嚴(yán)謹(jǐn)判斷
if(square == null){
return;
}
//添加小方塊到arr
arr.push(square);
/*
判斷位于該小方塊左邊的小方格是否能被收錄進(jìn)選擇數(shù)組
1.小方格不能是最左邊的
2.小方格左邊必須有小方塊
3.小方塊左邊的要和該小方塊顏色相同
4.該小方塊左邊沒有被收錄到數(shù)組中去
5.遞歸
*
* */
//向左
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 < boardWidth - 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 < boardWidth - 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);
}
//向上
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);
}
}
//讓選中的小方塊閃爍
function flicker(arr){
var num = 0 ;
//設(shè)置計時器,讓其一之閃爍
timer = setInterval(function(){
for (var i = 0 ; i < arr.length ; i++) {
//設(shè)置縮放樣式
arr[i].style.border = "3px solid #BFEFFF";
arr[i].style.transform = "scale("+(0.9 + 0.05 *Math.pow(-1 , num))+")";
}
//小方塊閃爍完成之后num++,使其再次縮放
num++;
},300);
}
function back(){
//若計時器還存在,清楚計數(shù)器
if(timer != null){
clearInterval(timer);
}
//返回原樣式
for(var i = 0 ; i < squareSet.length ; i++){
for(var j = 0 ; j < squareSet[i].length ; j++){
//嚴(yán)謹(jǐn)判斷
if (squareSet[i][j] == null) {
continue;
}
squareSet[i][j].style.border = "0px solid #BFEFFF";
squareSet[i][j].style.transform = "scale(0.95)";
}
}
}
//選中分?jǐn)?shù)
function selectScore(){
var socre = 0 ;
//遍歷choose
for(var i = 0 ; i < choose.length ; i++){
socre += baseScore + stepScore * i ;
}
//嚴(yán)謹(jǐn)判斷
if (socre <= 0) {
return ;
}
//設(shè)置select_score的樣式
var select_score = document.getElementById('select_score');
select_score.innerHTML = choose.length + "塊" + socre + "分";
select_score.style.transition = null ;
//設(shè)置透明度,讓其突然顯示
select_score.style.opacity = 1 ;
//讓其逐漸消失
setTimeout(function(){
select_score.style.transition = 'opacity 1s';
select_score.style.opacity = 0;
},1000);
}
//鼠標(biāo)移動到該小方塊時,閃爍
function mouseOver(obj){
//當(dāng)鼠標(biāo)在移動到該方塊突然移動到其他位置時
if(!flag){
tempSquare = obj;
return ;
}
//當(dāng)鼠標(biāo)移開選中的方塊之后,讓其回到原來的樣式
back();
//選擇相鄰相同的小方格
//傳一個數(shù)組
choose = [];
checkLinked(obj , choose);//obj是當(dāng)前鼠標(biāo)移到的小方塊,choose是存儲響鈴小方塊的數(shù)組
if (choose.length <= 1) {
choose = [] ;
return;
}
//將選中的設(shè)置樣式,讓其閃爍
flicker(choose);
//顯示所選中的小方塊的分?jǐn)?shù)
selectScore();
}
function move(){
/*
1.設(shè)置一個指針,開始的時候指針指向最下面一行
2.此時指針和j是否一樣,一樣都++。
3.若改行該列該列有小方塊,均++,反之j++,pointer不變,循環(huán)判斷該條件
3.當(dāng)j移動到該列某行的小方塊,該小方塊存在,則將j指向的小方塊的位置設(shè)置為指針指向的那一個小方塊的位置
* */
//向下移動
for (var i = 0 ; i < boardWidth ; i ++) {
var pointer = 0;//pointer指向小方塊,當(dāng)遇到null的時候停止,等待上面的小方塊落到這里來
for (var j = 0 ; j < boardWidth ; j ++) {
if (squareSet[j][i] != null) {
if (j != pointer) {
squareSet[pointer][i] = squareSet[j][i];
squareSet[j][i].row = pointer;
squareSet[j][i] = null;
}
pointer ++;
}
}
}
//橫向移動
for (var i = 0 ; i < squareSet[0].length ; ) {
if (squareSet[0][i] == null) {
for (var j = 0 ; j < boardWidth ; j ++) {
squareSet[j].splice(i, 1);
}
continue;
}
i ++;
}
refresh();
}
function isFinish(){
for (var i = 0 ; i < squareSet.length ; i++) {
for (var j = 0 ; j < squareSet[i].length ; j++) {
//判斷周圍是否還有可消除的方塊
var temp = [];
checkLinked(squareSet[i][j] , temp);
if(temp.length > 1){
return false ;
}
}
}
return true;
}
function init(){
//獲取面板
table = document.getElementById('pop_star');
//創(chuàng)建二維數(shù)組
for(var i = 0 ; i < boardWidth ; i++){
squareSet[i] = new Array();
for(var j = 0 ; j < boardWidth; j++){
//創(chuàng)建小方塊
var square = createSquare(Math.floor(Math.random() * 5), i, j);
//鼠標(biāo)移動到該方塊
square.onmouseover = function(){
mouseOver(this);
}
//點擊小方塊時的操作
square.onclick = function(){
//小方塊在被點擊的時候其他操作不能影響他的執(zhí)行
if(choose.length == 0 || !flag ){
return ;
}
flag = false;
tempSquare = null ;
/*
1.增加當(dāng)前分?jǐn)?shù)
2.小方塊消失
3.向下或想做移動
4.判斷游戲是否結(jié)束
*/
var socre = 0 ;
//遍歷choose
for(var i = 0 ; i < choose.length ; i++){
socre += baseScore + stepScore * i ;
}
totalScore += socre ;//總分?jǐn)?shù)
//改變樣式
document.getElementById('now_score').innerHTML = '當(dāng)前分?jǐn)?shù):' + totalScore;
//小方塊消失
/*
1.從二維數(shù)組里面移除選擇了的小方塊
2.在面板上移除div,不然div會一直占著格子
* */
for(var i = 0 ; i < choose.length ; i++){
//立即函數(shù),立即出發(fā)該函數(shù),否則的話,不會執(zhí)行
(function(i){
setTimeout(function(){
//將二維數(shù)組的某一值設(shè)置為空,后面的會向前移
squareSet[choose[i].row][choose[i].col] = null ;
//移除div
table.removeChild(choose[i]);
},i * 100);
})(i);
}
//移動
setTimeout(function(){
move();
setTimeout(function(){
var finished = isFinish();
if(finished){
if (totalScore >= targetScore) {
alert('闖關(guān)成功');
} else{
alert('闖關(guān)失敗');
}
}else{//還可以繼續(xù)
choose = [] ;
flag = true;
mouseOver(tempSquare);
}
} , 300 + choose.length * 150);
},choose.length * 100);
}
//將小方塊放進(jìn)二維數(shù)組
squareSet[i][j] = square;
//將創(chuàng)建好的小方塊插入到面板中
table.appendChild(square);
}
}
//顯示小星星,刷新整個面板
refresh();
}
//頁面加載完成之后,初始化所有操作
window.onload = function(){
init();
}
其實這里還有優(yōu)化的就是闖關(guān)部分,大致的思路就是,游戲每過一關(guān)增加目標(biāo)分?jǐn)?shù),當(dāng)游戲結(jié)束時,闖關(guān)失敗,目標(biāo)分?jǐn)?shù)恢復(fù)初始值。
大家有什么不懂,可以在評論區(qū)評論。
jq進(jìn)階版的源碼詳情見我github,網(wǎng)址
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于JavaScript實現(xiàn)文本一鍵復(fù)制和長按復(fù)制功能
本文主要內(nèi)容分三部分,第一部分是需求分析,第二部分是實現(xiàn)步驟,第三部分是問題詳解,如果您只需要解決問題,請閱讀第一、二部分即可,如果您有更多時間,進(jìn)一步學(xué)習(xí)問題相關(guān)知識點,請閱讀至第三部分2023-10-10
javascript設(shè)計模式之單體模式學(xué)習(xí)筆記
這篇文章主要為大家詳細(xì)介紹了javascript設(shè)計模式之單體模式學(xué)習(xí)筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02
JS實現(xiàn)導(dǎo)出Excel和CSV文件操作
這篇文章介紹了JS實現(xiàn)導(dǎo)出Excel和CSV文件的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
盤點javascript 正則表達(dá)式中 中括號的【坑】
下面小編就為大家?guī)硪黄P點javascript 正則表達(dá)式中 中括號的【坑】。小編覺得總結(jié)的不錯?,F(xiàn)在分享給大家,希望能給大家一個參考2016-03-03
layer彈出層自適應(yīng)高度,垂直水平居中的實現(xiàn)
今天小編就為大家分享一篇layer彈出層自適應(yīng)高度,垂直水平居中的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09

