讲解视频:可以在bilibili搜索“MATLAB教程新手入门篇——数学建模清风主讲”。
MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili
一副扑克牌有54张牌(桃杏梅方四种花色的A 2 3 4 5 6 7 8 9 10 J Q K加双王),假设三名玩家玩斗地主,其中地主有20张牌,两个农民各17张牌。若你是其中一名玩家,且你每次都选择当农民。,请编程模拟以下场景:先玩第一把,若这把手上有炸弹则这把玩完后下场换其他人玩;若手上没有炸弹则继续玩第二把,直到玩到第k把时手上有炸弹,此时玩完这一把后下场换其他人玩。请输出你模拟的k。注意:假设每把牌都洗的足够的混乱,确保为无序;有炸弹是指手上有双王或者有四张相同的牌例如4张3。(这里的k表示你作为农民首次出现炸弹的轮数,由于发牌过程是随机的,那么k肯定也是一个随机的变量,即每次模拟的k可能都不相同。比如运气好可能第一把就出现了炸弹,此时k等于1,运气不好可能需要好多把才会出现炸弹,此时k较大)。
思路:由于循环的次数不定,因此我们可以使用while循环来不断模拟游戏的进行,直到满足退出的条件。在每一轮中,我们作为农民会随机抽取17张牌,并检查是否有双王或者普通的炸弹。如果有任何一种炸弹,就会退出循环,否则会增加游戏的轮数,继续下一轮。最后,我们可以输出模拟的k值,表示玩到第k把时手上有炸弹。
% 用1至13分别代替A 2 3 ... J Q K, 重复4次表示四种花色;用14和15分别代表大小王
poke = [repmat(1:13,1,4),14,15]; % 生成一副扑克牌
k = 1; % 玩了多少把游戏
while 1
% 从1:54中随机抽取17个数,表示17张牌对应的下标
idx = randperm(54,17); % randperm函数的用法:《第3章:课后习题讲解中拓展的函数》
% 发牌并排序(排序后牌面看起来更清楚一点,事实上不排序也不影响下面的代码)
p = sort(poke(idx));
% 检查是否有大小王
v1 = all(ismember([14,15],p)); % v1为true表示有双王,为false表示没有双王
% 检查是否有普通的炸弹
v2 = false; % v2表示是否有普通的炸弹,先假设没有,因此初始化为false
for ii = 1:13
if sum(p == ii) == 4 % 如果有四张一样的牌
v2 = true; % % 将v2赋值为ture,表示有普通的炸弹
break % 只要有一个普通的炸弹就可以退出for循环了
end
end
if v1 || v2 % 如果有王炸或者普通炸弹就可以退出while循环
break % 跳出while循环
else
k = k + 1; % 没有炸弹就再玩一把
end
end
disp(k) % 输出首次出现炸弹时玩的轮数
在本题中,既用到了while循环又用到了for循环,且出现了两个不同用途的break,大家课后一定要认真消化,并尝试自己求解这个例题(当然,判断是否存在普通的炸可以不用循环语句,我们在第三章的课后习题中有讲解,详情请看第三章课后习题挑战篇的Q5)。
MATLAB课程第3章课后习题讲解——数学建模清风老师_哔哩哔哩_bilibili
另外,本题还能继续扩展下去,例如重复上面的模拟过程N次(N可以设置得大一点,例如N等于10万),得到这N次模拟结果的k,并计算这N次k的平均值,这个平均值就能表示你作为农民首次出现炸弹所需的期望轮数。这个拓展的问题将留作本章最后的课后习题,我们下一道题也会介绍类似的思想。