简陋的斗地主,js实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简陋的斗地主,js实现相关的知识,希望对你有一定的参考价值。

最近闲了两天没事做,用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实现简陋的观察者模式

Vue项目实战 —— 后台管理系统( pc端 ) —— Pro最终版本

纯js实现10分钟倒计时

练习---斗地主案例分析和代码实现

斗地主案例的代码实现(单列)

代码实现:模拟斗地主洗牌和发牌并对牌进行排序的代码实现