大富翁银行游戏盘——泰国之旅

对于大富翁游戏的简单建模

昨天晚上和朋友们一起玩大富翁游戏,玩了几局总是输,我怀疑先出发的玩家大概率是赢家。于是和一朋友利用matlab对游戏进行仿真。游戏规则已经简化,但基本符合我们的游戏规则。下面是代码部分。
主程序。
在这里插入图片描述

主程序

clear;clc;
dbstop if error
%% 模拟大富翁
tic
ITER = 2000;
winer = cell(ITER,11);
for TIMES = 1:ITER
    % 定义地图
    D.placedata = [2400,200,1200,6000,11000,1000,1200;
        3000,300,1600,7000,13000,1500,1500;
        2600,300,1600,7000,13000,1500,1300;
        2800,300,1600,7000,13000,1500,1400;
        2600,300,1600,7000,13000,1500,1300;
        3200,400,2000,8000,16000,2000,1600;
        3600,400,2000,8000,16000,2000,1800;
        2200,200,1200,6000,11000,1000,1100;
        3400,400,2000,8000,16000,2000,1700;
        2200,200,1200,6000,11000,1000,1100;
        2400,200,1200,6000,11000,1000,1200;
        3200,400,2000,8000,16000,2000,1600;
        2800,300,1600,7000,13000,1500,1400;
        3400,400,2000,8000,16000,2000,1700;
        3000,300,1600,7000,13000,1500,1500;
        3600,400,2000,8000,16000,2000,1800;
        2000,3000,6000,9000,12000,+inf,1000;
        2000,3000,6000,9000,12000,+inf,1000;
        2000,3000,6000,9000,12000,+inf,1000;
        2000,3000,6000,9000,12000,+inf,1000;];
    % 0表示起始地,+20001-16表示地点索引,17-20表示连锁地点,-1表示机会和命运,-2表示获得一枚幸运星,-3表示什么也不做
    D.map = [0,1,17,2,-1,3,4,-1,5,-2,-1,6,7,18,8,-3,-1,9,10,11,12,19,-1,20,-3,13,14,-1,15,16];
    % 第一列为目前所在地,第二列为目前所有金钱,第三列为目前持有空地,目前持有一星地,二星地,三星地,现状态 0为正常,1为跳过
    % 第八列为幸运星个数 第九列为在抵押房产,第十列为是否已经遍历,第十一列为玩家索引
    D.N = 4;%N个玩家
    D.starts = 7;%幸运星个数为7
    D.people = cell(D.N,11);
    %初始化目前所在地
    for i = 1:size(D.people,1)
        D.people{i,1} = 1;
        D.people{i,2} = 15000;
        D.people{i,7} = 0;
        D.people{i,10} = 0;
        D.people{i,11} = i;
    end
    turns = 0;
    while true%一局
        %循环遍历每个玩家
        player = 1;
        while true%一轮
            if size(D.people,1)==1
                break
            end
            D.people{player,10} = 1;
            %如果要跳过,则跳过
            if D.people{player,7}==1
                D.people{player,7} = 0;
                if sum(cell2mat(D.people(:,10))) ~= size(D.people,1)
                    player = find(cell2mat(D.people(:,10)) == 0);
                    player = player(1);
                    continue
                else
                    break
                end
            end
            %随机抛色子
            dian = randperm(6,1);
            [D.people{player,1},tf] = chulidian(D.people{player,1}+dian);
            %得到现在地点是什么内容
            if tf == 1 %如果经历了原点
                D.people{player,2} = D.people{player,2}+2000;
            end
            content = D.map(D.people{player,1});
            %         D = contentcheck(D);
            if content == 0

            elseif content == -2
                D.people{player,8} = D.people{player,8}+1;
                D = xingyunxingcheck(D,player);
            elseif content == -1
                D = destinyandchance(D,player);
            elseif content == -3

            else
                [D,tf] = paycheck(D,player);
                if tf ~= 1%如果没有破产则进行购买检测
                    D = buycheck(D,player);
                    %                 else%如果破产则找到下一个玩家
                    %                     if sum(cell2mat(D.people(:,10))) ~= size(D.people,1)
                    %                         player = find(cell2mat(D.people(:,10)) == 0);
                    %                         player = player(1);
                    %                     else
                    %                         break
                    %                     end
                end
            end
