斗地主游戲文檔

1.體系結(jié)構(gòu)圖

體系結(jié)構(gòu)圖.png

2.邏輯流程圖

2.1簡易流程圖

邏輯流程圖.png

2.2詳細(xì)流程圖

詳細(xì)邏輯流程圖.png

3.服務(wù)器-客戶端通訊圖

sc通訊圖.png

4.數(shù)據(jù)結(jié)構(gòu)

4.1牌型

Paste_Image.png
  • 一副牌,共54張,由左至右相應(yīng)的index從0開始排開;
  • 牌型:
    單牌(ONE):任意一張單牌(3 < 4 <… < K< A < 2 < 小王<大王)。
    對子(TWO):任意兩張點(diǎn)數(shù)相同的牌,如:66。
    三頭(THREE):任意三張點(diǎn)數(shù)相同的牌,如666。
    連三(THREE_2): 二個(gè)連續(xù)三張牌,如:333444
    單順(STRAIGHT): 任意五張或五張以上點(diǎn)數(shù)相連的牌,如:45678或78910JQK。不包括 2和雙王。
    雙順(TWO_2): 三對或更多的連續(xù)對牌
    三順(THREE_3): 三對或更多連續(xù)三張牌,如:333444555
    炸彈(FOUR):任意四張點(diǎn)數(shù)相同的牌,如:6666

4.2牌型比較

  • 大小順序:3,4,5,6,7,8,9,10,J,Q,K,A,2,大王,小王。
  • 根據(jù)相應(yīng)的index轉(zhuǎn)為對應(yīng)大小的value,3-K分別對應(yīng)3-13,A:14,2:15,小王:16 , 大王:17
  • 除炸彈以外,普通牌型不允許對壓,相同牌型下比它大的能對壓。

4.3壓牌邏輯

壓牌邏輯.png

5.頁面展示

5.1開始游戲

開始游戲.PNG

5.2等待頁面

等待.PNG

5.3發(fā)牌頁面

發(fā)牌頁面.PNG

6代碼展示

6.1頁面渲染

//等待頁面
var htmlWait = "<h3 class='waiting'><h2>Waiting....</h2><h5>正在為你尋找小伙伴</h5></div>";
//發(fā)牌頁面
var htmlPoker="<div class='choose'><div class='oppo-usr'></div><div class='oppo-pokers'></div></div><div class='display'></div><div class='choose'><div class='user'><div class='usr'></div><button class='abandon'></button></div><div class='pokers'></div> <div class='button'> <button class='cancel'></button> <button class='no'></button> <button class='confirm'></button> </div></div>";
//登錄頁面
var htmlStart="<div class='menu'><button type='button' id='login'></button></div>";
//忙碌頁面
var htmlCrowded="<h3 class='waiting'><h2>Cowded....</h2><h5>房間好擠呀,你暫時(shí)進(jìn)不來</h5></div>";

6.2結(jié)構(gòu)定義

  • 用戶對象
//狀態(tài)定義
var INIT="INIT";//初始化
var WAITING="WAITING";//等待
var DISCARD="DISCARD";//發(fā)牌
var GAMEOVER="GAMEOVER";//游戲結(jié)束
var pkObj = {
    data:{
        status:INIT,
        count:27,
        pokers:[]
    },
    from:id,
    to: fid,
    success:0,
    init:function (){
        if(pkObj.data.status===INIT){
            $("#login").click(doInit);
        }
        socketInit();
    }
};
  • 牌對象
var ONE = "ONE";
var TWO = "TWO";
var TWO_2 = "TWO_2";
var THREE = "THREE";
var THREE_2 = "THREE_2";
var THREE_3 = "THREE_3";
var FOUR = "FOUR";
var STRAIGHT = "STRAIGHT";
var ERROR = "ERROR";
var KING = "KING";
 var poker= {
        type: type,                        //類型
        val: m,                            //大小
        length: pokerList.length  //張數(shù)
    };

6.3消息模型

  • 服務(wù)器端
