不得不說,作遊戲是會上癮的,此次帶來的是win系統上的經典遊戲《蜘蛛紙牌》,不能完美,但求一玩css
DEMO:html
http://colorgamer.com/demo/webgame/spider/web
規則請打開win系統的蜘蛛紙牌,而後點擊幫助數組
綜合起來,《蜘蛛紙牌》基本上就這麼6個問題,解決了,也就完成了。下面一個一個來實現app
光洗牌,不難。若是要作到每次洗牌都有解就不是我能解決的問題了(win系統裏的蜘蛛紙牌是否是每次都有解,我確實不知道)。這裏就隨便洗洗,沒解也沒辦法,即便有解,你也不必定能解完,是吧。dom
這裏是同色,因此不用去考慮4個花色,那一副牌,從A-K,是13張,有4組,就是13*4=52張牌。兩副就是104張。先初始化一組牌ide
var _cards_init=['1','2','3','4','5','6','7','8','9','10','J','Q','K'];
跟着把它變成1副牌post
_cards_init=_cards_init.concat(_cards_init,_cards_init,_cards_init); //使用concat來連接數組
這裏本身連接本身3次,就變成了4組,一副牌。再接着連接本身一次,就變成兩副牌動畫
_cards_init=_cards_init.concat(_cards_init);
兩副牌有了,接着就洗牌,這裏簡單的使用隨機數來洗。this
//洗牌 function shuffle(){ var len=_cards_init.length; if(len>0){ var i=random(len); _cards.push(_cards_init[i]); _cards_init.splice(i,1); shuffle(); } }
這是一個遞歸,每次從初始化的剩餘牌序列裏隨機取一個,放到新牌的數組裏,而後將取走的牌從初始化的數組裏移除,重計長度,只要長度不小於1,那麼重複這個操做,至到所有取完爲止。這樣生成的新牌數組裏的牌基本上就是亂序了,達到洗牌的效果。
牌洗好以後,就得將最開始的牌面放到界面上。win7的蜘蛛紙牌是10列,前4列5張扣牌,1張明牌,後6列4張扣牌,1張明牌。這裏也按這樣的方式開始。
由於是按列爲基礎進行擺牌,因此程序在肯定牌所在位置的時候,須要分別記錄,每一列等因而一個序列,有牌移進來,要增長它的長度,有牌移走的時候,要減小它的長度。因此這裏使用了一個數組來分別記錄牌的信息
var _cards_table=new Array();
接着肯定位置,按照初始化的界面,一共要放54張牌到牌面上,其中44張是扣牌,10張是明牌,因此,先重新牌數組裏取54張牌出來,其中前10張,也就是0-9,是個位數,直接將下標作了牌的參數
for(var i=0;i<10;i++){ _cards_table[i]=new Array(); } var _html_cards_table=''; for(var i=0;i<54;i++){ if(i<=9){ j=i; _html_cards_table+="<div class='cardbg cardbg"+j+"' action-t='' action-line='"+j+"'></div>"; }else{ var s=i.toString(); j=s.substring(s.length-1); } j=parseInt(j); var num=cardNum(_cards[i]); var back=''; //背面牌 if(i>=0&&i<44){ back='back'; } var l=_cards_table[j].length; _html_cards_table+="<div class='card cardv"+num+" card"+j+" "+back+"' action-t='"+back+"' action-line='"+j+"' action-index='"+l+"' style='z-index:1;position:absolute;left:"+_cardsPostion[0]+"px;top:"+_cardsPostion[1]+"px;'>"+_cards[i]+"</div>"; _cards_table[j].push(num); }
其實,這裏固定牌的位置,直接使用了CSS樣式,不太好,由於有時候你不知道到底一列會出現多少個紙牌,要是CSS樣式寫少了,那多出來的紙牌放的位置就會出現問題。最好的辦法是JS直接判斷索引值,根據索引值*固定數來肯定位置。
這些牌放出去後,天然得將它們重新牌的數組裏移除,之後發牌,就是數組裏剩下的牌了
_cards.splice(0,54); _cards_table+='<div id="post">發牌<span id="postnum">5</span></div>'; //順便添加一個發牌的按鈕 $("#game_map").html(_cards_table); //將生成的牌放到遊戲地圖上
這裏除了這些初始牌面外,還有一個東西,那就是隱藏的一個牌,由於每列的牌都有可能徹底的移出,這時候符合條件的牌序列又能夠移到這個空列裏來,因此,得在那個位置放一個看不見的牌,但這個牌只有列號,沒有其它的東西。
if(i<=9){ j=i; _cards_table+="<div class='cardbg cardbg"+j+"' action-t='' action-line='"+j+"'></div>"; }
首先,得爲各牌添加單擊事件。而後第一次點的牌要記錄下它的3個東西:一、所在列。二、列上的索引值。三、牌面值(A-K)。再次點擊其它牌的時候,進行判斷,它是否是符合移動條件,如:被點擊牌及以後的牌序列是否是符合條件(遞減),目標牌是否是比第一次點擊牌大1,若是是,移動牌到新位置,若是不是,給出提示,不符合條件
function clickCard(){ $(".card").unbind('click').click(function(){ var line=$(this).attr('action-line'); var back=$(this).attr('action-t'); if(back){ return false; } var index=parseInt($(this).attr('action-index')); var cards_num; line=parseInt(line); cards_num=_cards_table[line][index]; if(_cards_selected.length==1){ if((cards_num-1)==_cards_selected[0][2]){ var _index=index+1; moveCard(line,_index,_cards_selected[0][2]); }else{ alert('不能移動到那個位置2_'+cards_num+'_'+_cards_selected[0][2]); } css_remove(); _cards_selected.shift(); clickCard(); }else{ if(getCards(line,index)==0){ _cards_selected[0]=[]; _cards_selected[0][0]=line; _cards_selected[0][1]=index; _cards_selected[0][2]=cards_num; }else{ css_remove(); } } }); }
移走了,也就得把它從該列的數組裏清除掉,這裏使用splice(),只須要傳入起始索引值,將它和它以後的全部牌都清除。而後建立新的牌加入到目標列的數組裏
function moveCard(line,index,cards_num){ line=parseInt(line); var len=_cards_table[_cards_selected[0][0]].length; _cards_table[_cards_selected[0][0]].splice(_cards_selected[0][1],len); var html=''; var moveCardIndex=index; _moveCardNum=len-_cards_selected[0][1]; for(var i=_cards_selected[0][1];i<len;i++){ var v=$(".card"+_cards_selected[0][0]).eq(_cards_selected[0][1]).html(); var o=$(".card"+_cards_selected[0][0]).eq(_cards_selected[0][1]); var num=cardNum(o.html()); _cards_table[line].push(num); var cardline=o.attr('action-line'); o.removeClass('card'+cardline); o.addClass('card'+line); o.attr('action-line',line); o.attr('action-index',moveCardIndex); move_animation(o,line,moveCardIndex,1); moveCardIndex++; } $(".card"+_cards_selected[0][0]).eq(_cards_selected[0][1]-1).removeClass('back'); $(".card"+_cards_selected[0][0]).eq(_cards_selected[0][1]-1).attr('action-t',''); $("#scores").html(parseInt($("#scores").html())+1); }
checkComplate(line);用於判斷是否已經實現A-K,若是是將它清除
首先判斷該列的紙牌數是否超過13張,由於若是連13張都沒有,又怎麼會有完整的A-K呢。以後再判斷明牌是否是有13張,並且明顯的大小是否是從大到小減1的。若是都符合,那將它們所有清除,並從該列的數組裏將它們清除。
function checkComplate(line){ var obj=$(".card"+line) var len=obj.length; var preNum=0; var error=0; var comNum=[]; if(len>=13){ for(var i=0;i<len;i++){ if(obj.eq(i).attr('action-t')==''){ if(preNum>0){ if(parseInt(cardNum(obj.eq(i).html()))+1==preNum){ }else{ comNum=[]; } comNum.push(i); }else{ comNum.push(i); } preNum=parseInt(cardNum(obj.eq(i).html())); } } if(comNum.length>=13){ for(var i in comNum){ obj.eq(comNum[i]).remove(); if(i==0){ obj.eq(comNum[i]-1).removeClass('back'); obj.eq(comNum[i]-1).attr('action-t',''); var len=_cards_table[line].length; _cards_table[line].splice(comNum[i],len); } } _left_group--; if(_left_group==0){ alert('你贏了,共移動'+$('#scores').html()+'次'); $("#re").click(); } } } }
發牌其實和初始化牌面沒什麼區別,只是每次只發10張,也就是向0-9列分別增長一張牌,發出去後,剩於牌就減去這些牌
function post(){ $("#post").click(function(){ if(_cards.length<=0){ alert('無牌可發了'); return false; } var _html_cards_table=''; for(var i=0;i<10;i++){; var num=cardNum(_cards[i]); var l=_cards_table[i].length; _html_cards_table+="<div class='card cardv"+num+" card"+i+"' action-t='' action-index='"+l+"' action-line='"+i+"' style='z-index:1;position:absolute;left:"+_cardsPostion[0]+"px;top:"+_cardsPostion[1]+"px;'>"+_cards[i]+"</div>"; _cards_table[i].push(num); } _cards.splice(0,10); var cardbenum=$(".card").length; $("#game_map").append(_html_cards_table); var _i=cardbenum; var _this=this; this.move_animation=function(){ var line=$(".card").eq(_i).attr('action-line'); var index=$(".card").eq(_i).attr('action-index'); move_animation($(".card").eq(_i),line,index); _i++; if(_i<cardbenum+10){ setTimeout(_this.move_animation,100); } } this.move_animation(); $("#postnum").html(parseInt($("#postnum").html())-1); clickCard(); }); }
以上6點,就是《蜘蛛紙牌》的基本內容,代碼裏還有一些方法,是爲了增長一些方便,好比返回J-K的值等等,這裏就不說了。直接編輯源代碼,仍是很累的。
裏面還有關於動畫的內容,暫時就不講了,所有代碼也不帖了,能夠查看試玩頁面的源文件