本人刚学java,没什么基础,想写一个动态博弈的小程序,内容如下:
囚徒困境博弈,两个人分别有cooperate(合作)和defect(背叛)两种选择,如果双方均cooperate,收益各为-1;如果一方cooperate另一方defect,则前者收益-10,后者收益0;如果双方均defect,则收益各为-9。
现在有三种人(策略),第一种人总是defect,第二种人随机选择cooperate或defect,第三种人的策略称为Tit-for-Tat,即第一轮cooperate,然后模仿对方上一轮的选择。
三种人两两配对进行博弈,博弈一共进行10轮,然后计算并打印每种人的总收益。
以下是我写的源程序:
class Strategy{
String[] a=new String[10];//每个阶段的行动,总共进行10轮博弈
String name;//策略的名称
int revenue;//策略在博弈中的总收益
Strategy(String name){
this.name=name;
}
String Getopponent(Strategy s,int round){   //获取对方上一轮的策略
return s.a[round];
}
}
public class MPDyPDgameTFT{
public static void main(String[] args){
Strategy[] S=new Strategy[3];
S[0]=new Strategy("Tit-for-Tat");
S[1]=new Strategy("Random");
S[2]=new Strategy("Always Defect");
MPDyPDgameTFT g=new MPDyPDgameTFT();
g.PDgame(S);                          
g.print(S);
}
public void PDgame(Strategy[] s){                       //囚徒困境博弈
for(int id1=0;id1<=2;id1++){
for(int id2=1;id2<=2;id2++){
for(int i=0;i<10;i++){
s[2].a[i]="defect";
if(Math.random()<=0.5)
s[1].a[i]="defect";
else s[1].a[i]="cooperate";
if(i==0)
s[0].a[i]="cooperate";
else
s[0].a[i]=(s[0].Getopponent(s[id2], i-1));//模仿对手上一轮的选择
if(id2<=id1)
continue;
if(s[id1].a[i]=="cooperate"){
if(s[id2].a[i]=="cooperate"){
s[id1].revenue+=-1;
s[id2].revenue+=-1;
}
else
s[id1].revenue+=-10;
}
else{
if(s[id2].a[i]=="cooperate"){
s[id2].revenue+=-10;
}
else
s[id1].revenue+=-9;
    s[id2].revenue+=-9;
}
}
}
}

}
public void print(Strategy[] s){
System.out.println("10轮博弈结果如下:");
for(int id=0;id<=2;id++){
System.out.println(s[id].name+"的收益为:"+s[id].revenue);
}
}
}这个程序在eclipse中可以正常运行,但我觉得程序非常混乱。大家能不能建议一下,这个程序的结构应该怎样安排才合理?

