最近闲了两天没事做,用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 }
View Code
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 }
View Code
以上4步,是我认为的主要的4个函数,其他的函数,如初始化,事件注册等,在源码已有注释,写的不好勿喷。
附上源码:http://files.cnblogs.com/files/csbt/DDZ.zip
原标题:简陋的斗地主,js实现
关键词:JS