%             disp(sum(cell2mat(D.people(:,10))))
%             disp(size(D.people,1))
%             disp('-----------------------------------')
            if sum(cell2mat(D.people(:,10))) ~= size(D.people,1)
                player = find(cell2mat(D.people(:,10)) == 0);
                player = player(1);
            else

                break
            end
        end
        %         for i = 1:size(D.people,1)
        %             if isempty(D.people(i,1))
        %                 D.people(i,:) = [];
        %             end
        %         end
        %将所有玩家的被访问信息置零
        for i = 1:size(D.people,1)
            D.people{i,10} = 0;
        end
        turns = turns+1;
        if size(D.people,1) == 1
            break
        end

    end
    winer(TIMES,:) = D.people;
    clear D
    disp(TIMES)
end
%% 结果分析
%检查最后获胜玩家和投色子的先后顺序的关系
win = zeros(ITER,1);
money = zeros(ITER,1);
for i = 1:size(winer,1)
    win(i) = winer{i,11};
    money(i) = winer{i,2};
end
figure(1)
histogram(win)
figure(2)
histogram(money)
toc

%%

xlswrite('wind.xls', win);    
xlswrite('money.xls', money);

得到所有玩家的幸运星列表

function Dout = xingyunxingcheck(D,player)
%得到所有玩家的幸运星列表
startslist = cell2mat(D.people(:,8));
% 如果幸运星被分配完,则选取最多的几位玩家随机在自己地盘上盖房子
if sum(startslist)==D.starts
    %统计该玩家有多少块地以及可以建房屋的地
    di = D.people(player,3:5);
    %统计这些地建一所房屋需要花费多少钱,优先建造有2所房屋的地方
    for i = 3:-1:1
        if isempty(di(i))
            continue
        else
            houseidx = cell2mat(di(i));
            houseconprice = D.placedata(houseidx,6);
            houseconprice(houseconprice==+inf) = [];
            if isempty(houseconprice)
                continue
            else
                %取最大的一个建造价格,造房子
                [house,houseidx] = find(houseconprice==max(houseconprice));
                house = house(1);
                houseidx = houseidx(1);
                D.people{player,i}(houseidx) = [];
                D.people{player,i+1}(end+1) = house;
                break
            end
        end
    end
    %将所有玩家幸运星清零
    for i = 1:size(D.people,1)
        D.people{i,8} = 0;
    end

end
    Dout = D;

规则判断与执行

function Dout = destinyandchance(D,player)
object = [1,1,2,2,3,3,4,4,5,6,7,8,9,10,11,11];
len = length(object);
r = randperm(len,1);
event = object(r);
if event == 1%减一个幸运星
    D.people{player,8} = D.people{player,8}-1;
elseif event == 2%加一个幸运星
    D.people{player,8} = D.people{player,8}+1;
    D = xingyunxingcheck(D,player);
elseif event == 3%让该玩家与另一玩家减500
    tempplayer = randperm(size(D.people,1),1);
    while tempplayer == player
    tempplayer = randperm(size(D.people,1),1);
    end
    %找到tempplayer的初始编号
    startind = D.people{tempplayer,11};
    D.people{player,2} = D.people{player,2}-500;
    D.people{tempplayer,2} = D.people{tempplayer,2}-500;
    D = breakcheck(D,player);
    [~,row] = ismember(startind,cell2mat(D.people(:,11)));
    D = breakcheck(D,row);
elseif event == 4%让该玩家减750
    D.people{player,2} = D.people{player,2}-750;
    D = breakcheck(D,player);
elseif event == 5%让该玩家减100
    D.people{player,2} = D.people{player,2}-100;
    D = breakcheck(D,player);
elseif event == 6%让该玩家减200
    D.people{player,2} = D.people{player,2}-200;
    D = breakcheck(D,player);
elseif event == 7%让该玩家减500
    D.people{player,2} = D.people{player,2}-500;
    D = breakcheck(D,player);
elseif event == 8%让该玩家加1850
    D.people{player,2} = D.people{player,2}-1850;
elseif event == 9%让该玩家加1000
    D.people{player,2} = D.people{player,2}-1850;
