标签:
最近闲了两天没事做,用js写了个斗地主,练习练习。代码和功能都很简陋,还有bug,咋只是聊聊自己的思路。
这里说说斗地主主要包含的功能:洗牌,发牌,玩家出牌、电脑出牌,出牌规则的验证,输赢啥的没有判断,只是实现了这几个主要功能,下面依次说说几个功能的实现:
1.洗牌:
1 var pukes=this.manage.pukes;//存放扑克牌的数组 2 //洗牌 3 for(var i=0;i<pukes.length;i++){ 4 var tmp=pukes[i]; 5 var index=util.random(i,pukes.length);//随机交换两张牌 6 pukes[i]=pukes[index]; 7 pukes[index]=tmp; 8 }
2.发牌(简版默认是玩家自己为地主,电脑为农民),由于前面洗牌时已经将牌的顺序打乱,所以发牌只是简单的循环把pukes中的元素添加到每个玩家实例中的pukes字段中。
1 //发牌 2 var start=0; 3 for(var i=0;i<this.manage.pukes.length-3;i++) { 4 if(start==this.manage.players.length){ 5 start=0; 6 } 7 this.manage.pukes[i].status=true; 8 this.manage.players[start].pukesLen++; 9 this.manage.players[start++].pukes.push(this.manage.pukes[i]); 10 } 11 for(var i=this.manage.pukes.length-3;i<this.manage.pukes.length;i++){ 12 //地主多三张 13 this.manage.pukes[i].status=true; 14 this.manage.players[this.manage.curPlayerIndex].pukesLen++; 15 this.manage.players[this.manage.curPlayerIndex].pukes.push(this.manage.pukes[i]); 16 }
3.玩家出牌,玩家出牌分为电脑和玩家自己两个步骤,电脑出牌是非常傻瓜的出牌方式(有牌就出):
1 //出牌 2 if(this.options.playerIndex==this.manage.curPlayerIndex) { 3 var spks = [],gz=false; 4 5 if (this.manage.curMaxPlayerIndex == this.options.playerIndex) { 6 this.manage.deskPukes = []; 7 } 8 if (this.isCompute) { 9 //电脑自动出牌 10 var start = 0; 11 var len=this.manage.deskPukes.length||1; 12 while (start < this.pukes.length) { 13 spks = []; 14 for (var i = 0,j=start; i <len&&j<this.pukes.length; i++) { 15 //随便选一张 可以出就行 16 if(this.pukes[j].status) { 17 spks.push(this.pukes[j++]); 18 } 19 } 20 if(spks.length) { 21 if (rules.valids(spks, this.manage.deskPukes)) { 22 gz = true; 23 break; 24 } 25 } 26 start++; 27 } 28 } 29 else { 30 //玩家选择出牌 31 for (var i = 0; i < this.pukes.length; i++) { 32 if (this.pukes[i].selected && this.pukes[i].status) { 33 spks.push(this.pukes[i]); 34 } 35 } 36 if (rules.valids(spks, this.manage.deskPukes)) { 37 gz=true; 38 } 39 else{ 40 alert("出牌不符合规则!"); 41 } 42 } 43 if(gz){ 44 this.manage.curMaxPlayerIndex=this.options.playerIndex; 45 this.manage.deskPukes = []; 46 for (var i = 0; i < spks.length; i++) { 47 this.pukesLen--; 48 this.manage.deskPukes.push(spks[i]); 49 spks[i].status = false; 50 } 51 } 52 this.manage.renderPukes(); 53 this.manage.renderCurDiscard(); 54 if(this.isCompute||gz) { 55 this.manage.nextPlayer(); 56 } 57 } 58 else{ 59 alert("没轮到你出牌!"); 60 }
4.出牌规则的验证,是很多函数组合起来,然后循环调用,如果遇到返回ture的即为出牌符合规则:
1 //以下为出牌规则 2 var rules={ 3 _rules:[ 4 new danzRule(), 5 new duiRule(), 6 new sandRule(), 7 new zandRule(), 8 new shunzRule(), 9 new liandRule() 10 ], 11 valids:function(_pukes,_curPukes){ 12 for(var i=0;i<this._rules.length;i++){ 13 if(this._rules[i].valid(_pukes,_curPukes)){ 14 return true; 15 } 16 } 17 return false; 18 } 19 }; 20 21 function danzRule(){ 22 //单张规则 23 } 24 danzRule.prototype.valid=function(_pukes,_curPukes){ 25 //校验 26 var pukes=_pukes;//玩家的牌 27 var curPukes=_curPukes;//左面的牌 28 if(pukes&&pukes.length==1){ 29 //比较牌面值 30 if(!curPukes||!curPukes.length){ 31 return true; 32 } 33 if(curPukes[0].dians==2&&pukes[0].dians<15){ 34 //2特殊处理 35 return false; 36 } 37 if(pukes[0].dians==2&&curPukes[0].dians<15){ 38 //2特殊处理 39 return true; 40 } 41 return pukes[0].dians>curPukes[0].dians; 42 } 43 return false; 44 } 45 46 function duiRule(_pukes,_curPukes){ 47 //两张规则 48 49 } 50 duiRule.prototype.valid=function(_pukes,_curPukes){ 51 //校验 52 var pukes=_pukes;//玩家的牌 53 var curPukes=_curPukes;//左面的牌 54 if(pukes&&pukes.length==2){ 55 //比较牌面值 56 if(pukes[0].dians>14&&pukes[1].dians>14){ 57 return true; 58 } 59 if(pukes[0].dians!=pukes[1].dians){ 60 return false; 61 } 62 if(!curPukes||!curPukes.length){ 63 return true; 64 }else { 65 if(curPukes.length!=2){ 66 return false; 67 } 68 if (curPukes[0].dians > 14 && curPukes[1].dians > 14) { 69 return false; 70 } 71 if (curPukes[0].dians != curPukes[1].dians) { 72 return false; 73 } 74 if (curPukes[0].dians == 2) { 75 return false; 76 } 77 } 78 if(pukes[0].dians==2){ 79 return true; 80 } 81 return pukes[0].dians>curPukes[0].dians; 82 } 83 return false; 84 } 85 86 function sandRule(){ 87 //三带 88 } 89 sandRule.prototype.valid=function(_pukes,_curPukes){ 90 //校验 91 92 93 var pukes=_pukes;//玩家的牌 94 var curPukes=_curPukes;//左面的牌 95 if(pukes&&(pukes.length>=3)){ 96 //比较牌面值 97 var books=getBooks(pukes); 98 if(!valid(books))return false; 99 if(!curPukes||!curPukes.length)return true; 100 if(curPukes.length!=books.length)return false; 101 var books2=getBooks(curPukes); 102 if(!valid(books2))return false; 103 return getSum(books)>getSum(books2); 104 } 105 return false; 106 107 function getSum(books){ 108 var sum=0; 109 for(var i=0;i<books.length;i++) { 110 if(books[i]==3){ 111 if(i==2)return 9999; 112 sum+=i; 113 } 114 } 115 return sum; 116 } 117 function valid(books){ 118 //验证三带是否有效 119 var counts3= 0,countsd= 0,d2=true,start=false,startIndex=-1; 120 121 for(var i=0;i<books.length;i++) { 122 if(start&&books[i]==3&&startIndex!=(i-1)){ 123 return false; 124 }else{ 125 startIndex=i; 126 } 127 if(books[i]==3){ 128 if(!start) { 129 start = true; 130 startIndex = i; 131 } 132 counts3++; 133 } 134 if(books[i]==1){ 135 d2=false; 136 } 137 } 138 139 for(var i=0;i<books.length;i++) { 140 if(d2&&books[i]==2){ 141 countsd++; 142 } 143 else if(!d2&&books[i]==1){ 144 countsd++; 145 } 146 } 147 return counts3>0&&counts3==countsd; 148 } 149 150 function getBooks(pukes){ 151 //返回三带的每个点数的个数 152 var books=[]; 153 for(var i=0;i<pukes.length;i++){ 154 if(!books[pukes[i].dians]){ 155 books[pukes[i].dians]=1; 156 }else{ 157 books[pukes[i].dians]++; 158 } 159 } 160 return books; 161 } 162 } 163 164 165 function zandRule(){ 166 //炸弹 167 } 168 zandRule.prototype.valid=function(_pukes,_curPukes){ 169 var pukes=_pukes;//玩家的牌 170 var curPukes=_curPukes;//左面的牌 171 if(pukes&&pukes.length==4) { 172 if(!allEqual(pukes)){ 173 return false; 174 } 175 if(!curPukes||(curPukes.length>0&&curPukes.length!=4)||!allEqual(curPukes)){ 176 return true; 177 } 178 else{ 179 if(pukes[0].dians==2){ 180 return true; 181 } 182 if(curPukes[0].dians==2){ 183 return false; 184 } 185 return pukes[0].dians>curPukes[0].dians; 186 } 187 188 } 189 return false; 190 191 function allEqual(pukes){ 192 if(!pukes||!pukes.length)return false; 193 var base=pukes[0].dians; 194 for(var i=1;i<pukes.length;i++){ 195 if(base!=pukes[i].dians){ 196 return false; 197 } 198 } 199 return true; 200 } 201 202 } 203 204 function liandRule(){ 205 //连对 206 } 207 liandRule.prototype.valid=function(_pukes,_curPukes) { 208 var pukes=_pukes;//玩家的牌 209 var curPukes=_curPukes;//左面的牌 210 if(pukes&&pukes.length>=6) { 211 if(!verificationCoherence(pukes)){ 212 return false; 213 } 214 if(!curPukes||curPukes.length<=0){ 215 return true; 216 } 217 if(!verificationCoherence(curPukes)){ 218 return false; 219 } 220 if(pukes.length!=curPukes.length){ 221 return false; 222 } 223 return getSumDians(pukes)>getSumDians(curPukes); 224 } 225 return false; 226 function getSumDians(pukes){ 227 var sum=0; 228 for(var i=0;i<pukes.length;i++) { 229 sum+=pukes[i].dians; 230 } 231 return sum; 232 } 233 234 function verificationCoherence(pukes){ 235 //验证连贯性 236 if(!pukes||!pukes.length)return false; 237 var books=[]; 238 for(var i=0;i<pukes.length;i++){ 239 if(pukes[i].dians==2||pukes[i].dians>14){ 240 return false; 241 } 242 if(!books[pukes[i].dians]){ 243 books[pukes[i].dians]=1; 244 }else{ 245 books[pukes[i].dians]++; 246 } 247 if(books[pukes[i].dians]>2){ 248 return false; 249 } 250 } 251 var start=false; 252 253 for(var i=0;i<books.length;i++) { 254 if(books[i]&&books[i]!=2){ 255 return false; 256 } 257 if(books[i]==2&&!start){ 258 start=true; 259 } 260 if(start&&books[i]!=2){ 261 return false; 262 } 263 } 264 265 return true; 266 } 267 } 268 function shunzRule(){ 269 //顺子 270 } 271 shunzRule.prototype.valid=function(_pukes,_curPukes){ 272 var pukes=_pukes;//玩家的牌 273 var curPukes=_curPukes;//左面的牌 274 if(pukes&&pukes.length>=5) { 275 if(!verificationCoherence(pukes)){ 276 return false; 277 } 278 if(!curPukes||curPukes.length<=0){ 279 return true; 280 } 281 if(!verificationCoherence(curPukes)){ 282 return false; 283 } 284 if(pukes.length!=curPukes.length){ 285 return false; 286 } 287 return getSumDians(pukes)>getSumDians(curPukes); 288 } 289 return false; 290 291 function getSumDians(pukes){ 292 var sum=0; 293 for(var i=0;i<pukes.length;i++) { 294 sum+=pukes[i].dians; 295 } 296 return sum; 297 } 298 299 function verificationCoherence(pukes){ 300 //验证连贯性 301 if(!pukes||!pukes.length)return false; 302 var books=[]; 303 for(var i=0;i<pukes.length;i++){ 304 if(pukes[i].dians==2||pukes[i].dians>14){ 305 return false; 306 } 307 if(!books[pukes[i].dians]){ 308 books[pukes[i].dians]=1; 309 }else{ 310 return false; 311 } 312 } 313 var start=false; 314 for(var i=0;i<books.length;i++) { 315 if(books[i]==1&&!start){ 316 start=true; 317 } 318 if(start&&!books[i]){ 319 return false; 320 } 321 } 322 return true; 323 } 324 325 }
以上4步,是我认为的主要的4个函数,其他的函数,如初始化,事件注册等,在源码已有注释,写的不好勿喷。
附上源码:http://files.cnblogs.com/files/csbt/DDZ.zip
标签:
原文地址:http://www.cnblogs.com/csbt/p/ddz.html