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++实现一个简单的博弈过程的主要内容,如果未能解决你的问题,请参考以下文章

VsCode 代码片段-提升研发效率

如何在 C++ 中为 GLSL 片段着色器实现 iGlobalTime?

简单博弈

详细实例说明+典型案例实现 对动态规划法进行全面分析 | C++

GAN生成对抗网络----手写数据实现

GAN生成对抗网络----手写数据实现