DavidSilver增强学习补充——21点游戏BlackjackExample
发布日期:2022-03-25 23:42 点击次数:162
(PS:为了尽可能理解如何运用MC方法求解21点游戏,我们将信息更加细化——相比David Silver的PPT。)21点游戏规则大多数赌场使用6副牌或8副牌玩这种游戏,以防止“数牌点”,在本次模拟中使用两副牌(共104张,分别为8个1,2,3,4,5,6,7,8,9,10,J,Q,k)。只有2位参与者,玩家和庄家。游戏开始时每人得到两张牌,对于牌面为2-10的牌,点数和面数相同;对于为花牌(J、Q、K)的牌,点数为10;牌面为A的牌,点数为1或者11。 游戏的目的是得到总数尽量接近21点的牌,不得超过,并使玩家得到的总点数多于庄家。 如果开始两张牌的总点数恰为21(A-10或A-花牌),称为21点,自动成为胜者(若玩家和庄家都得到21点,则为平局,玩家的赌注仍在台上)。靠21点赢时,付给玩家3赔2,即1.5赔1(1元赌注赢1.5元,且1元赌注仍保留)。 如果玩家和庄家都未得到21点,玩家想要多少张牌就可以取多少张牌,一次一张,使总数尽量接近21点,如果玩家超过了21点炸金花规则,就输了,游戏结束。一旦玩家对牌的点数满意,玩家就“打住”,然后庄家按照下列规则取牌: 当庄家牌的点数为17、18、19、20和21时,就打住;若庄家牌的点数小于或等于16,必然取牌。庄家总把A的点数记为11,除非这样使他超过21(这时A的点数记为1)。例如,庄家的A-6组合是17点,不是7点(庄家没有选择权),且庄家必须打住在17点上。而若庄家有A-4组合(15点),又拿了一张K,那么新的总点数是15,因为A回到点数1(使之不超过21点),庄家还要再取牌。 如果庄家超过21点,玩家就赢了(赢赌注的钱,每1元赌注赢1元)。如果庄家的总点数超过玩家,玩家将输掉全部赌注。如果庄家和玩家的总点数相同,为平局(玩家不输也不赢)。 赌场中这个游戏的刺激之处在于,庄家开始的两张牌一张明、一张暗,所以玩家不知道庄家牌的总点数,必须根据那张明牌赌一把。在这个项目模拟中玩家不用考虑这种情况,玩家需要做的是:用两幅牌做12次游戏,玩家可以有无限的赌资,每次下赌2元。两副牌玩过一次后,用两幅新牌(104张)继续玩。这时记录玩家的得分(加或者减X元),然后下一幅牌从0开始。输出是12次游戏的12个结果,可以用平均数或总数决定玩家的总成绩。 运用MC方法求解玩家的最佳策略是什么? 求解过程第1步 初始化。 第2步 得到 (A,2,3,4,5,6,7,8,9,10,J,Q,k)内的随机数 、 、 、 ,计算 和 的和SUM1(玩家总点数 ), 和 的和SUM2(庄家总点数 ),同时庄家现出自己的第一张牌 。 第3步 判断 的值,若 >10,出现花牌,则将其值改为10,并重新计算SUM1。第4步 判断 的值,若 >10,出现花牌,则将其值改为10,并重新计算SUM1。 第5步 判断 的值,若 >10,出现花牌,则将其值改为10,并重新计算SUM2。 第6步 判断 的值,若 >10,出现花牌,则将其值改为10,并重新计算SUM2。 第7步 判断 的值是否为1,若等于1将其值改为11,重新计算SUM1,并判断SUM1是否大于21,若大于21则将 改为1,并重新计算SUM1,若没有大于21则继续第9步;若 不为1,直接进行第9步。 第8步 判断 的值是否为1,若等于1将其值改为11,重新计算SUM1,并判断SUM1是否大于21,若大于21则将 改为1,并重新计算SUM1,若没有大于21则继续第10步;若 不为1,直接进行第10步。 第9步 判断 的值是否为1,若等于1将其值改为11,重新计算SUM2,并判断SUM2是否大于21,若大于21则将 改为1,并重新计算SUM2,若没有大于21则继续第11步;若 不为1,直接进行第11步。 第10步 判断 的值是否为1,若等于1将其值改为11,重新计算SUM2,并判断SUM2是否大于21,若大于21则将 改为1,并重新计算SUM2,若没有大于21则继续第12步;若 不为1,直接进行第12步。 第11步 玩家判断SUM1是否大于等于决策数,若是则玩家停止取牌,跳到第13步;若没有则继续取牌,得到 内的随机数 ,进行第12步。 第12步 同第4步和第8步,判断 的值,若 >10,则将其值改为10,并将其值加到SUM1;接着判断 的值是否为1,若 等于1将其值改为11,重新计算SUM1,并判断SUM1是否大于21,若大于21则将 改为1,并重新计算SUM1,若没有大于21则回到第11步;若 不为1,直接进行第13步。 第13步 庄家判断SUM2是否大于16,若是则庄家不取牌,跳到第15步;否则庄家取牌,得到 内的随机数 ,进行第14步。 第14步 同第6步和第10步,判断 的值,若 >10,则将其值改为10,并将其值加到SUM2;接着判断 的值是否为1,若 等于1将其值改为11,重新计算SUM2,并判断SUM2是否大于21,若大于21则将 改为1,并重新计算SUM2,若没有大于21则回到第13步;若 不为1,直接进行第15步。 第15步 比较SUM1和SUM2的大小。 If(SUM1>21&&SUM2>21)or(SUM1=21&&SUM2=21),则为平局,得分SCORE=0; If SUM1=21&&SUM2≠21,则玩家赢,得分SCORE=3; If(SUM2=21&&SUM2≠21)or(21>SUM2>SUM1),则庄家赢,得分SCORE=-2; If 21>SUM1>SUM2 则玩家赢,得分SCORE=2; If 21>SUM1=SUM2 则为平局,SCORE =0. 第16步 输出得分SCORE。 在matlab中进行仿真,共有两个文件dian21.m和choose.m。 程序dian21.mfunction y=dian21()
n=input('请输入局数:');
SUM=0;%玩家的得分
flag=input('请输入决策数:');
%我们可以改变决策数的值,测试哪一个值最优
%决策数具体的含义是:玩家的总点数大于决策数就停止取牌
for i=1:n%总共进行的局数
%%第1步
a=ones(8,13);%产生8*13的矩阵,代表分别有8个A,2,3,4,5,6,7,8,9,10,J,Q,k
numz=0;%庄家手里牌的数量
numw=0;%玩家手里牌的数量
pz=[];%储存庄家手里牌的点数
pw=[];%储存玩家手里牌的点数
totz=0;%庄家总点数
totw=0;%玩家总点数
%%第2步,第3、4、5、6、7、8、9、10步隐含在了choose.m函数中
[numz,pz,a]=choose(numz,pz,a);%庄家第一次要牌
totz=totz+pz(numz);
[numz,pz,a]=choose(numz,pz,a);%庄家第二次要牌
totz=totz+pz(numz);
[numw,pw,a]=choose(numw,pw,a);%玩家第一次要牌
totw=totw+pw(numw);
[numw,pw,a]=choose(numw,pw,a);%玩家第二次要牌
totw=totw+pw(numw);
%%玩家做出决定是否继续要牌
while 1
if (totw>flag)%如果玩家当前手里牌的点数相加已经超过了决策数则停止要牌
break;
else%否则继续要牌,直到超过决策数
[numw,pw,a]=choose(numw,pw,a);
totw=totw+pw(numw);
end
end
%%庄家做出决定是否继续要牌
while 1
if (totz>=17)&(totz<=21)%如果庄家当前手里牌的总点数已经等于或超过17则停止要牌
break;
end
if totz<17%如果庄家当前手里牌的总点数小于17则继续要牌
[numz,pz,a]=choose(numz,pz,a);
totz=totz+pz(numz);
else
b=0;
for i=1:numz
if pz(i)==11%如果庄家手里的牌某一张为11
pz(i)=1;%将这张牌变成1
totz=totz-10;%庄家当前手里牌的总点数-10
b=1;%代表修改过庄家的牌
break;
end
end
if b==0
break;
end
end
end
SCORE=0;
if (totw>21 && totz>21) || (totz==21&&totw==21)
%(玩家>21&&庄家>21)或者(玩家=21&&庄家=21)
SCORE=0;%平局,得分0
else if (totw==21 && totz~=21)
%(玩家=21&&庄家不等于21)
SCORE=3;%玩家胜利,得分3
else if (totz==21&&totw~=21) || (21>totz && totz>totw) ||(totw>21 && totz<21)
%(庄家=21&&玩家不等于21)||(庄家<21&&玩家<庄家)||(玩家>21&&庄家<21)
SCORE=-2;%庄家胜利,得分-2
else if (21>totw && totw>totz) ||(totz>21 && totw<21)
%(玩家<21&&玩家>庄家)||(玩家<21&&庄家>21)
SCORE=2;%玩家胜利,得分2
else if 21>totw && totw==totz
%(玩家<21&&玩家=庄家)
SCORE=0;
end
end
end
end
end
SUM=SUM+SCORE;
end
fprintf('玩家得分平均值SCORE=%d\n',SUM/n);程序choose.m function [num,p,a]=choose(num,p,a)
while 1
Sum=0;
%产生2个随机数m和n
m=fix(rand(1)*8)+1;%随机数m:1-8,代表每种牌有8张
n=fix(rand(1)*13)+1;%随机数n:1-13,代表1,2,3,4,5,6,7,8,9,10,J,Q,k
if a(m,n)==1%代表这张牌没有被要过
a(m,n)=0;%代表这张牌没有被要过
num=num+1;%牌的数量+1
%%第3、4、5、6步
if n>10%若n>10,出现花牌,则将其值改为10
n=10;
end
p=[p n];%将n添加到点数的末尾
%%第7、8、9、10步
for i=1:num%将每次牌的点数相加
Sum=p(i)+Sum;
end
if n==1%判断n是否为1,若等于1
if Sum<21%判断点数是否小于21,若小于21
n=11;%将n改为11
end
end
break;
end
end 求解结果 >> dian21请输入局数:10000 请输入决策数:10玩家得分平均值SCORE=-2.976000e-01>> dian21 请输入局数:10000 请输入决策数:11玩家得分平均值SCORE=-1.553000e-01 >> dian21 请输入局数:10000 请输入决策数:12玩家得分平均值SCORE=-5.760000e-02 >> dian21 请输入局数:10000 请输入决策数:13玩家得分平均值SCORE=1.010000e-02 >> dian21 请输入局数:10000 请输入决策数:14玩家得分平均值SCORE=-1.950000e-02 >> dian21 请输入局数:10000 请输入决策数:15玩家得分平均值SCORE=1.080000e-02 >> dian21 请输入局数:10000 请输入决策数:16玩家得分平均值SCORE=6.600000e-02>> dian21 请输入局数:10000 请输入决策数:17玩家得分平均值SCORE=8.020000e-02>> dian21 请输入局数:10000 请输入决策数:18玩家得分平均值SCORE=-6.900000e-02>> dian21 请输入局数:10000 请输入决策数:19玩家得分平均值SCORE=-3.064000e-01 >> dian21 请输入局数:10000 请输入决策数:20玩家得分平均值SCORE=-8.145000e-01 >> dian21 请输入局数:10000 请输入决策数:21玩家得分平均值SCORE=-1.387000e+00 可见,在决策数为17时玩家的平均得分最高。 所以最终决策是:玩家的总点数大于17就停止取牌。