原创一个计算斗地主谁必赢谁必输的程序
这个程序的缘由是看到朋友圈里发布了这么一张图:
我是个斗地主菜鸟啊,反正一时半会是没看出来到底谁能赢,但是我对这类问题倒是很有兴趣,真好我那阵也写过几个类似这种动态规划算法的程序,于是我开发了一个小软件来计算题目所述的情况下到底是谁必赢,而且还可以修改能出什么牌的规则,如下图:
难点是出牌规则这块,不过最后还是克服了,算出来的结果是地主赢,网上搜了一下答案,符合。当然除了程序猿,一般人很难理解,就打个牌还用弄程序算?我自己看看不就知道谁赢了吗,但是程序的好处嘛就是只要你算法是对的,遇到再多这种类似的问题都是一样解决啊,而且不会出错,秒杀解决。
这不,今年过年在QQ群里又遇到这么一个类似的题目,如下:
在群里还在争论不休的时候,我拿出程序一算,搞定,如下图:
我想结果应该是没错吧,后来我就随便看了看源码(VC写的,IDE是VS2005),突然想起来,我有没有把“过”也算到应对的可能里去啊,找找,发现还是有的,放心了,看来当时还是用心的,哈哈。
019-04-22修正:
这两天我又在头条上看到这种题目,我当然要再算一下了,我下巴都掉了,居然错了,纳尼。。。怎么会算错了呢,我敬了个呆,没办法,只好把算法和代码都理了一遍,发现递归主算法没有问题,问题是出在一个比较牌型大小的函数,因为2比较特殊,作为单牌是除了大小鬼最大的,但是作为比如连对,飞机这种,2又是较小的(甚至规则允许不允许也是个问题),就是这个判断的有问题,修复了之后再算是对的,我又把这篇文章里的两道都算了一下,发现第一道3 3 3 3 4 5 6 7 j j 2 2 2 2 竟然使用了2 3 4 5 6 7这种走法,算出来农民赢,额。。。这是从一个侧面证明了我这个程序是正确的嘛。。我略一攻防,好像这么走的确是农民赢啊,如果把顺子这种规则去掉就是地主赢,看来的确顺子有没有带2不一样,所以这样就归结到了规则是怎么规定的。然后又发现我这篇里第二个例子,农民的牌弄错了,小鬼打成了q,我重新算了一下,无论是g还是q,结果是一样的,第二个例子还好,可能碰巧对了。
最后再mark一下递归主程序的逻辑
//2023-04-22:函数的作用是 - 给定农民的牌,地主的牌,当前轮到谁了,上一手牌是什么,算出谁必赢 ePlayResult CsrcDlg::playCards(int depth, const vector& farmer, const vector& landlord, bool fmr_turn, const CCard& cur_card)
为了算谁赢,我可以遍历当前选手的可选出牌方法,如果有一种出牌方法可以得出他必赢,则在当前局面下,该选手必赢,如果一种方法都不能必赢,则他此局面必输。递归就在于遍历出牌方法时,判断使用此方法后形成的新局面谁必赢,使用的还是这个函数,也就是递归了。
看了自己写的这个c代码,有点糟,主要是手法不够老道,需要理解的东西太多,没有做一定的控制。另外c++的写法也实在太冗余了,看了不舒服,IDE也不行。
最后给个下载地址:一个计算斗地主谁必赢谁必输的程序.zip
2023-04-22修正版:https://pan.baidu.com/s/1d0a70gfZcE0sdtrkDBHlmw 提取码:wsjw