斗地主

  1 <?php
  2 /*
  3  * 黑桃 @
  4  * 红桃 #
  5  * 片花 %
  6  * 梅花 *
  7  * */
  8 
  9 //fwrite(STDOUT,'name ?'.PHP_EOL);
 10 //fscanf(STDIN,"%s",$name);
 11 
 12 /*
 13  * 可配置参数:
 14  * 一副牌54张
 15  * 一局n副牌
 16  * 一局m个人
 17  * 一局分成x组
 18  *
 19  * 0.是否开始
 20  * 1.初始化数据54张牌,抽出3张底牌,3个人,分成2组,A组1人,B组2人
 21  * 2.51张牌,发牌给3个人,先发给A组
 22  * 3.随机一人开始出牌
 23  * 4.接下来一人出牌
 24  * 5.一人手中无牌,该组胜利
 25  * 6.计算输赢,一张牌1分,把得分平均发给赢组的人员
 26  * */
 27 
 28 class game
 29 {
 30     private static $playCards = [
 31                     2,2,2,2,
 32                     3,3,3,3,
 33                     4,4,4,4,
 34                     5,5,5,5,
 35                     6,6,6,6,
 36                     7,7,7,7,
 37                     8,8,8,8,
 38                     9,9,9,9,
 39                     10,10,10,10,
 40                     11,11,11,11,  //J
 41                     12,12,12,12,  //Q
 42                     13,13,13,13,  //K
 43                     14,14,14,14,  //A
 44                     20,           //小王
 45                     21            //大王
 46                 ];
 47     public  $playCardsNum;
 48     public  $peopleNum;
 49     public  $termNum;
 50     public  $people = array();
 51     private  $landlord=null;    //当前地主id做个标记
 52     private  $prevPerson=null;  //上个出牌人的id
 53     private  $currPerson=null;  //当前出牌人id
 54     private  $prevCard;         //上个人出的牌
 55     private  $prevCardType;     //上个人出牌型
 56     private  $cardTpyeObj;
 57 
 58     public  static $input=null;
 59     public  static $start;
 60 
 61 
 62     public function __construct($playCardsNum=1, $peopleNum=3, $termNum=2)
 63     {
 64         $this->playCardsNum = $playCardsNum;
 65         $this->peopleNum    = $peopleNum;
 66         $this->termNum      = $termNum;
 67         $this->cardTpyeObj  = CardTpye::obj();
 68 
 69         self::start() && $this->run();
 70     }
 71 
 72     public function run()
 73     {
 74         $this->peopleInit();
 75 
 76         while(self::$start)
 77         {
 78             //发牌
 79             $this->cardInit();
 80             //争地主
 81             $this->landlord();
 82             $this->showPerson();
 83             //出牌
 84              $this->playHand();
 85             //清空每局的垃圾信息
 86             $this->clean();
 87             //重新开始
 88             self::start();
 89         }
 90 
 91         self::notice("bye ~");
 92     }
 93 
 94 
 95 
 96     //询问是否开始
 97     public static function start()
 98     {
 99         self::notice("start   or  close ?");
100         self::notice("start:1     close:0");
101         self::getInput();
102         if(self::$input == 0)
103         {
104             self::$start = false;
105             self::delInput();
106             return false;
107         }else{
108             self::$start = true;
109             self::delInput();
110             return true;
111         }
112     }
113 
114     //初始化人员
115     public function peopleInit()
116     {
117         //初始化人员
118         for($peoson=0; $peoson<$this->peopleNum; $peoson++)
119         {
120             self::notice($peoson." name ?");
121             self::getInput();
122             $peosonInfo = array(
123                 "name"  => self::$input,
124                 "win"   => 0,
125                 "status" => 0,  //0农民  1地主
126                 "cards" => array()
127             );
128             if(empty(self::$input))
129             {
130                 $peoson--;
131             }else {
132                 array_push($this->people, $peosonInfo);
133             }
134             self::delInput();
135         }
136     }
137 
138     //开始发牌
139     public  function cardInit()
140     {
141         shuffle(self::$playCards);
142         foreach(self::$playCards as $key=>$card)
143         {
144             $tmpNum = $key % $this->peopleNum;
145             array_push($this->people[$tmpNum]['cards'], $card);
146         }
147 
148         array_walk($this->people,function(&$peoson){
149             sort($peoson['cards']);
150         });
151     }
152 
153     //显示每个人的牌
154     public function showPerson($id=null)
155     {
156         $status = array("peasant","landlord");
157 
158         if($id === null){
159             array_walk($this->people,function(&$peoson) use($status){
160                  $notice = $status[$peoson['status']]."  ".$peoson['name'].": ".implode(',',$peoson['cards']);
161                  self::notice($notice);
162             });
163         }else{
164             $notice = $status[$this->people[$id]['status']]."  ".$this->people[$id]['name'].": ".implode(',',$this->people[$id]['cards']);
165             self::notice($notice);
166         }
167     }
168 
169     //争地主
170     public function landlord()
171     {
172         $id = 0;
173         $score = 0;
174         foreach($this->people as $key=>$peoson)
175         {
176             self::notice($key." ".$peoson['name']." ".": please input score [1,2,3]");
177             self::getInput();
178             if(self::$input>$score) {
179                 $score=self::$input;
180                 $id=$key;
181             }
182             self::notice("s:".$score."  id:".$id);
183         }
184         $this->people[$id]['status'] = 1;
185         $this->landlord = $id;
186         self::delInput();
187     }
188 
189     //出牌
190     public function playHand()
191     {
192         $play = true;
193         while($play)
194         {
195             //计算该谁出牌了
196             if(is_null($this->currPerson)){
197                 $this->currPerson = $this->landlord;
198             }else{
199                 $needPlay = $this->currPerson + 1;
200                 $this->currPerson = !isset($this->people[$needPlay]) ? 0:$needPlay;
201             }
202 
203 
204             //没通过就重出
205             do {
206                 self::notice(PHP_EOL . PHP_EOL . "please play");
207                 $this->showPerson($this->currPerson);
208                 self::getInput();
209                 //验证出牌规则
210                 $pass = $this->ruleCheck();
211                 !$pass && self::notice("error.");
212             }while(!$pass);
213 
214             //把出的牌删除
215             if(!empty(self::$input))
216             {
217                 self::notice("play: " . self::$input);
218                 $playCards = explode(',', self::$input);
219                 foreach ($playCards as $card) {
220                     $key = array_search($card, $this->people[$this->currPerson]['cards']);
221                     unset($this->people[$this->currPerson]['cards'][$key]);
222                 }
223 
224                 //记录下出的牌和个人id
225                 $this->prevPerson = $this->currPerson;
226                 $this->prevCard = self::$input;
227                 self::log("p:".$this->prevPerson."  c:".$this->prevCard);
228             }
229 
230             //赢了
231             if(empty($this->people[$this->currPerson]['cards']))
232             {
233                 $this->people[$this->currPerson]['win'] ++ ;
234                 self::notice($this->people[$this->currPerson]['name']." win");
235                 $play = false;
236             }
237 
238             self::delInput();
239         }
240 
241         self::notice("game over");
242     }
243 
244     //验证规则
245     public function ruleCheck()
246     {
247 
248         /*
249          * 牌型验证,和上局人出的牌型一致
250          * 0.单张    一张牌一样
251          * 1.两对    两张牌一样
252          * 2.三对    三张牌一样
253          * 3.三队带一
254          * 4.三队带二对
255          * 5.四张炸
256          * 6.炸带单张
257          * 6.炸带两队
258          * 7.单顺最小5张   连续的牌,差为1
259          * 8.两对顺 最小三对
260          * 9.三队顺 最小2对
261          * 10.三队顺带2个单牌
262          * 11.三队顺带2个两对
263          * 12.四炸顺
264          * 13.四炸顺带两个单牌
265          * 14.四炸顺带两个对
266          * */
267 
268         //如果出空
269         if(is_null(self::$input))
270         {
271             //第一次不能出空
272             if(empty($this->prevCard)){
273                 return false;
274             }
275             //转一圈到自己了,不能出空
276             if($this->currPerson == $this->prevPerson){
277                 return false;
278             }
279 
280             return true;
281         }
282 
283 
284         $cards = explode(',',self::$input);
285         $type = $this->cardTpyeObj->getType($cards);
286         //第一次出,或其他人都不要,转一圈到自己了
287         if(is_null($this->prevPerson)  ||  $this->currPerson==$this->prevPerson)
288         {
289             if($type==0){
290                 return false;
291             }else{
292                 $this->prevCardType = $type;
293                 return true;
294             }
295         }else{
296             //根据类型验证大小
297             if($type==0 || $type!=$this->prevCardType){
298                 return false;
299             }else{
300                 $prevCards = explode(",",$this->prevCard);
301                 $big = $this->cardTpyeObj->size($type, $prevCards, $cards);
302                 return $big;
303             }
304         }
305 
306 
307     }
308 
309     //清空每局的垃圾信息
310     public function clean()
311     {
312         array_walk($this->people,function(&$person){
313             $person['staus'] = 0;
314             $person['cards'] = array();
315         });
316         $this->landlord = null;
317         $this->prevPerson = null;
318         $this->prevCard = "";
319     }
320 
321 
322 
323     public static function notice($message)
324     {
325         fwrite(STDOUT,$message.PHP_EOL);
326     }
327     public static function getInput()
328     {
329         fscanf(STDIN,'%s',self::$input);
330     }
331     public static function delInput()
332     {
333         self::$input = null;
334     }
335     public static function log($message)
336     {
337         $str = time()."  ".$message."
";
338         file_put_contents("log.txt", $str, FILE_APPEND);
339     }
340 
341 }
342 
343 $game = new game();
344 
345 
346 
347 class CardTpye
348 {
349     private static $obj;
350 
351     private function __construct(){}
352     private function __clone(){}
353     public static function obj()
354     {
355         if(!isset(self::$obj))
356         {
357             self::$obj = new self;
358         }
359         return self::$obj;
360     }
361 
362     //类型验证
363     public function getType(array $cards)
364     {
365         $type = 0;
366         switch(count($cards)){
367             case 1:
368                 $type=1;break;
369             case 2:
370                 $this->dui_2($cards) && $type=2;
371                 break;
372             case 3:
373                 $this->dui_3($cards) && $type=3;
374                 break;
375             case 4:
376                 $this->dui_3_1($cards) && $type=4;
377                 $this->bomb_4($cards) && $type=5;
378                 break;
379             case 5:
380                 $this->dui_3_2($cards) && $type=6;
381                 $this->bomb_4_1($cards) && $type=7;
382                 break;
383             default:
384                 $type=0;
385         }
386 
387         return $type;
388     }
389     //大小验证
390     public function size($type, array $prev, array $current)
391     {
392         $big = false;
393         switch($type){
394             case 1:
395                 $big = $this->one_size($prev, $current);
396                 break;
397             case 2:
398                 $big = $this->dui_2_size($prev, $current);
399                 break;
400             case 3:
401                 $big = $this->dui_3_size($prev, $current);
402                 break;
403             case 4:
404                 $big = $this->dui_3_1_size($prev, $current);
405                 break;
406             case 5:
407                 $big = $this->bomb_4_size($prev, $current);
408                 break;
409             case 6:
410                 $big = $this->dui_3_2_size($prev, $current);
411                 break;
412             case 7:
413                 $big = $this->bomb_4_1_size($prev, $current);
414                 break;
415             default:
416                 break;
417         }
418 
419         return $big;
420     }
421 
422 
423 
424     /********************验证大小***************************/
425     private function one_size(array $prev, array $current)
426     {
427         return self::bigOrSmall($prev[0],$current[0]);
428     }
429 
430     private function dui_2_size(array $prev, array $current)
431     {
432         return self::bigOrSmall($prev[0],$current[0]);
433     }
434 
435     private function dui_3_size(array $prev, array $current)
436     {
437         return self::bigOrSmall($prev[0],$current[0]);
438     }
439 
440     private function dui_3_1_size(array $prev, array $current)
441     {
442         //获取三张
443         $getDui_3 = function (array $cards){
444             if($cards[0] == $cards[1]){
445                 return array_slice($cards,0,3);
446             }else{
447                 return array_slice($cards,1,3);
448             }
449         };
450 
451         $prevDui_3 = $getDui_3($prev);
452         $currDui_3 = $getDui_3($current);
453         return self::bigOrSmall($prevDui_3[0], $currDui_3[0]);
454     }
455 
456     private function bomb_4_size(array $prev, array $current)
457     {
458         return self::bigOrSmall($prev[0], $current[0]);
459     }
460 
461     private function dui_3_2_size(array $prev, array $current)
462     {
463         $getDui_3 = function (array $cards)
464         {
465             sort($cards);
466             if($cards[0]==$cards[1] && $cards[1]==$cards[2])
467             {
468                 return array_slice($cards, 0, 3);
469             }else{
470                 return array_slice($cards, 2, 3);
471             }
472         };
473         $prevDui_3 = $getDui_3($prev);
474         $currDui_3 = $getDui_3($current);
475         return self::bigOrSmall($prevDui_3[0], $currDui_3[0]);
476     }
477 
478     private function bomb_4_1_size(array $prev, array $current)
479     {
480         $getDui_4 = function (array $cards)
481         {
482             sort($cards);
483             if($cards[0] == $cards[1])
484             {
485                 return array_slice($cards, 0, 4);
486             }else{
487                 return array_slice($cards, 1, 4);
488             }
489         };
490 
491         $prevDui_4 = $getDui_4($prev);
492         $currDui_4 = $getDui_4($current);
493         return self::bigOrSmall($prevDui_4[0], $currDui_4[0]);
494     }
495 
496 
497 
498     private static function bigOrSmall($pre, $cur)
499     {
500         if($cur <= $pre)
501         {
502             return false;
503         }else{
504             return true;
505         }
506     }
507 
508     /*****************验证牌型*************************/
509     /*
510      * type=2
511      * 两张牌---对子验证
512      * 规则:两张牌型一样
513      * */
514     private function dui_2(array $input)
515     {
516         if($input[0] == $input[1])
517         {
518             return true;
519         }else{
520             return false;
521         }
522     }
523 
524     /*
525      * type=3
526      * 三张牌---三对验证
527      * 规则:三张牌一样
528      * */
529     private function dui_3(array $input)
530     {
531         if($input[0]==$input[1] && $input[1]==$input[2])
532         {
533             return true;
534         }else{
535             return false;
536         }
537     }
538 
539     /*
540      * type=4
541      * 四张牌---三带一
542      * 规则:前三张一样,第四张随便
543      * */
544     private function dui_3_1(array $input)
545     {
546         //前三张一样
547         if($input[0]==$input[1])
548         {
549             if($input[1]==$input[2])
550             {
551                 return true;
552             }else{
553                 return false;
554             }
555         }else{
556             if($input[1]==$input[2] && $input[2]==$input[3])
557             {
558                 return true;
559             }else{
560                 return false;
561             }
562         }
563     }
564 
565 
566     /*
567      * type=5
568      * 四张牌---炸弹
569      * 规则:四张一样
570      * */
571     private function bomb_4(array $input)
572     {
573         if($input[0]==$input[1] && $input[1]==$input[2] && $input[2]==$input[3])
574         {
575             return true;
576         }else{
577             return false;
578         }
579     }
580 
581     /*
582      * type=6
583      * 五张牌---三带二
584      * 规则:前三张一样,后两张一样
585      * */
586     private function dui_3_2(array $input)
587     {
588         sort($input);
589         if($input[0]==$input[1] && $input[1]==$input[2])
590         {
591             $dui_3 = array_slice($input, 0, 3);
592             $dui_2 = array_slice($input, 3, 2);
593         }else{
594             $dui_2 = array_slice($input, 0, 2);
595             $dui_3 = array_slice($input, 2, 3);
596         }
597 
598         if($this->dui_3($dui_3) && $this->dui_2($dui_2))
599         {
600             return true;
601         }else{
602             return false;
603         }
604 
605     }
606 
607     /*
608      * type=7
609      * 五张牌---四带一
610      * 规则:四张一样的,一张单个
611      * */
612     private function bomb_4_1(array $input)
613     {
614         if($input[0] == $input[1])
615         {
616             if($input[1]==$input[2] && $input[2]==$input[3]){
617                 return true;
618             }else{
619                 return false;
620             }
621         }else{
622             if($input[1]==$input[2] && $input[2]==$input[3] && $input[3]==$input[4])
623             {
624                 return true;
625             }else{
626                 return false;
627             }
628         }
629     }
630 
631 
632 
633 }
原文地址:https://www.cnblogs.com/hanyouchun/p/5106341.html