移豆子游戏的必胜玩法

移豆子游戏是这样玩的,有一定数目的豆子(比方说有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;
  }

你可能感兴趣的:(游戏,C++,算法,Random,Class,语言)