elseif event == 10%3000停一轮
    D.people{player,2} = D.people{player,2}+3000;
    D.people{player,7} = 1;
elseif event == 11%2/3 stop 1/3 nothing
    if rand()<2/3
        D.people{player,7} = 1;
    end
end
Dout = D;

支付玩家过路费&得到玩家到达地点

function [Dout,tf] = paycheck(D,player)
%支付玩家过路费
%得到玩家到达地点
dian = D.map(D.people{player,1});
%判断地点的归属
tempplayer = 0;
for i = 1:size(D.people,1)
    for j = 3:6
        if ismember(dian,D.people{i,j})
            tempplayer = i;
            break
        end
    end
    if tempplayer ~=0
        break
    end
end
if tempplayer ~= 0 
    %支付玩家乾
    D.people{tempplayer,2} = D.people{tempplayer,2}+D.placedata(dian,j-1);
    D.people{player,2} = D.people{player,2}-D.placedata(dian,j-1);
    
    [D,tf] = breakcheck(D,player);
else
    tf = 0;
end
Dout = D;

选择是否购买该地

function Dout = buycheck(D,player)
%选择是否购买该地
%得到该土地购买价格
dian = D.map(D.people{player,1});
price = D.placedata(dian,1);
%得到该玩家剩余乾数量
res = D.people{player,2};
%如果剩余乾数量大于土地购买价格则购买土地
%判断地点的归属
tempplayer = 0;
for i = 1:size(D.people,1)
    for j = 3:6
        if ismember(dian,D.people{i,j})
            tempplayer = i;
            break
        end
    end
    if tempplayer ~=0
        break
    end
end
%如果没有人拥有这件地产则选择够不够买
if tempplayer == 0 
    if price<res
        D.people{player,2} = D.people{player,2}-price;
        D.people{player,3}(end+1) = dian;
    end
end
%如果土地是自己的则选择是不是购买绿房子
if tempplayer == player
    if j ~= 6
        upgradeprice = D.placedata(dian,6);
        upgradeprice(upgradeprice==+inf) = [];
        if ~isempty(upgradeprice)
        if upgradeprice<res
            %升级房屋
            D.people{player,j}(D.people{player,j}==dian) = [];
            D.people{player,j+1}(end+1) = dian;
        end
        end
    end
end
Dout = D;

找到破产的玩家

function [Dout,tf] = breakcheck(D,player)
tf = 0;
%找到破产的玩家
own = D.people{player,2};
if own<0
    %得到该玩家欠债数
    %清算该玩家的房产
    house = D.people(player,3:6);
    %先卖房屋数量少的房产
    for i = 1:4
        payoff = 0;
        h = house{i};
        if ~isempty(h)
            %将抵押费从小到大排序
            hmortgage = D.placedata(h,7);
            hmortgage(hmortgage == +inf) = [];
            [val,ind] = sort(hmortgage,'ascend');
            hmortgage = val;
            j = 1;
            while true
                %首先卖掉所有房子
                own = own+(i-1)*0.5*D.placedata(ind(j),6);
                %将该房产绿色房子数量减至0
                    D.people{player,i+2}(ind(j)) = [];
                    D.people{player,3}(end+1) = h(ind(j));
                if own < 0
                    %卖掉该房屋
                    own = own+D.placedata(ind(j),7);
                    D.people{player,3}(end) = [];
                    D.people{player,9}(end+1) = h(ind(j));
                end
                if own >0
                    payoff = 1;
                    break
                end
                hmortgage(j) = [];
                if isempty(hmortgage)
                    break
                else
                    [val,ind] = sort(hmortgage,'ascend');
                    hmortgage = val;
                end
            end
            if payoff == 1
                break
            end
        end
    end
    if payoff == 1
        D.people{player,2} = own;
    else
        D.people(player,:) = [];
        tf = 1;
    end

end
Dout = D;

处理位置点

function [dian,tf] = chulidian(data)
if sum(data>30)>0
    tf = 1;
else
    tf = 0;
end
    data(data>30) = data(data>30)-30;
    dian = data;
end

获胜者分布

西木康

获胜者资金分布

西木康

附加 朋友文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值