一个老题,扑克博弈
蛮有趣的博弈问题A,B两人玩一个游戏,每位参加者发18张牌:三张6点,三张5点,三张4点,三张3点,三张2点,三张1点.他们轮流出牌,A先出一张,B再出一张,每轮不能不出牌.
谁先出的牌使得桌子上的牌的全部点数之和等于50谁就算赢了,
但若那张牌使全部点数之和超过了50,他就算输了.问A和B谁有必胜策略? 倒想起了原来编递归函数来算阶乘。 A先出1点,以后看B出x点,则自己出(7-x)点,这样使桌面上的点数总和保持为(7k+1)型,可拿到50的情形。
B看出了苗头,并利用A手头1点数目不足的弱点,最后三轮中连出6点,让A无法形成上述策略而告输。
抛砖引玉。具体怎样设计策略而稳赢,还没想好。 那显然A的策略是必输策略阿
呵呵 可以用程序解决吗?用程序复杂度不高:lol 有简单的方法吗?计算机说只要先手先出3,4,5或6都可以赢 :b:
能不能出示你的程序
另外,这种策略类的游戏
能不能不用C/C++程序
Prolog/Lisp/Haskell/SML/Python等都可以
唯独不要用C/C++,呵呵 习惯用C/C++了,其它语言基本不会用了。
#include <stdio.h>
#define LIMIT (1<<24)
int states;
#define FAIL -1
#define SUCC -2
void gen(int left){
int first_u=left&((1<<12)-1);
int second_u=left>>12;
int cfirst,csecond;
int i,sum;
cfirst=csecond=0,sum=0;
for(i=0;i<6;i++){
int c1=(first_u>>(2*i))&3;
int c2=(second_u>>(2*i))&3;
cfirst+=c1;
csecond+=c2;
sum+=(c1+c2)*(i+1);
}
sum=126-sum;
if(sum>50){
states=FAIL;
}else if(sum==50){
states=SUCC;
}else{
int s,j;
for(i=0;i<6;i++){
s=(first_u>>(2*i))&3;
}
for(i=0;i<6;i++){
int new_u=first_u;
int reach;
if(s>0){
new_u-=1<<(2*i);
}
reach=second_u|(new_u<<12);
if(states==SUCC)
break;
}
if(i<6){
states=FAIL;
}else{
states=SUCC;
}
}
}
void output_states(int x);
int next_state(int x)
{
int first_u=x&((1<<12)-1);
int second_u=x>>12;
int i,s;
for(i=0;i<6;i++){
s=(first_u>>(2*i))&3;
}
int reach=-1;
for(i=0;i<6;i++){
int new_u=first_u;
if(s>0){
new_u-=1<<(2*i);
reach=second_u|(new_u<<12);
if(states==SUCC){
output_states(reach);
}
}
}
return reach;
}
void output_states(int x)
{
printf("State %06x:",x);
if(states==SUCC){
printf("F");
}else{
printf("S");
}
printf("\n");
}
int main()
{
int i;
for(i=0;i<LIMIT;i++){
gen(i);
}
output_states(LIMIT-1);
printf("next states:\n");
next_state(LIMIT-1);
return 0;
}
原帖由 mathe 于 2008-7-2 09:31 发表 http://bbs.emath.ac.cn/images/common/back.gif
有简单的方法吗?计算机说只要先手先出3,4,5或6都可以赢
可否用文字具体叙述之后的出牌策略?:Q: 程序用一个24比特的整数表示牌局中一个状态,
低12比特代表接下去出牌的人手中牌的状态,高12比特代表另外一个人手中牌的状态。
其中12比特可以看成6个两比特的数据,分别代表持有1,2,3,...,6的数目(0~3张)
然后一次计算各个局面是先手胜还是先手负,结果SUCC表示先手负(无论怎么出牌都会达到FAIL局面),FAIL表示先手胜局面(存在一种出牌方案留下SUCC的局面)