博弈论中的枪手模型说,三个枪手中最弱的生存下来的可能性最大,这其实挺反直觉的。模型中设置三者同时开枪、且开枪只有一轮,我觉得这是不合理的。我觉得现实中应该是,一个裁判喊开始,但是枪手的出枪速度有块有慢,而且决斗必须决定出谁是最后那一个站着的人。我觉得最弱的那个人,一定是生存几率最低的那个人,能力越强生存下去的几率就越大。
有了这个想法,我们就需要来验证一下。找三个人来站着对着开枪是不太可能了,但是我们有计算机,可以建个模型来仿真验证一下。
模型中我们做如下前提:
1】三个枪手gunner1、gunner2、gunner3,
2】命中率80% 、60% 、40%
3】三个枪手开枪速度分别是 0.17s、0.18s、0.19s
4】谁上一枪打我,我这一枪就打谁,谁对我威胁大,我先打谁,不允许放空枪
5】最后一个生存者结束比赛
好了,有了以上前提,我们可以开始建立模型了,我们的模型通过Matlab建立。
先说结论吧:
先开枪的占有优势,枪法准的不一定占有劣势,取决于准到什么程度,出抢速度快的占有优势(因为出枪速度不算做危险因子),但是不明显。
根据上面设定:生存概率 gunner1:gunner2:gunner3 = 4.7:1:4.3
总结起来就是:
1】当其中有抢手占有绝对优势的时候,该枪手生存概率最高;当所有抢手势均力敌时候,最弱的那个枪手生存概率最高。
2】而且博弈论的前提是所有的信息对所有的枪手绝对透明,所有的枪手对场上的信息绝对掌握,否则博弈结论不成立。
主脚本:
clc
clear
close all
testResult = [];
%% 进行N场比赛
for iloop2 = 1:1000
%% 实例三个抢手
gunner1 = Gunner('gunner1',0.8,0.17);
gunner2 = Gunner('gunner2',0.6,0.18);
gunner3 = Gunner('gunner3',0.4,0.19);
% 参赛抢手注册
gunnerList = Context();
gunnerList.register(gunner1);
gunnerList.register(gunner2);
gunnerList.register(gunner3);
%% 实例一个裁判,并将参赛抢手信息注册给裁判
referee = Referee(gunnerList);
timer = 0;
% 每场比赛的时间从0开始,按照0.01秒的步进进行计时
% 直到赛场上只剩最后一个人比赛结束
% 每当有人开枪后,会回调裁判的处理函数进行赛场形势判断
% 裁判根据判断结果设置参赛者的下一状态
while(size(referee.findAliveGunner(),2) > 1)
timer = timer + 0.01;
% 判断哪个选手开枪
for iloop3 = 1:size(gunnerList.dataDictionary,2)
shootAlert = mod(timer,gunnerList.dataDictionary(iloop3).pShootSpeed);
if(shootAlert < 1e-2 && gunnerList.dataDictionary(iloop3).pIsAlive == 1)
referee.setDangerGunner(gunnerList.dataDictionary(iloop3))
referee.setGunnerOrder(gunnerList.dataDictionary(iloop3));
gunnerList.dataDictionary(iloop3).didShoot(1);
else
gunnerList.dataDictionary(iloop3).didShoot(0);
end
end
end
aliveGunner = referee.findAliveGunner();
if(aliveGunner.gunnerName == 'gunner1')
testResult = [testResult,1];
elseif(aliveGunner.gunnerName == 'gunner2')
testResult = [testResult,2];
elseif(aliveGunner.gunnerName == 'gunner3')
testResult = [testResult,3];
end
end
numel(testResult(testResult == 1))
numel(testResult(testResult == 2))
numel(testResult(testResult == 3))
裁判脚本:
classdef Referee<handle
properties
gunnerList;
end
methods
% 构造函数,并添加你监听机制以及回调函数
function obj = Referee(gunnerList)
obj.gunnerList = gunnerList;
for iloop1 = 1:size(obj.gunnerList.dataDictionary,2)
obj.gunnerList.dataDictionary(iloop1).addlistener('gunnerDidShoot',@obj.processShootEvent);
end
end
function setDangerGunner(obj,gunner)
aliveGunnerVector = obj.findAliveGunner();
aliveGunnerVector = aliveGunnerVector(aliveGunnerVector ~= gunner);
aliveNum = numel(aliveGunnerVector);
hitRateVector = zeros(1,aliveNum);
for iloop1 = 1:aliveNum
hitRateVector(iloop1) = aliveGunnerVector(iloop1).pHitRate;
end
[~,dangerGunnerIdex] = max(hitRateVector);
dangerGunner = aliveGunnerVector(dangerGunnerIdex);
gunner.pWhoIsTheDanger = dangerGunner;
end
function setGunnerOrder(obj,gunner)
aliveGunnerVector = obj.findAliveGunner();
aliveGunnerVector = aliveGunnerVector(aliveGunnerVector ~= gunner);
gunner.setAliveOrder(aliveGunnerVector);
end
end
methods
function aliveGunner = findAliveGunner(obj)
aliveGunner = [];
if(1 == obj.gunnerList.dataDictionary(1).pIsAlive)
gunner1 = obj.gunnerList.dataDictionary(1);
aliveGunner = [aliveGunner,gunner1];
end
if(1 == obj.gunnerList.dataDictionary(2).pIsAlive)
gunner2 = obj.gunnerList.dataDictionary(2);
aliveGunner = [aliveGunner,gunner2];
end
if(1 == obj.gunnerList.dataDictionary(3).pIsAlive)
gunner3 = obj.gunnerList.dataDictionary(3);
aliveGunner = [aliveGunner,gunner3];
end
end
% 主要处理内容:
% 首先判断被射击者是否仍然存活
% 将开枪选手的事件更新到被射击者的信息库中
% 将射击后的在场抢手状态分发给所有抢手
% 遇到同时开枪的状况先进行判断的选手会更占优
function processShootEvent(obj,src,data)
% 获取袭击目标,并对袭击目标进行设置
target = src.pShootTarget;
target.pWhoShootMe = src;
target.pIsAlive = obj.isTargetAlive(src.pHitRate);
end
function isAlive = isTargetAlive(obj,pHitRate)
if(rand <= pHitRate)
isAlive = 0;
else
isAlive = 1;
end
end
end
end
枪手脚本
classdef Gunner<handle
properties
gunnerName;
pIsAlive;
pHitRate;
pShootSpeed;
pShootTarget;
pWhoShootMe;
pWhoIsTheDanger;
aliveGunner;
end
events
gunnerDidShoot;
end
methods
% 构造函数,设置枪手基本信息
function obj = Gunner(gunnerName,hitRate,shootSpeed)
obj.gunnerName = gunnerName;
obj.pIsAlive = 1;
obj.pHitRate = hitRate;
obj.pShootSpeed = shootSpeed;
obj.pWhoShootMe = 0;
obj.pWhoIsTheDanger = 0;
end
function didShoot(obj,didShoot)
if(didShoot == 1)
chooseTheTarget(obj);
obj.notify('gunnerDidShoot');
end
end
% 朝自己开枪的人里选最危险的那个
% 都没有朝自己开枪时候选最危险的那个
% 如果都没有,就随机选一个人
function chooseTheTarget(obj)
if(obj.pWhoShootMe ~= 0)
obj.pShootTarget = obj.pWhoShootMe;
elseif(obj.pWhoIsTheDanger ~= 0)
obj.pShootTarget = obj.pWhoIsTheDanger;
else
aliveNum = numel(obj.aliveGunner);
obj.pShootTarget = obj.aliveGunner(ceil(rand*aliveNum));
end
end
function setAliveOrder(obj,aliveOrder)
obj.aliveGunner = aliveOrder;
end
end
end
参赛选手名单脚本
classdef Context < handle
properties
dataDictionary;
dataLen;
end
methods
function obj = Context()
obj.dataDictionary = [];
end
end
methods
function register(obj,data)
obj.dataDictionary = [obj.dataDictionary,data];
obj.dataLen = obj.dataLen + 1;
end
function data = getData(obj,ID)
if isKey(obj.dataDictionary,ID)
data = obj.dataDictionary(ID);
else
error('ID NOT EXIST');
end
end
end
end