如何用js写一个斗地主

前言

以下只是学习websocket过程中开发的一个demo,功能有限可能还会有些bug。

首先,这是线上链接

技术栈和已实现功能

技术栈:

* 前端:vue
* 后端:nodejs+websocket+ws
复制代码

已实现功能:

* 随机发牌(自动分配地主和地主牌)
* 出牌同步
* 断线重连(依据ip。demo中为了方便演示,并没有限定一个ip只能加入一次)
* 退出游戏(同房间其他玩家也会清除手牌)
* 游戏大厅与多房间游戏
* log公告窗口
复制代码

基本功能的实现

websocket基础知识

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。 demo中使用的ws库,npm i ws 安装完成之后,开启websocket服务:

const WebSocket = require('ws');//引入ws
 
const wss = new WebSocket.Server({ port: 8002 });//开启服务
 
wss.on('connection',function(ws,req){   //客户端链接
    ws.on('message', function incoming(data) {});   //接收客户端消息
    ws.on('close',function reset(){})   //客户端关闭触发
})
wss.broadcast = function broadcast(data) {  //广播
  wss.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
};
复制代码

与之对应,在客户端需要:

const ws = new WebSocket('ws://localhost:8002');
ws.onopen = function(e){}   //客户端链接
ws.onclose = function(e){}  //客户端关闭
ws.onerror = function(){}   //连接出错
ws.onmessage = function(e){} //接收服务端消息
复制代码

由于ws只能发送二进制和string,但是我们数据传输需求基本都是复杂数据对象,因此每次发送和接收前都需要用JSON.stringfy()和JSON.parse()转换。

发牌函数

首先需要获得所有牌型

function Card(){
    var type = ['黑桃','红心','梅花','方块']
    var nume = [
    {label:'A',value:14},{label:'2',value:16},{label:'3',value:3},{label:'4',value:4},
    {label:'5',value:5},{label:'6',value:6},{label:'7',value:7},{label:'8',value:8},
    {label:'9',value:9},{label:'10',value:10},{label:'J',value:11},{label:'Q',value:12},{label:'K',value:13}]
    var All = []
      type.forEach(v=>{
        nume.forEach(cv=>{
          All.push({
            type:v,
            label:cv.label,
            value:cv.value,
            isOn:false
          })
        })
      })
      All.push({
        type:'大王',
        label:'大王',
        value:100,
        isOn:false
      })
      All.push({
        type:'小王',
        label:'小王',
        value:50,
        isOn:false
      })
      return All
  }
复制代码

然后根据随机数生成4个数组,前三个为玩家手牌,第四个为地主牌。

  module.exports = function initCard(num){ //初始化手牌
    var AllCard = Card()
    var player = []
    for(var i=0;i<num;i++){
      player.push([])
      for(var j=0;j<(51/num);j++){
        var n = Math.floor(Math.random()*AllCard.length)
        player[i].push(AllCard[n])
        AllCard.splice(n,1)
      }
    }
    player.push(AllCard)
    AllCard=[]
    for(var i=0;i<player.length;i++){
      player[i]=player[i].sort(reSort('value'))
    }
    return player
}
复制代码

发牌展示

html结构如下:

<ul :style="'width:'+((bossCard.length-1)*24+100)+'px'" class="cardList" v-show="bossCard.length>0" v-if="bossCard">
  <li v-for="(item,ci) in bossCard" :class="item.isOn==true?'isOn':''" :key="ci" :style="'left:'+ci*24+'px;z-index:'+ci">
    <div :class="item|setClass" style="text-align: left;">{{item.label}}</div>
    <div class="cardBg"></div>
  </li>
</ul>
复制代码
  • 画一张扑克牌
根据type添加不通类名,然后通过背景图添加花色
filters: {
    setClass(item){
      if(item.type == '黑桃') return 'heitao'
      if(item.type == '红心') return 'hongxin'
      if(item.type == '梅花') return 'meihua'
      if(item.type == '方块') return 'fangkuai'
      if(item.type == '大王') return 'dawang'
      if(item.type == '小王') return 'xiaowang'
    }
}
复制代码
  • 发牌动画
接收到服务端的手牌后通过定时器一张一张添加到vm,然后添加transition: all linear 0.2s即可实现类似qq斗地主的发牌效果。
var t = setInterval(()=>{
  if(i+1>cardArr.length){
    _this.isInit = true
    return clearInterval(t)
  }
  _this.player.push(cardArr[i])
  i++
},200)
复制代码

待续

也不知道有没有人看,先写到这里。感兴趣的可以看下github源码。 整个demo都是想到哪写到哪,代码特别乱还没来得及整理,出牌验证规则也还没有写。后边有时间了整理一下代码然后补全功能。

转载于:https://juejin.im/post/5d0b3d8651882528fd530ab1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值