io.on('connection', function(socket){
//添加用戶
socket.on('add user', function (obj) {
    count++;
    //玩家一加入
     if(count===1){
        socket.join(obj.from);
        first=obj;
        first.authority=true;
     }
  //玩家二加入
    else if(count===2){
        socket.join(obj.from);
        second=obj;
        //洗牌
        var res=shuffle();
        first.data.pokers=res.poker1;
        second.data.pokers=res.poker2;
        first.to=second.from;
        second.to=first.from;
        //用戶狀態(tài)改變由WAITING到DISCARD發(fā)牌
        first.data.status=DISCARD;
        second.data.status=DISCARD;
        //發(fā)送發(fā)牌事件
        io.to(first.from).emit("start poker", first);
        io.to(second.from).emit("start poker", second);
        }
      //玩家三登入
        else{
            socket.join(obj.from);
            other=obj;
             io.to(other.from).emit("crowded", other);
        }
  }
//監(jiān)聽discard事件,當(dāng)一方的牌數(shù)剩余為0,發(fā)送游戲結(jié)束信號(hào)
socket.on('discard',function(data,sendMessage){
    if(data.data.count===0){
        io.to(data.from).emit("game over", 1);
        io.to(data.to).emit("game over",2 );
    }
    else{
      //當(dāng)牌還有剩余時(shí),向?qū)κ职l(fā)送接收牌的信號(hào)
        io.to(data.to).emit("receive poker", sendMessage,data.data.count);
    }
  })
  //監(jiān)聽abandon事件,當(dāng)有一方放棄游戲,發(fā)送游戲結(jié)束信號(hào)
  socket.on('abandon',function(data){
      io.to(data.from).emit("game over", 3);
      io.to(data.to).emit("game over",4);
    })
  })
  • 客戶端
function socketInit() {
    //發(fā)牌
    socket.on('start poker', function (data) {
        doDiscard(data);
    });
  //接收對方的牌
    socket.on('receive poker',function (data,count) {
        doReceive(data,count);
    });
  //擁擠
    socket.on('crowded',function () {
        doCrowded();
    });
  //游戲結(jié)束
    socket.on('game over',function (data) {
        //自己獲勝
        if(data===1)
        {
            alert("you win!");
        }
      //對方獲勝
        else if(data===2){
            alert("you lose!");
        }
        //自己放棄
        else if(data===3){
            alert("你放棄啦!");
            $(".wrapper").html("");
           //回到初始頁面
            $(".wrapper").append(htmlStart);
            $("#login").click(doInit);
            pkObj.data.status=INIT;
        }
        else{
            alert("對方落荒而逃,恭喜你,不戰(zhàn)而勝!");
        }
    })
}  
                            

6.4函數(shù)介紹

服務(wù)端
  • 洗牌函數(shù)
//洗牌
function shuffle() {
  var pokers = new Array();
  for(var i = 0; i < 54; i++) {
    pokers[i]=i;
  }
  for (var i = 0; i < 54; i++) {
    var rd=parseInt(Math.random()*54);
    var b=pokers[i] ;
    pokers[i]= pokers[rd];
    pokers[rd]=b;
}
   var poker1 = [];
   var poker2 = [];
   for(var i = 0; i < 54; i++) {
    if(i<27)
        poker1[i]=pokers[i];
     else{
        poker2[i-27]=pokers[i];
    }
   }
   sort(poker1);
   sort(poker2);
  result = {
    poker1: poker1,
    poker2: poker2
  };
  return result;
}
//排序
function sort(pokers){
    var i=27;
    var temp;
    while (i > 0) {
    for (var j = 0; j < i - 1; j++) {
        if (((pokers[j]+11)%13> (pokers[j + 1]+11)%13)&&(pokers[j + 1]!==52||pokers[j + 1]!==53)) {
            temp = pokers[j];
            pokers[j] = pokers[j + 1];
            pokers[j + 1] = temp;}
        //小王
        if(pokers[j]===53){
            temp = pokers[j];
            pokers[j] = pokers[26];
            pokers[26] = temp;}
        //大王
        if(pokers[j]===52){
            temp = pokers[j];
            pokers[j] =pokers[j+1];
            pokers[j+1] = temp;}
                   }
                    i--;
         }
}
客戶端
  • 發(fā)牌
function doDiscard(data) {
    pkObj=data;
    $(".wrapper").html("");
    $(".wrapper").append(htmlPoker);
    //自己的牌
    yourPoker();
  //對方的牌
    myPoker(pkObj.data);
    $(".poker").click(function(){
        if($(this).hasClass("select")){
            $(this).removeClass("select");
            $(this).animate({top:"+=50px"});
        }
        else{
            $(this).addClass("select");
            $(this).animate({top:"-=50px"});
        }
    });
    //發(fā)牌
    $(".confirm").click(function(){
        //得到對方發(fā)來的牌
        var oppo_pokerList=new Array();
        if($(".display").children() !== null){
            $(".display").children().each(function(){
                oppo_pokerList.push(parseInt($(this).attr("data-value")));});
        }

        //得到自己的牌
        var pokerList=new Array();
        for(var i=0;i<27;i++){
            var index=".choose .poker"+i;
            if($(index).hasClass('select')){
                $(index).html();
                pokerList.push(parseInt($(index).attr("data-value")));
            }
        }
        if(getPokerType(pokerList).type===ERROR){
            console.log("error");
            alert("發(fā)的牌不和標(biāo)準(zhǔn)");
            doCancel();
        }
        //對方?jīng)]有牌即自己首發(fā)or對方放棄 自己沒有牌即表示放棄
        else if(oppo_pokerList.length===0||pokerList.length===0){
            doConfirm(pkObj);
        }
         //自己牌合乎標(biāo)準(zhǔn)
         else if(comparePoker(pokerList,oppo_pokerList)) {
            doConfirm(pkObj);
        }
        else{
            alert("發(fā)的牌不和標(biāo)準(zhǔn)");
            doCancel();
        }
    });
    //取消
    $(".cancel").click(function(){
        console.log("cancel");
        doCancel();
    });
    //不出
    $(".no").click(function(){
        $(".display .poker").remove();
        var sendMessage=$(".display").html();
        socket.emit('discard', pkObj, sendMessage);
        doCancel();
    });
    //退出游戲
        $(".abandon").click(function(){
        socket.emit('abandon', pkObj);
    })
}
  • 出牌
function doConfirm(pkObj) {
    var count=0;
    $(".display .poker").remove();
    for(var i=0;i<27;i++){
        var index=".poker"+i;
        if($(index).hasClass('select')){
            $(index).html();
            $(".display").append($(index));
            count++;
        }
    }
    var sendMessage=$(".display").html();
    pkObj.data.count-=count;
    socket.emit('discard', pkObj, sendMessage);
    $(".confirm").hide();
    $(".no").hide();
}
  • 放棄出牌
function doCancel() {
    for(var i=0;i<13;i++){
        var index=".choose .poker"+i;
        if($(index).hasClass('select')){
            $(index).removeClass('select');
            $(index).animate({top:"+=50px"});
        }
    }
}
  • 牌面大小轉(zhuǎn)換
function myPoker(data) {
    for(var i=0;i<27;i++){
        var x=data.pokers[i]%13*(-90);
        var y=parseInt(data.pokers[i]/13)*(-120);
        var left=x+"px";
        var top=y+"px";
        var count;
        //大王
        if(data.pokers[i]===52)
            count=17;
        //小王
        else if(data.pokers[i]===53)
            count=16;
        //A
        else if((data.pokers[i]+11)%13===11){
            count=14;
        }
        //2
        else if((data.pokers[i]+11)%13===12){
            count=15;
        }
        else {
            count=(data.pokers[i])%13+1;
        }
        var pokeri="poker"+i;
        var html = $("<button class='poker' data-value=''></button>").addClass(pokeri).attr("data-value", count);
        html.css({"background-position":left+" "+top});
        $(".pokers").append(html);
    }
}
  • 接收牌
function doReceive(data,after) {
    $(".confirm").show();
    $(".no").show();
     var before= $(".oppo-pokers").children().length;
    for(var i=before;i>after;i--){
        $(".oppo-pokers").children('.oppo-poker:last').remove();
    }
    if($(".display").children() != null){
        $(".display .poker").remove();
    }
    $(".display").append(data);
}
  • 牌型狀態(tài)機(jī)
function typeState(type, n, m) {
    switch (type) {
        //單
        case ONE:
            if(n == m) {
                type = TWO;
            } else if(n == m +1 && m == 16) {
                type = KING;
            } else if(n == m + 1){
                type = STRAIGHT;
            } else {
                type = ERROR;
            }
            break;
        //對
        case TWO:
            if(n == m) {
                type = THREE;
            } else if(n == m + 1){
                type = TWO_2;
            } else {
                type = ERROR;
            }
            break;
        case TWO_2:
            if(n == m) {
                type = TWO;
            } else {
                type = ERROR;
            }
            break;
        case THREE:
            if(n == m) {
                type = FOUR;
            } else if(n == m + 1){
                type = THREE_2;
            } else {
                type = ERROR;
            }
            break;
        case THREE_2:
            if(n == m) {
                type = THREE_3;
            } else {
                type = ERROR;
            }
            break;
        case THREE_3:
            if(n == m) {
                type = THREE;
            } else {
                type = ERROR;
            }
            break;
        case STRAIGHT:
            if(n == m + 1) {
                type = STRAIGHT;
            } else {
                type = ERROR;
            }
            break;
        default:
            break
    }
    return type;
}
  • 牌型獲取
function getPokerType(pokerList) {
    var type = ONE;
    var n, m;
    if(pokerList.length===1){
        m=pokerList[0];
    }
    else {
        for (var i = 0; i < pokerList.length; i++) {
            n = pokerList[i];
            m = pokerList[i + 1];
            type = typeState(type, n, m);
        }
        if(type == TWO_2 || type == THREE_2 || type == THREE_3 || (type == STRAIGHT && pokerList.length < 5)) {
            type = ERROR;
        }
    }

    var poker= {
        type: type,
        val: m,
        length: pokerList.length
    };
    return poker;
}
  • 牌型大小比較
function comparePoker(pokerList,oppo_pokerList) {
    var flag= false;
    var data1 = getPokerType(oppo_pokerList); //對方的牌類型
    var data2 = getPokerType(pokerList);  //我的牌類型
    if((data1.type == data2.type && (data1.length == data2.length) && pokerList[0] > oppo_pokerList[0]) || (data1.type != FOUR && data2.type == FOUR) || (data2.type == KING)) {
        flag= true;
    }
    //flag為true可出牌,否則不能出牌
    return flag;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 體系結(jié)構(gòu)圖 邏輯流程圖 邏輯流程圖詳細(xì) 通訊圖 圖片參考簡書作者kamidox的文章使用 Sublime + Pl...
    ofelia_why閱讀 1,032評論 0 3
  • 兩人斗地主 一、體系結(jié)構(gòu)圖 通訊模型 大功能模塊切換關(guān)系 二、邏輯流程圖 登錄login.PNG 主頁面開始界面....
    wuyumumu閱讀 617評論 0 0
  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 14,259評論 0 38
  • 斗地主游戲文檔 1.體系結(jié)構(gòu) 2.邏輯流程圖 3.服務(wù)器-客戶端通訊圖 4.數(shù)據(jù)結(jié)構(gòu) 4.1牌型 4.2比較大小 ...
    折柳畫馬閱讀 1,261評論 0 2
  • Nginx的代理功能與負(fù)載均衡功能是最常被用到的,關(guān)于nginx的基本語法常識(shí)與配置已在上篇文章中有說明,這篇就開...
    R_X閱讀 1,072評論 0 0

友情鏈接更多精彩內(nèi)容