本人刚学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中可以正常运行,但我觉得程序非常混乱。大家能不能建议一下,这个程序的结构应该怎样安排才合理?
囚徒困境博弈,两个人分别有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中可以正常运行,但我觉得程序非常混乱。大家能不能建议一下,这个程序的结构应该怎样安排才合理?
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();
}
}
请高手帮我看看怎么解决这个问题。
this.SumRevenue+=this.Revenue[i];
你这句话写在构造函数里,那时候Revenue还没有赋值,默认0,也就是说SumRevenue是0。
你最后打印的话,一定都是0。
在TFT的构造函数里,只给Action[0]赋值就好了。
然后给Strategy加一个是否是TFT的标记。
在PrisonsDilemmaGame里加点判断,如果传入的对象是TFT的话,就把另一个对象这次的策略赋值给TFT的Action[index++]。index=1;
其他都一样就行了。另外建议你把策略用int常量表示。
我还有一个问题请教,如果有很多种策略(例如100种)进行博弈,能不能设计一个循环呢?应该怎么设计啊?我初步的想法是建立一个策略的数组,请问是否可行?或者还有没有其他方法?
我说的有点乱,不知道大家能不能听明白。
第一次来论坛发言,得到那么多人的帮助,感谢大家!
你在实例化的时候是不可能预知到之后的行动的,那你有什么可能在实例化的时候就给Action数组的所有元素赋值?
所以你的问题根本不是涉及到相互引用,而是你无法预知未来。呵呵。
既然TFT的行动只有第一次是确定的,那么实例化的时候只给Action[0]赋值不就好了嘛。然后在父类Strategy里加一个boolean值的标记,用来标识是否是根据对方行动执行的策略,也就是在实例化的时候不能确定的策略。PrisonsDilemmaGame里根据那个标记做判断。如果是TFT,或是TF2T,这类的,就在一次博弈以后,用对方的行动给Action[i+1]赋值。Action[i+1]也就是下一次的行动。注意最后判断下不要数组越界就好了。boolean值标记的方式也不是最好,我的想法是给根据对方行动的策略抽象出一个共同的父类,然后用instanceof判断就好了。不过如果两个策略都是根据对方行动来的,可能就会有点复杂,但也就是多做判断而已。思路清楚一点,其实就是点逻辑问题,理清楚程序的执行流程,没什么难的。
还有你说的策略数组,当然是可行的。只要逻辑OK,没什么是不可行的。加油吧。享受动脑的过程。哈哈哈。