MATLAB模拟斗地主发牌程序

MATLAB模拟斗地主发牌程序

问题假设

一副扑克牌有54张,其中大王和小王各一张,A,2,3,4,5,6,7,8,9,10,J,Q,K各有4张。假设我们不考虑这四种花色,地主发20张牌,两个农民各发17张牌。为了方便,A,2,3,4,5,6,7,8,9,10,J,Q,K分别用数字1至13代替,小王用14代替,大王用15代替。首先我们要知道这边牌是随机的。且每张牌发出去后就不能再有了(也就是不重复)。这里的核心用到的是randperm函数,若不了解的话可以自行去查一下,我这里不多说了。但是不能直接用randperm(54,20)、randperm(5,17)、randperm(54,17)。因为这样生成出来会有重复。所以我们可以把1~54分成5个部分 ,即第一部分为1–13,第二部分为14,15,(即大王小王),接下来是16~28、29–41、42–54,即把所有大于15的数都化为1–15之间。你也可以理解为牌的花色。

数字数字代表的牌花色
1–13A 1 2…J Q K黑桃
14–15小王、大王
16–28A 1 2…J Q K梅花
29–41A 1 2…J Q K方块
42–54A 1 2…J Q K红桃

分析程序步骤

Mon 06 Mon 13 Mon 20 问题假设 问题分析 程序模拟 分析结果 任务 MATLAB 模拟斗地主过程

我们分成5个模块来讲:

54个数字
第一个玩家分配的数字
转化为1--15之间的数
确定地主是几号玩家把底牌分配给地主
去掉第一个玩家选到的数字
第二个玩家分配的数字
转化为1--15之间的数
去掉第一和第二个玩家选到的数字
第三个玩家分配的数字
转化为1--15之间的数

我们分别给三个玩家分别记为1、2、3(方便后面选地主),,代码已经给出详细的注释和分块。

  1. 找第一个玩家的牌:首先使用randperm(54,17),得到1–54的17个乱序的数,即第一个玩家的牌代表的数字,然后把大于数字15的化为1–15内,第一个玩家的牌就得到了。
  2. 接下来是第二个玩家的牌,我们已经在54个数中取出了17个,那么我们使用R=setdiif(K,wj1) 函数取差集,也就是说1–54个数中哪些没被地主取走。剩下37个数字,取17个数,我们使用wj2=randperm(37,17) ,得到1–37的17个随机乱序的数,再将这17个数代表位置索引对应着取过差集的R,即得到第一个玩家的牌的数字(在1–54之间的数字),再把大于数字15的化为1–15内,就得到第二个家的牌了。
  3. 然后是第三个玩家的牌,经过上面步骤,已经在剩下的37个取走17,那么还剩20个数,用R1=setdiff(R,wj22),即37个数中哪些没有被取走。再在剩下的20个数中用wj3=randperm(20,17),得到1–20的17个随机乱序的数,再将这17个数的位置索引对应着取过差集的R,即得到第一家农民的牌的数字(在1–54之间的数字),再把大于数字15的化为1–15内,就得到第三个玩家的牌了。
  4. 即剩下的1–54中的3个数字就是底牌的数字,然后直接把大于数字15的化为1–15内,底牌也完成了。
  5. 最后是确定地主落入谁家,然后把底牌分配给地主:我们随机生成1~3的一个数,若是1,则地主是第一个玩家,以此类推。

代码实现

%%
clear,clc
K=1:54;
wj1=randperm(54,17);        %第一家在54个数中随机选出来的17个数
%将第一个玩家分配到的数字转化为1~15个数之间
for h=1:length(wj1)
    if wj1(h)<16                 %标号在1~15
        wj11(h)=wj1(h);
   elseif  wj1(h)>15&wj1(h)<29 ;      %标号在16~28
        wj11(h)=wj1(h)-15;
    elseif  wj1(h)>28&wj1(h)<42 ;     %标号在29~41
        wj11(h)=wj1(h)-28;
    else wj1(h)>41&wj1(h)<55 ;        %标号在42~54
        wj11(h)=wj1(h)-41;
    end
end
disp('第一个玩家的牌为:')
wj11
%%
R=setdiff(K,wj1);           %去掉第一家在0~54个数中取到的数剩下的数字(34)
wj2=randperm(37,17);        %第二家在剩下的34张中随机分配到的17%这里是把在1~34选到的对应到剩下的牌的标号
for j=1:length(wj2)
    wj22(j)=R(wj2(j));
end
wj22;                       %第一家农民随机在54张中分配到的的17%转化为1~15个数之间
for h=1:length(wj22)
    if wj22(h)<16
        wj222(h)=wj22(h);
    elseif wj22(h)>15&wj22(h)<29;
        wj222(h)=wj22(h)-15;
   elseif  wj22(h)>28&wj22(h)<42;
        wj222(h)=wj22(h)-28;
    else wj22(h)>41&wj22(h)<55;
        wj222(h)=wj22(h)-41;
    end
end
disp('第二个玩家的牌为:')
wj222
%%
R1=setdiff(R,wj22);
wj3=randperm(20,17);
for y=1:length(wj3)
    wj31(y)=R1(wj3(y));
end
wj31;
%转化为1~15个数之间
for h=1:length(wj31)
     if wj31(h)<16;
        wj32(h)=wj31(h);
    elseif wj31(h)>15&wj31(h)<29;
        wj32(h)=wj31(h)-15;
    elseif  wj31(h)>28&wj31(h)<42;
        wj32(h)=wj31(h)-28;
    elseif  wj31(h)>41&wj31(h)<55;
        wj32(h)=wj31(h)-41;
    end
end
disp('第三家的牌为:')
wj32
%%
%底牌
dp=setdiff(R1,wj31);
for d=1:length(dp)
     if dp(d)<16;
        dp1(d)=dp(d);
    elseif dp(d)>15&dp(d)<29;
        dp1(d)=dp(d)-15;
    elseif  dp(d)>28&dp(d)<42;
        dp1(d)=dp(d)-28;
    elseif  dp(d)>41&dp(d)<55;
        dp1(d)=dp(d)-41;
    end
end
disp('底牌为:')
dipai=sort(dp1)                %排序过后的底牌
%%
%选地主
xdz=randi([1 3],1,1);        %记这三家的标号分别为123
fprintf('地主是%d号玩家\n',xdz)
%底牌分给地主
if xdz==1
    wj11=[wj11 dp1];
elseif xdz==2
    wj222=[wj222 dp1];
else
    wj32=[wj32 dp1];
end
%%
%下面相当于把牌给排序了的
fprintf('整理后的牌:\n')    %排序后的牌
wanjia1=sort(wj11)         %地主家排序后的牌
wanjia2=sort(wj222)        %第一家农民排序后的牌
wanjia3=sort(wj32)         %第二家农民排序后的牌
结果分析

结果如下:刚开始每个玩家都是17个数字(代表牌),当选过地主后,地主(玩家1)有20个数字(代表牌),其他玩家都是17个数字(代表牌),可以看到玩家1(地主)有4个11(即4个 J J J),但是玩家2有王炸。通过结果分析是合理。注意每次运行的结果都会不同;相当于重新洗牌发牌了
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值