解决方案 »

  1.   

    花了很长时间重写了程序,看起来好一些了,但是碰到了一个很严重的问题,大家帮我看看吧!
     
    package game;
    class Strategy{
    String[] Action; //每轮的行动
    int[] Revenue; //每轮的收益
    int SumRevenue=0; //总收益
    static int rounds=10;
    Strategy(){
    this.Action=new String[rounds];
    this.Revenue=new int[rounds];
    for(int i=0;i<rounds;i++){
    this.SumRevenue+=this.Revenue[i];
    }
    }
    public void print(){
    System.out.println("收益为"+this.SumRevenue);
    }
    }
    class TFT extends Strategy{
    String getoppo(Strategy s,int r){
    return s.Action[r];
    }
    TFT(){
    this.Action[0]="cooperate";
    for(int i=1;i<rounds;i++){
    this.Action[i]=this.getoppo(s,i-1);/*此处有错。当我试图把TFT单独定义为一个类时,问题出现了:
                                         因为TFT总是模仿对手上一轮的策略,而在TFT实例化之前并不知道它的对
                                         手是什么,因此也无法对TFT类进行定义。*/
    }
    }
    }
    class Random extends Strategy{
    Random(){
    for(int i=0;i<rounds;i++){
    if(Math.random()<=0.5)
    this.Action[i]="cooperate";
    else
    this.Action[i]="defect";
    }
    }
    }
    class AlwaysDefect extends Strategy{
    AlwaysDefect(){
    for(int i=0;i<rounds;i++)
    this.Action[i]="defect";
    }
    }
    public class PrisonsDilemmaGame{
    public void pdgame(Strategy a,Strategy b){
    for(int i=0;i<10;i++){
    if(a.Action[i]=="cooperate"){
    if(b.Action[i]=="cooperate"){
    a.Revenue[i]--;
    b.Revenue[i]--;}
    else 
    a.Revenue[i]-=10;
    }
    else{
    if(b.Action[i]=="defect"){
    a.Revenue[i]-=9;
    b.Revenue[i]-=9;}
    else 
    b.Revenue[i]-=10;
    }
    }
    }
    public static void main(String[] args){
    TFT s1=new TFT();
    Random s2=new Random();
    AlwaysDefect s3=new AlwaysDefect();
    PrisonsDilemmaGame g=new PrisonsDilemmaGame();
    g.pdgame(s1,s2);
    g.pdgame(s2,s3);
    g.pdgame(s1,s3);
    System.out.println("10轮收益结果如下:");
    System.out.print("Tit-for-Tat的收益为");
    s1.print();
    System.out.print("Random的收益为");
    s2.print();
    System.out.print("Always Defect的收益为");
    s3.print();
    }
    }
    请高手帮我看看怎么解决这个问题。
      

  2.   

    可以在你的类中再增加一个变量,lase 用来记录上次的选择。
      

  3.   

    先不说TFT的问题
    this.SumRevenue+=this.Revenue[i];
    你这句话写在构造函数里,那时候Revenue还没有赋值,默认0,也就是说SumRevenue是0。
    你最后打印的话,一定都是0。
      

  4.   

    再说你TFT的问题。
    在TFT的构造函数里,只给Action[0]赋值就好了。
    然后给Strategy加一个是否是TFT的标记。
    在PrisonsDilemmaGame里加点判断,如果传入的对象是TFT的话,就把另一个对象这次的策略赋值给TFT的Action[index++]。index=1;
    其他都一样就行了。另外建议你把策略用int常量表示。
      

  5.   

    谢谢slert的指教!但是很多策略都要参考对方上一轮的行动来进行博弈的,例如TFT和TF2T这两个策略的构造必须有其他策略上一轮的行动。那么对这两种策略分别进行实例化的时候就涉及到了相互引用的关系。
    我还有一个问题请教,如果有很多种策略(例如100种)进行博弈,能不能设计一个循环呢?应该怎么设计啊?我初步的想法是建立一个策略的数组,请问是否可行?或者还有没有其他方法?
    我说的有点乱,不知道大家能不能听明白。
    第一次来论坛发言,得到那么多人的帮助,感谢大家!
      

  6.   

    你有好好看我的回复么?还是我表达的不够清楚。
    你在实例化的时候是不可能预知到之后的行动的,那你有什么可能在实例化的时候就给Action数组的所有元素赋值?
    所以你的问题根本不是涉及到相互引用,而是你无法预知未来。呵呵。
    既然TFT的行动只有第一次是确定的,那么实例化的时候只给Action[0]赋值不就好了嘛。然后在父类Strategy里加一个boolean值的标记,用来标识是否是根据对方行动执行的策略,也就是在实例化的时候不能确定的策略。PrisonsDilemmaGame里根据那个标记做判断。如果是TFT,或是TF2T,这类的,就在一次博弈以后,用对方的行动给Action[i+1]赋值。Action[i+1]也就是下一次的行动。注意最后判断下不要数组越界就好了。boolean值标记的方式也不是最好,我的想法是给根据对方行动的策略抽象出一个共同的父类,然后用instanceof判断就好了。不过如果两个策略都是根据对方行动来的,可能就会有点复杂,但也就是多做判断而已。思路清楚一点,其实就是点逻辑问题,理清楚程序的执行流程,没什么难的。
    还有你说的策略数组,当然是可行的。只要逻辑OK,没什么是不可行的。加油吧。享受动脑的过程。哈哈哈。
      

  7.   

    问题解决了,首先要感谢国家,其次感谢cctv和mtv,最后也是最重要的,感谢本贴的所有热情帮助的朋友!