最近在看一本关于博弈的书.有个比较简单的合作不合作的博弈.挺有意思,大意是这样的:
这个博弈是对现实生活中人与人之间是否合作的简单抽象,具体内容和规则可以概括为“如果A与B都是合作态度,则是双赢,每人得3分;如果A合作态度,B玩阴的,则A欺骗了B,取得了B本该得到的利益,则B得5分,A扣3分,反之亦然。最后如果A和B都不合作,则一拍两散,两个人都白费劲,则每人扣一分”在这个游戏里,每个人都和除了自己之外的人合作100次,则得分最高的人胜利.
我抽象到C#代码里是用一个接口来规范参与者,让他们实现自己的算法,并通过泛型列表保存和对手之间以往的合作记录,并可以根据合作记录来返回采取的策略..废话不说接口代码如下:
Code
1 public interface ActorBase
2 {
3 bool Gamble(string OpponentName);//你的策略封装在这个函数里,true是合作false是不合作
4 string GetUniqueCode();//用于返回你的名字来让对手确认你的身份
5 int Score { get; set; }//记录总分
6 void AddRecord(string OpponentName,bool record); //用于添加以往对战的记录
7 }
对于我的策略,我在第一次合作时保持合作态度,在以后是否合作都根据对手和自己上一步的情况来确定是否合作
具体代码如下:
1
public
class
CareySon : ActorBase
2
{
3 Dictionary<string, List<bool>> Record;//用于保存和对手以往的记录
4 public Songyunjian()//构造函数,用于构造记录
5 {
6 Record = new Dictionary<string, List<bool>>();
7 }
8 public string GetUniqueCode() //返回你的唯一标识
9 {
10 return "CareySon";
11 }
12 public void AddRecord(string OpponentName, bool record)
13 {
14 if (!Record.ContainsKey(OpponentName))//如果没合作过,创建合作记录
15 {
16 List<bool> l = new List<bool>();
17 l.Add(record);
18 Record.Add(OpponentName, l);
19 }
20 else
21 {
22 Record[OpponentName].Add(record);//利用索引器把记录添加到list里
23 }
24 }
25 public bool Gamble(string name)
26 {
27 if (!Record.ContainsKey(name))//如果是第一次合作,则保持合作态度
28 {
29 return true;
30 }
31 else
32 {
33 List<bool> t = Record[name];
34 if (t.Count >= 1)
35 {
36 if (t[t.Count - 1])//如果最后一次是合作则返回合作
37 {
38 return true;
39 }
40 else//否则返回不合作
41 {
42 return false;
43 }
44 }
45 return true;
46
47
48 }
49 }
50 public int Score
51 {
52 get { return _score; }
53 set{_score=value;}
54 }
55 public int _score=0;//用于记录每个人的分数
56
57 }
下面是一个我加进去的随机选手,即合作和不合作的态势是随机的,这里只展示Gamble()方法,其他同
1
public
bool
Gamble(
string
name)
2
{
3
Random rd
=
new
Random();
4
int
i
=
rd.Next(
2
);
5
if
(i
==
1
)
6
{
7
return
true
;
8
}
9
return
false
;
10
}
下面是我一个舍友的策略,即根据后3次的合作记录来返回是否合作,Gamble()方法如下:
1
public
bool
Gamble(
string
name)
2
{
3
int
z
=
0
;
4
if
(
!
Record.ContainsKey(name))
5
{
6
return
true
;
7
}
8
else
9
{
10
List
<
bool
>
l
=
Record[name];
11
if
(l.Count
==
1
)
12
{
13
if
(l[
0
])
14
{
15
return
true
;
16
}
17
else
18
{
19
return
false
;
20
}
21
}
22
else
if
(l.Count
==
2
)
23
{
24
if
(l[
0
]
&&
l[
1
])
25
{
26
return
true
;
27
}
28
else
29
{
30
return
false
;
31
}
32
}
33
else
if
(l.Count
>=
3
)
34
{
35
if
(l[l.Count
-
1
]) z
++
;
36
if
(l[l.Count
-
2
]) z
++
;
37
if
(l[l.Count
-
3
]) z
++
;
38
if
(z
>=
2
)
return
true
;
39
else
{
40
return
false
;
41
}
42
}
43
}
44
return
false
;
45
}
我的另一个舍友的策略是通过以往所有的合作记录来决定,如果合作次数大于不合作的,则合作,如果小于,则不合作,等于也不合作,代码如下:
1
public
bool
Gamble(
string
name)
2
{
3
int
z
=
0
, c
=
0
;
//
z是合作次数,c是不合作次数
4
if
(
!
Record.ContainsKey(name))
5
{
6
return
true
;
7
}
8
else
9
{
10
foreach
(
bool
b
in
Record[name])
11
{
12
if
(b) z
++
;
13
else
14
{
15
c
++
;
16
}
17
}
18
if
(z
==
c)
19
{
20
return
false
;
21
}
22
if
(z
>
c)
23
{
24
return
true
;
25
}
26
if
(z
<
c)
27
{
28
return
false
;
29
}
30
}
31
return
false
;
32
33
}
最后是客户端调用的代码
1
using
System;
2
using
System.Collections.Generic;
3
using
System.Linq;
4
using
System.Web;
5
using
System.Web.UI;
6
using
System.Web.UI.WebControls;
7
using
TheGame;
8
public
partial
class
GameTheory : System.Web.UI.Page
9
{
10
protected
void
Page_Load(
object
sender, EventArgs e)
11
{
12
List
<
TheGame.ActorBase
>
player
=
new
List
<
TheGame.ActorBase
>
();
//
我把接口和实现的代码放入了TheGame命名空间
13
TheGame.ActorBase CareySon
=
new
TheGame.Songyunjian();
14
TheGame.ActorBase RandomPlayer
=
new
TheGame.RandomPlayer();
15
TheGame.ActorBase Tony
=
new
TheGame.Tony();
16
TheGame.ActorBase Jack
=
new
TheGame.Jack();
17
player.Add(CareySon);
18
player.Add(RandomPlayer);
19
player.Add(Tony);
20
player.Add(Jack);
21
/*
从这里开始下面都是算法部分
*/
22
for
(
int
x
=
1
; x
<=
100
; x
++
)
//
循环合作100次
23
{
24
for
(
int
i
=
0
; i
<
player.Count; i
++
)
//
让选手和其他所有选手进行博弈
25
{
26
for
(
int
j
=
i
+
1
; j
<
player.Count; j
++
)
27
{
28
29
bool
abBool
=
player[i].Gamble(player[j].GetUniqueCode());
30
ActorBase ab
=
player[i];
31
bool
absBool
=
player[j].Gamble(player[i].GetUniqueCode());
32
ActorBase abs
=
player[j];
33
if
(abBool
&&
absBool)
//
当AB合作的时候
34
{
35
ab.Score
+=
3
;
36
abs.Score
+=
3
;
37
ab.AddRecord(abs.GetUniqueCode(),
true
);
38
abs.AddRecord(ab.GetUniqueCode(),
true
);
39
}
40
else
if
(abBool
&
!
absBool)
//
当AB合作而ABS不合作
41
{
42
ab.Score
-=
3
;
43
abs.Score
+=
5
;
44
ab.AddRecord(abs.GetUniqueCode(),
false
);
45
abs.AddRecord(ab.GetUniqueCode(),
true
);
46
}
47
else
if
(absBool
&
!
abBool)
//
当abs合作而AB不合作的情况
48
{
49
ab.Score
+=
5
;
50
abs.Score
-=
3
;
51
ab.AddRecord(abs.GetUniqueCode(),
true
);
52
abs.AddRecord(ab.GetUniqueCode(),
false
);
53
}
54
else
if
(
!
absBool
&&
!
abBool)
//
当双方都不合作的情况下
55
{
56
ab.Score
-=
1
;
57
abs.Score
-=
1
;
58
ab.AddRecord(abs.GetUniqueCode(),
false
);
59
abs.AddRecord(ab.GetUniqueCode(),
false
);
60
}
61
62
}
63
}
64
}
65
OutputResult(player);
//
输出并打印到屏幕上成绩
66
67
}
68
private
void
OutputResult(List
<
TheGame.ActorBase
>
l)
69
{
70
foreach
(ActorBase ab
in
l)
71
{
72
HttpContext.Current.Response.Write(
"
Player: <span style='background-color:#cdcdcd;color:blue;border:solid 1px #3cdcad'>
"
+
ab.GetUniqueCode()
+
"
</span> and the Score is <span style='background-color:#cdcdcd;color:blue;border:solid 1px #3cdcad'>
"
+
ab.Score.ToString()
+
"
</span><br />
"
);
73
}
74
}
75
}
76
自此代码就完了,代码有点粗糙,各位看官切勿仍板砖-.-!!
某一次的运行结果如下,我就不抓图了:
-----------------------------------------------------
Player:
CareySon and the Score is
686
Player:
RandomPlayer and the Score is
570
Player:
Tony and the Score is
670
Player:
Jack and the Score is
734
-----------------------------------------------------
园子里有很多博弈学高手,有什么好的策略发上来一起探讨下:-)