C++实现一个简单的博弈过程
Posted Jing Sir
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++实现一个简单的博弈过程相关的知识,希望对你有一定的参考价值。
如下所示,这是一个简单的博弈:
#include <iostream>
using namespace std;
class PDRule
{
public:
const int R; //同时合作的奖励R
const int S; //被背叛的损失S
const int T; //背叛的收益T
const int P; //同时背叛的惩罚P
PDRule(int R,int S,int T,int P):R(R),S(S),T(T),P(P){}
virtual ~PDRule(){}
int calculatePayoff(int stra1,int stra2);//根据两个参与博弈者的策略,计算第一个博弈者的收益
};
int PDRule::calculatePayoff(int stra1,int stra2)
{ //合作策略为1,背叛策略为0
if( stra1==1 && stra2==1 ) return R;
else if ( stra1==1 && stra2==0 ) return S;
else if ( stra1==0 && stra2==1 ) return T;
else return P;
}
class Player
{
protected:
int oppStra; // 对手上一轮策略
int id;
public:
Player(){
id = 1;
oppStra=-1; // 初始没有对手策略,设置为-1
}
virtual ~Player(){}
virtual int nextStra(); // 本轮采用的策略
virtual void setOppStra(int oppS);// 设置对手上一轮策略
virtual void reset(){oppStra=-1;} // 恢复到初始设置
virtual int getID() {return id;}
};
void Player::setOppStra(int oppS)
{
oppStra = oppS;
}
int Player::nextStra()
{
return 1; // 总是采用合作策略
}
class IterationPDG
{
private:
Player * player1;
Player * player2;
int maxTurn;
int payoff1;
int payoff2;
PDRule pdr;
public:
IterationPDG(int maxTurn, Player * p1,Player * p2, PDRule & pdr): maxTurn(maxTurn),pdr(pdr),player1(p1),player2(p2)
{
payoff1 = 0;
payoff2 = 0;
}
virtual ~IterationPDG(){}
void start();
int getPayoff1(){return payoff1;}
int getPayoff2(){return payoff2;}
};
void IterationPDG::start()
{
player1->reset();
player2->reset();
for(int i=0;i<maxTurn;i++){
int s1 = player1->nextStra();
int s2 = player2->nextStra();
payoff1 += pdr.calculatePayoff(s1,s2);
payoff2 += pdr.calculatePayoff(s2,s1);
player1->setOppStra(s2);
player2->setOppStra(s1);
}
}
class Player2103: public Player
{
private:
/*此处说明添加数据的用途
* oppHistory用于保存过去2次博弈对手的策略
*/
int sum_oppscore;//计算对手当前的总分
int sum_myscore; //计算我的总分
int myoppstra; //我的上一轮策论
int sum_oppstra; //对手的上一轮策略和
int i; //当前局次
int flag; //标记对方的程序是否为智能程序
public :
//提供无参构造函数
Player2103()
{
id = 2103; //命名id
sum_oppscore=0; //初始化对手当前得分
sum_myscore=0; //初始化我的当前得分
myoppstra=1; //初始化我第一轮的策略
sum_oppstra=0; //初始化对手上一轮策论和
i=0; //初始化当前轮次
flag=1; //默认对方为智能
}
/*一、统计对手和我的当前得分,若对方的分数减去我的分数小于等于2,下一轮合作,否则背叛
二、若前二十次对手都出合作,则二十次之后都出背叛*/
int nextStra() //重新定义该函数,让你的Player按照你的逻辑博弈
{
i++;
if(i<21 && flag)
{
if (sum_oppscore-sum_myscore<=14)
{
myoppstra=1;
return 1;
}
else
{
myoppstra=0;
return 0 ;
}
}
if(i==21 && sum_oppstra==20)
{
flag=0;
myoppstra=0;
return 0;
}
if(i>21 && flag==0)
{
myoppstra=0;
return 0 ;
}
else
{
if (sum_oppscore-sum_myscore<=14)
{
myoppstra=1;
return 1;
}
else
{
myoppstra=0;
return 0 ;
}
}
}
void setOppStra(int oppS)
{
sum_oppstra+=oppS;
if(oppS==1 && myoppstra==1)
{
sum_oppscore+=3;
sum_myscore+=3;
}
else if(oppS==1 && myoppstra==0)
{
sum_oppscore+=5;
sum_myscore+=0;
}
else if(oppS==0 && myoppstra==1)
{
sum_oppscore+=5;
sum_myscore+=0;
}
else
{
sum_oppscore+=1;
sum_myscore+=1;
}
}
void reset() // 恢复到初始设置
{
Player::reset();
sum_oppscore=0;
sum_myscore=0;
myoppstra=1;
sum_oppstra=0; //对手的上一轮策略和
i=0; //当前局次
flag=1;
//对新添加的数据进行reset
}
};
class Player1000: public Player
{
int flag;
public :
//无参构造函数
Player1000()
{
flag=1;
id=1000; //命名id
}
int nextStra()
{
if(flag)
{
flag=0;
return 0;
}
else
{
flag=1;
return 1;
}
}
};
class Player2077: public Player
{
private:
/*此处以多行注释的形式说明添加数据的用途
* oppHistory用于保存过去2次博弈对手的策略
*/
int sum_oppscore;//计算对手当前的总分
int sum_myscore; //计算我的总分
int myoppstra; //我的上一轮策论
int sum_oppstra; //对手的上一轮策略和
int i; //当前局次
int flag; //标记对方的程序是否为智能程序
public :
//必须提供无参构造函数
Player2077()
{
id = 2077; //命名id
sum_oppscore=0; //初始化对手当前得分
sum_myscore=0; //初始化我的当前得分
myoppstra=1; //初始化我第一轮的策略
sum_oppstra=0; //初始化对手上一轮策论和
i=0; //初始化当前轮次
flag=1; //默认对方为智能
}
/*一、统计对手和我的当前得分,若对方的分数减去我的分数小于等于2,下一轮合作,否则背叛
二、若前二十次对手都出合作,则二十次之后都出背叛*/
int nextStra() //重新定义该函数,让你的Player按照你的逻辑博弈
{
i++;
if(i<21 && flag)
{
if (sum_oppscore-sum_myscore<=14)
{
myoppstra=1;
return 1;
}
else
{
myoppstra=0;
return 0 ;
}
}
if(i==21 && sum_oppstra==20)
{
flag=0;
myoppstra=0;
return 0;
}
if(i>21 && flag==0)
{
myoppstra=0;
return 0 ;
}
else
{
if (sum_oppscore-sum_myscore<=14)
{
myoppstra=1;
return 1;
}
else
{
myoppstra=0;
return 0 ;
}
}
}
void setOppStra(int oppS)
{
sum_oppstra+=oppS;
if(oppS==1 && myoppstra==1)
{
sum_oppscore+=3;
sum_myscore+=3;
}
else if(oppS==1 && myoppstra==0)
{
sum_oppscore+=5;
sum_myscore+=0;
}
else if(oppS==0 && myoppstra==1)
{
sum_oppscore+=5;
sum_myscore+=0;
}
else
{
sum_oppscore+=1;
sum_myscore+=1;
}
}
void reset() // 恢复到初始设置
{
Player::reset();
sum_oppscore=0;
sum_myscore=0;
myoppstra=1;
sum_oppstra=0; //对手的上一轮策略和
i=0; //当前局次
flag=1;
//对新添加的数据进行reset
}
};
class Player1001:public Player
{
private:
int oppHistory[2];//oppHistory用于保存过去2次博弈对手的策略
public :
//必须提供无参构造函数
Player1001()
{
id=1001; //命名id
//初始化对手策略历史
oppHistory[0]=-1;
oppHistory[1]=-1;
}
/*此处以多行注释的形式说明博弈的逻辑
* 过去2次对手策略如连续为背叛(0,0),则本轮背叛对手,否则合作
*/
int nextStra() //重新定义该函数,让你的Player按照你的逻辑博弈
{
if(oppHistory[0]==0&&oppHistory[1]==0)
return 0;
else
return 1;
}
/*更新保存的博弈信息
*/
void setOppStra(int oppS)
{
Player::setOppStra(oppS);
oppHistory[0] = oppHistory[1];
oppHistory[1] = oppS;
}
void reset() // 恢复到初始设置
{
Player::reset();
oppHistory[0]=-1;
oppHistory[1]=-1; //对新添加的数据进行reset
}
};
class Player1234: public Player
{
int i,j;
public :
//无参构造函数
Player1234()
{
i=0;
j=0;
id=1234; //命名id
}
int nextStra()
{
while(i>0)
{
i--;
return 1;
}
j++;
i+=j;
return 0;
}
};
class Player5678: public Player
{
int i,j;
public :
//无参构造函数
Player5678()
{
i=0;
j=0;
id=5678; //命名id
}
int nextStra()
{
while(i>0)
{
i--;
return 0;
}
j++;
i+=j;
return 1;
}
};
int main()
{
Player2103 player2103; //派生类对象1
Player5678 player5678;
Player1001 player1001;
Player1234 player1234;
Player1000 player1000;
Player2077 player2077; //派生类对象2
Player * players [6] ; //将所有博弈者收集到基类数组(异类收集)
players [0] = & player2103 ;
players [1] = & player5678 ;
players [2] = & player1001 ;
players [3] = & player1234 ;
players [4] = & player1000 ;
players [5] = & player2077 ;
int payoffs[6]={0,0,0,0,0,0};
PDRule pdr(3,0,5,1); //int R,int S,int T,int P
int maxTurn = 100; //该值在最后博弈时可能是100-1000中的任意值
for( int i = 0 ; i < 6; i++) {
for( int j = 0 ; j < 6 ; j++){
if ( i<j ){
IterationPDG ipdg( maxTurn, players[i], players[j], pdr);
ipdg.start();
payoffs[i] += ipdg.getPayoff1();
payoffs[j] += ipdg.getPayoff2();
}
}
}
for( int i = 0 ; i < 6 ; i++) {
cout<<players[i]->getID()<<" : "<<payoffs[i]<<endl;
}
}
以上是关于C++实现一个简单的博弈过程的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C++ 中为 GLSL 片段着色器实现 iGlobalTime?