移豆子游戏的必胜玩法

移豆子游戏是这样玩的,有一定数目的豆子(比方说有100粒),然后规定,两个人依次拿走一些数量的豆子数,每次拿走的数目有上限(比方说3粒),而且至少拿一粒。最后,谁拿走最后一堆豆子算谁输(当然,也可以设定最后拿走的赢)。

这其实是个数学趣题,高中的时候还搞定不了,不过现在自己想想倒也轻松搞定,看来的确是有进步啊。

假定游戏的完法是谁拿走最后一堆豆子算谁输(会分析这个,谁拿走最后一堆豆子算谁赢的必胜玩法就会容易搞定),我来分析一下这个游戏的奥秘,QUIT EASY!FOLLOW ME:
先分析个别情况,(然后推广至一般情况)假定每次可拿子数为3粒,谁拿走最后一堆豆子算谁输。
先手必胜用0表示,而先手必败用1表示(待会儿你就明白为什么要这样干了)
ATTENTION:
我们只讨先手必胜或必败的情况,因为当先手必胜时,后手必败;反之亦然
每次最多拿三粒。

1粒:你是先手吗?噢,很不幸,你必败了。                        1                       
2粒:你是先手吗?呵呵,拿一粒,对手面对一粒,你必胜,而他必败。0
3粒:有了前车之鉴,先手的你应该聪明了,对了,拿走两粒,你必    0
     胜。
4粒:看准了您呢,三粒,对手必败。                              0
5粒:唉呀呀,惨了,拿1,2,3粒时,对手得的子数为4,3,2,对    1
     手都必胜了,你必败了。
6粒:只要拿一粒,让对手只拿到5粒,对手就必败了。               0
7粒:2粒,理由同前。                                           0
8粒:3粒,理由同前。                                           0
9粒:完了,对手拿到6,7,8粒时对手都必胜,你必败了。           1
10粒:1粒,让对手拿10粒必败。                                  0
11粒:看出规律了吗,对了,取2粒。                              0
。。。

综上,归纳一下这个小游戏的必胜算法:
谁拿走最后一堆谁输的情况:当先手遇到的子数为1+k*(n+1)时(其中k为整数,n为每次可拿的最大子数),先手是必败的,其余情况时先手必胜,所以,这时游戏的双方只有一个目的,把给对手的子凑到1+k*(n+1)就Ok了。

再进一步推一下,对手必胜,对你而言,你就是必败,返之亦然。
1:1
2:对于1的结果取反,为0。
3:对上面两个结果取反,再取交集。(1&&0)=0
4:对上面三个结果取反,再取交集。(0&&1&&1)=0
5:对上面三个结果取反,再取交集。(1&&1&&1)=1必败。
。。。GOT IT?                  
                 
谁拿走最后一堆谁赢的情况:分析的方法和上面是一样的(略),小结为先手遇到子数为k*(n+1)时必败。

下面为实现这个效果的一个AI类(C++语言描述)
class AI{
  public:
   int  HighAI(int winMode,int netNum,int limitNum);
   int  LowAI(int netNum,int limitNum);
   int  AIThinking(int winMode,int netNum,int limitNum,int aiLevel);

 };
int  AI::HighAI(int winMode,int netNum,int limitNum){
 int outNum=0;
 int t=0;
 switch(winMode){//1谁拿走最后的最输,0谁拿走最后的谁赢
  case 1:
  if((t=(netNum-1)%(limitNum+1))==0){//无奈了,这可是必败的局面,只好等对手出错了。
   outNum=LowAI(netNum,limitNum);
   }
  else{//一击必杀
   outNum=t;
   }
   break;
  case 0:
  if((t=(netNum%(limitNum+1)))==0){//无奈了,这可是必败的局面,只好等对手出错了。
   outNum=LowAI(netNum,limitNum);
  }
  else{
   outNum=t;
   }
   break;
  }
 return outNum;
  }
int  AI::LowAI(int netNum,int limitNum){
 int outNum=0;
 randomize();
 do{
 outNum=random(limitNum)+1;
 }while(outNum>netNum);
 return outNum;
 }
int AI::AIThinking(int winMode,int netNum,int limitNum,int aiLevel){
 int outNum=0;
 switch(aiLevel){//富有可调性质的AILEVEL以后再做
 case 0:outNum=LowAI(netNum,limitNum);break;
 case 1:outNum=HighAI( winMode,netNum,limitNum);break;
  }
 return outNum;
  }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Pacman吃豆子游戏中的蒙特卡洛树是一种用于搜索和决策的算法。它通过模拟游戏状态的随机采样来建立一个搜索树,并基于搜索结果进行决策。 在Pacman吃豆子游戏中,每一步Pacman都需要选择一个行动,比如向上、向下、向左或向右动。为了找到最优的行动,蒙特卡洛树会基于之前的游戏状态和行动记录,以及对游戏规则的了解,构建一棵搜索树。 搜索树的根节点代表当前游戏状态,每个节点都有一个值,记录了这个节点在模拟游戏中的平均胜率和访问次数。接下来,蒙特卡洛树通过从根节点开始,逐步向下扩展搜索树,根据先前记录的游戏状态和行动记录,在游戏规则允许的情况下,随机选择一个未探索过的分支节点进行扩展,直到找到叶子节点。 当达到叶子节点后,蒙特卡洛树会利用模拟游戏状态的方式,进行随机采样,模拟游戏的进行,并记录胜利或失败的结果。根据这些结果,蒙特卡洛树会更新搜索树中每个节点的值,并进行回溯,将结果传递到根节点。 最后,在蒙特卡洛树中,Pacman选择要采取的行动时,会考虑每个可能的行动,并根据经验和胜率进行评估,选择具有最高期望的行动。 蒙特卡洛树是一个基于模拟的搜索算法,通过不断的模拟和更新搜索树,可以帮助Pacman在吃豆子游戏中做出更明智的决策,提高游戏的胜率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值