一塊兒來作webgame,《Javascript蜘蛛紙牌》

不得不說,作遊戲是會上癮的,此次帶來的是win系統上的經典遊戲《蜘蛛紙牌》,不能完美,但求一玩css

DEMO:html

http://colorgamer.com/demo/webgame/spider/web

關於蜘蛛紙牌

規則請打開win系統的蜘蛛紙牌,而後點擊幫助數組

這裏要實現的

  • 一樣是兩副牌,一共104張
  • 同一種花色的低難度遊戲

須要解決的問題

  • 一、洗牌
  • 二、判斷點擊牌所在序列是否符合可移動條件
  • 三、判斷目標位置是否符合可移動條件
  • 四、移動符合條件的紙牌序列到目標位置
  • 五、完成一個完整序列時的清除
  • 六、發牌

綜合起來,《蜘蛛紙牌》基本上就這麼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的值等等,這裏就不說了。直接編輯源代碼,仍是很累的。

裏面還有關於動畫的內容,暫時就不講了,所有代碼也不帖了,能夠查看試玩頁面的源文件

相關文章
相關標籤/搜索