找回密码
 欢迎注册
楼主: 056254628

[求助] 一种策略游戏

[复制链接]
发表于 2012-4-12 12:02:37 | 显示全部楼层
规则规定归零的手关闭(既不予取,也不许入)是必要的,否则游戏不会有胜负。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-12 13:03:25 | 显示全部楼层

局面的合并与过滤

本帖最后由 hujunhua 于 2012-4-13 07:13 编辑

一个局面 M 完整的表达可用$((a,b),(c,d))$, 其中(a,b),  (c,d)都是无序对。定义$M*k:=((a*k, b*k),(c*k, d*k))$, *是四则运算符。

合并法则:M×k等价于M,当gcd(k,N)=1时。
过滤法则:若从$((1,1),(1,1))$开始博弈,那么M×k可以从全体局面集中滤掉,当gcd(k,N)>1。

1~9中任意意都可以乘以适当的k变成1,2,5之一,所以不妨让a限于1,2,5而b,c,d取1~9中适当的值。

如此一来,7#的内容可以简化为:当两人手中都有一数归零(mod10)后,就只有16种局面,而且不存在策略了。这16种局面不难划分出胜负和。红色为先胜局面(7个),黑色为先负局面(6个):{11} → {12} → {23} → {15} →{52} →{27} → {17} → {14} → {25} → {51} → {16} → {29} →{19} {10}, 判和的局面共3个,形成一个循环{1, 3} → {1, 8} → {2, 1} → {1,3}
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-12 16:16:41 | 显示全部楼层
我觉得程序不能判断胜负和的局面应该也是构成循环,因此也是属于和的局面。
这样的话大部分局面都属于和。1111也是其中的一个。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-12 21:48:45 | 显示全部楼层
我觉得程序不能判断胜负和的局面应该也是构成循环,因此也是属于和的局面。
这样的话大部分局面都属于和。1111也是其中的一个。
056254628 发表于 2012-4-12 16:16

楼主这话是否暗示有非循环和局?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-12 23:49:34 | 显示全部楼层
14# hujunhua
误会我的意思了。
我的程序是这样的。
f(a,b,c,d)的值表示胜负和。 (a<=b,c<=d)
0 表示负,1表示和,2表示胜。
x表示未知,可能是0,可能是1,也可能是2.
其中f(0,b,0,d)值,已经知道,分别是0、1、2.

对于其他的f(a,b,c,d)初始都是x
接着对所有的a、b、c、d运行以下程序:   
      (a,b,c,d)有四种变化,(a、c中有1个0,变化减少2个。)
      (a1,b1,a,b),(a2,b2,a,b),(a3,b3,a,b),(a4,b4,a,b)      我的表示法是先手的数字放后面
具体判断如下:
这四种局面的f值中:
*如果没有x,那么f(a,b,c,d)=2-min(f(a1,b1,a,b),f(a2,b2,a,b),f(a3,b3,a,b),f(a4,b4,a,b))
*如果有x,那么只要有一个0,f(a,b,c,d)=2
*有x,没有0,那么  f(a,b,c,d)=x (即f值没有变化)
-------------------------------------------------------------------------
这样,对所有的a、b、c、d每循环上述程序一次,f值等于x的局面个数就会减少。
一直到f值等于x的局面个数不变为止。
按照我的设想,所有的局面最后都会归结于(0,b,0,d)局面,f值等于x的局面个数最后归0,这样所有的局面都有最终的结果,或胜或负或和。
但实际上不是如此,f值等于x的局面个数最后稳定在2000以上。
所以我才说大多数局面无法得到确切的结果。
想想原因可能是这样的:f(a,b,c,d)的值取决于其他局面的值,其他局面的值取决于......,最后又取决于前面出现过的局面的值,这样就形成了循环,双方为了不形成必胜局面给对方,谁都不愿意从循环局面中离开,所以这些局面都是和局。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-13 00:13:27 | 显示全部楼层
对于f(a,b,c,d)=2-min(f(a1,b1,a,b),f(a2,b2,a,b),f(a3,b3,a,b),f(a4,b4,a,b))
f(a1,b1,a,b),f(a2,b2,a,b),f(a3,b3,a,b),f(a4,b4,a,b)中有x,没0的情况:
可以简化,把所有值为2的删除,最后剩下的都是值为1,或x。
选择值为1的变化,就保证和局,选择为x的变化,比如f(a1,b1,a,b)=x,
那么一直选择值为x的变化,如(a,b,c,d) -->(a1,b1,a,b) -->(a2,b2,a1,b1)-->(a3,b3,a2,b2)-->......
最后陷入循环之中(这个循序是费脑力的,必须时刻保持正确的选择,否则会输),或者在中间的某个局面选择值为1的变化,最后归于双方只有一个数字的和局循环之中(这个循环不需用脑,没得选择)。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-13 07:38:12 | 显示全部楼层
算法很妙,但是初值很重要。仅限于f(0,b,0,d)不够。f(a,b,0,d)=2,当a+d=0(mod10)或者b+d=0(mod10)时,它下一步终止于f(0,0,a,b)而不是f(0,b,o,d)型初值。

这个算法很容易实现递归程序,但递归层次会不会太深,尤其是对局面数不作合并与过滤的情况下。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-13 07:49:17 | 显示全部楼层
  1. // sf.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"
  4. #include <map>
  5. #include <vector>
  6. #include <list>
  7. #include <algorithm>
  8. using namespace std;

  9. #define MOD 10
  10. unsigned char mullist[3]={3,7,9};
  11. #define MC (sizeof(mullist)/sizeof(mullist[0]))
  12. //we must make sure a<=b and c<=d
  13. #define MAKE_STATE(a,b,c,d) ((((unsigned)(unsigned char)a)<<24)|(((unsigned)(unsigned char)b)<<16)|(((unsigned)(unsigned char)c)<<8)|(((unsigned)(unsigned char)d)))
  14. #define GET_A(x) ((unsigned char)(((unsigned)(x))>>24))
  15. #define GET_B(x) ((unsigned char)(((unsigned)(x))>>16))
  16. #define GET_C(x) ((unsigned char)(((unsigned)(x))>>8))
  17. #define GET_D(x) ((unsigned char)(((unsigned)(x))))

  18. unsigned int make_state(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
  19. {
  20.         unsigned char t;
  21.         if(a>b){t=b;b=a;a=t;}
  22.         if(c>d){t=d;d=c;c=t;}
  23.         return MAKE_STATE(a,b,c,d);
  24. }
  25. typedef map<unsigned int, int> IdMap;
  26. IdMap myIdMap;
  27. vector<unsigned int> idToState;
  28. vector<unsigned int> result;
  29. #define UNKNOWN   0
  30. #define FIRSTWIN  1
  31. #define FIRSTLOST 2
  32. struct Edges{
  33.         int e[4];
  34. };

  35. vector<Edges> prev,next;
  36. list<int> losers;
  37. vector<int> winers;
  38. int lc,wc;
  39. int getStateId(unsigned int x)
  40. {
  41.         IdMap::iterator it;
  42.         it=myIdMap.find(x);
  43.         if(it==myIdMap.end())return -1;
  44.         return it->second;
  45. }
  46. void init()
  47. {
  48.         unsigned char a,b,c,d;
  49.         int id=0;
  50.         int i;
  51.         myIdMap.clear();
  52.         for(a=0;a<MOD;a++)for(b=a;b<MOD;b++)for(c=0;c<MOD;c++)for(d=c;d<MOD;d++){
  53.                 unsigned int state = make_state(a,b,c,d);
  54.                 int i;
  55.                 for(i=0;i<MC;i++){
  56.                         IdMap::iterator iit=myIdMap.find(make_state((a*mullist[i])%MOD,(b*mullist[i])%MOD,(c*mullist[i])%MOD, (d*mullist[i])%MOD));
  57.                         if(iit!=myIdMap.end()){
  58.                                 myIdMap.insert(make_pair(state,iit->second));
  59.                                 break;
  60.                         }
  61.                 }
  62.                 if(i==MC){
  63.                         myIdMap.insert(make_pair(state,id));
  64.                         idToState.push_back(state);
  65.                         id++;
  66.                 }else{
  67.                         continue;
  68.                 }
  69.         }
  70.         for(i=0;i<id;i++)result.push_back(UNKNOWN);
  71.         for(id=0;id<idToState.size();++id){
  72.                 unsigned int state=idToState[id];
  73.                 unsigned char a,b,c,d;
  74.                 a=GET_A(state);
  75.                 b=GET_B(state);
  76.                 c=GET_C(state);
  77.                 d=GET_D(state);
  78.                 if(c==0&&d==0){
  79.                         Edges e;
  80.                         e.e[0]=e.e[1]=e.e[2]=e.e[3]=-1;
  81.                         next.push_back(e);
  82.                         continue;///terminate states, no out edges
  83.                 }
  84.                 int cc=0;
  85.                 int j;
  86.                 Edges e;
  87.                 if(c!=0){
  88.                         if(a!=0)
  89.                         e.e[cc++]=myIdMap.find(make_state(c,d,(a+c)%MOD,b))->second;
  90.                         if(b!=0)
  91.                         e.e[cc++]=myIdMap.find(make_state(c,d,a,(b+c)%MOD))->second;
  92.                 }
  93.                 if(d!=0){
  94.                         if(a!=0)
  95.                         e.e[cc++]=myIdMap.find(make_state(c,d,(a+d)%MOD,b))->second;
  96.                         if(b!=0)
  97.                         e.e[cc++]=myIdMap.find(make_state(c,d,a,(b+d)%MOD))->second;
  98.                 }
  99.                 sort(&e.e[0],&e.e[cc]);

  100.                 for(i=1,j=1;i<cc;i++){
  101.                         if(e.e[i]==e.e[i-1])continue;
  102.                         e.e[j]=e.e[i];
  103.                         j++;
  104.                 }
  105.                 cc=j;
  106.                 for(i=cc;i<4;i++){
  107.                         e.e[i]=-1;///mark invalid edges
  108.                 }
  109.                 next.push_back(e);
  110.         }
  111.         for(id=0;id<idToState.size();++id){
  112.                 unsigned int state=idToState[id];
  113.                 unsigned char a,b,c,d;
  114.                 a=GET_A(state);
  115.                 b=GET_B(state);
  116.                 c=GET_C(state);
  117.                 d=GET_D(state);
  118.                 if(a==0&&b==0){
  119.                         Edges e;
  120.                         e.e[0]=e.e[1]=e.e[2]=e.e[3]=-1;
  121.                         prev.push_back(e);
  122.                         continue;
  123.                 }
  124.                 int cc=0;
  125.                 int j;
  126.                 Edges e;
  127.                 if(a!=0){
  128.                         if((c-a)%MOD!=0)
  129.                         e.e[cc++]=myIdMap.find(make_state((c-a+MOD)%MOD,d,a,b))->second;
  130.                         if((d-a)%MOD!=0)
  131.                         e.e[cc++]=myIdMap.find(make_state(c,(d-a+MOD)%MOD,a,b))->second;
  132.                 }
  133.                 if(b!=0){
  134.                         if((c-b)%MOD!=0)
  135.                         e.e[cc++]=myIdMap.find(make_state((c-b+MOD)%MOD,d,a,b))->second;
  136.                         if((d-b)%MOD!=0)
  137.                         e.e[cc++]=myIdMap.find(make_state(c,(d-b+MOD)%MOD,a,b))->second;
  138.                 }
  139.                 sort(&e.e[0],&e.e[cc]);

  140.                 for(i=1,j=1;i<cc;i++){
  141.                         if(e.e[i]==e.e[i-1])continue;
  142.                         e.e[j]=e.e[i];
  143.                         j++;
  144.                 }
  145.                 cc=j;
  146.                 for(i=cc;i<4;i++){
  147.                         e.e[i]=-1;///mark invalid edges
  148.                 }
  149.                 prev.push_back(e);
  150.         }
  151.         for(id=0;id<idToState.size();++id){
  152.                 unsigned int state=idToState[id];
  153.                 unsigned char a,b,c,d;
  154.                 a=GET_A(state);
  155.                 b=GET_B(state);
  156.                 c=GET_C(state);
  157.                 d=GET_D(state);
  158.                 if(c==0&&d==0&&(a!=0||b!=0)){
  159.                         result[id]=FIRSTLOST;
  160.                         losers.push_back(id);
  161.                         lc++;
  162.                 }
  163.                 if(a==0&&b==0&&(c!=0||d!=0)){
  164.                         result[id]=FIRSTWIN;
  165.                         wc++;
  166.                 }
  167.         }
  168. }

  169. void dumpstate(int i){
  170.         unsigned int state=idToState[i];
  171.         unsigned char a,b,c,d;
  172. //        if(result[i]!=FIRSTLOST)return;
  173.         a=GET_A(state);
  174.         b=GET_B(state);
  175.         c=GET_C(state);
  176.         d=GET_D(state);
  177.         printf("state[%d:%d;%d:%d] is ",a,b,c,d);
  178.         if(result[i]==FIRSTWIN){
  179.                 printf("first user win\n");
  180.         }else if(result[i]==FIRSTLOST){
  181.                 printf("first user lost\n");
  182.         }else{
  183.                 printf("tie \n");
  184.         }
  185. }

  186. int _tmain(int argc, _TCHAR* argv[])
  187. {
  188.         int i;
  189.         init();
  190. start:
  191.         while(losers.size()>0){
  192.                 int id = losers.front();
  193.                 losers.pop_front();
  194.                 for(i=0;i<4;i++){
  195.                         int pid=prev[id].e[i];
  196.                         if(pid<0)break;
  197.                         if(result[pid]==UNKNOWN){
  198.                                 result[pid]=FIRSTWIN;
  199.                                 wc++;
  200.                                 winers.push_back(pid);
  201.                         }else if(result[pid]!=FIRSTWIN){
  202.                                 fprintf(stderr,"Invalid 1\n");
  203.                                 return -1;
  204.                         }
  205.                 }
  206.         }
  207.         int c=winers.size();
  208.         for(i=0;i<c;i++){
  209.                 int id = winers[i];
  210.                 int j;
  211.                 for(j=0;j<4;j++){
  212.                         int pid=prev[id].e[j];
  213.                         if(pid<0)break;
  214.                         if(result[pid]==UNKNOWN){
  215.                                 int k;
  216.                                 for(k=0;k<4;k++){
  217.                                         if(next[pid].e[k]<0)break;
  218.                                         if(result[next[pid].e[k]]!=FIRSTWIN)break;
  219.                                 }
  220.                                 if(k==4||next[pid].e[k]<0){//all next are first_win
  221.                                         result[pid]=FIRSTLOST;
  222.                                         lc++;
  223.                                         losers.push_back(pid);
  224.                                 }
  225.                         }
  226.                 }
  227.         }
  228.         if(losers.size()>0)goto start;
  229.         c=result.size();
  230.         printf("win count=%d, lost count=%d, undertermined=%d\n",wc,lc,c-wc-lc);
  231.         for(i=0;i<result.size();i++){
  232.                 if(result[i]!=UNKNOWN){
  233.                         dumpstate(i);
  234.                 }
  235.         }
  236.         return 0;
  237. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-13 07:50:45 | 显示全部楼层
程序使用了hujunhua的等价类合并方法,所以一个状态可能代表两个或四个等价状态
win count=117, lost count=49, undertermined=607
state[0:0;0:1] is first user win
state[0:0;0:2] is first user win
state[0:0;0:5] is first user win
state[0:0;1:1] is first user win
state[0:0;1:2] is first user win
state[0:0;1:3] is first user win
state[0:0;1:4] is first user win
state[0:0;1:5] is first user win
state[0:0;1:6] is first user win
state[0:0;1:8] is first user win
state[0:0;1:9] is first user win
state[0:0;2:2] is first user win
state[0:0;2:4] is first user win
state[0:0;2:5] is first user win
state[0:0;2:8] is first user win
state[0:0;5:5] is first user win
state[0:1;0:0] is first user lost
state[0:1;0:1] is first user win
state[0:1;0:2] is first user lost
state[0:1;0:4] is first user lost
state[0:1;0:5] is first user lost
state[0:1;0:6] is first user win
state[0:1;0:7] is first user win
state[0:1;0:9] is first user win
state[0:1;1:7] is first user win
state[0:1;1:9] is first user win
state[0:1;2:2] is first user win
state[0:1;2:7] is first user win
state[0:1;2:9] is first user win
state[0:1;3:3] is first user win
state[0:1;3:9] is first user win
state[0:1;4:5] is first user win
state[0:1;4:6] is first user win
state[0:1;4:9] is first user win
state[0:1;5:9] is first user win
state[0:1;6:6] is first user win
state[0:1;6:9] is first user win
state[0:1;7:7] is first user lost
state[0:1;7:9] is first user win
state[0:1;8:9] is first user win
state[0:1;9:9] is first user win
state[0:2;0:0] is first user lost
state[0:2;0:2] is first user win
state[0:2;0:3] is first user win
state[0:2;0:4] is first user lost
state[0:2;0:5] is first user win
state[0:2;0:7] is first user lost
state[0:2;0:8] is first user win
state[0:2;0:9] is first user lost
state[0:2;1:7] is first user win
state[0:2;1:8] is first user win
state[0:2;1:9] is first user win
state[0:2;2:2] is first user win
state[0:2;2:4] is first user win
state[0:2;2:8] is first user win
state[0:2;2:9] is first user win
state[0:2;3:5] is first user lost
state[0:2;3:7] is first user win
state[0:2;3:8] is first user win
state[0:2;4:4] is first user win
state[0:2;4:5] is first user win
state[0:2;4:6] is first user win
state[0:2;4:8] is first user win
state[0:2;4:9] is first user win
state[0:2;5:8] is first user win
state[0:2;6:6] is first user win
state[0:2;6:8] is first user win
state[0:2;6:9] is first user win
state[0:2;7:8] is first user win
state[0:2;7:9] is first user win
state[0:2;8:8] is first user win
state[0:2;8:9] is first user win
state[0:2;9:9] is first user win
state[0:5;0:0] is first user lost
state[0:5;0:1] is first user lost
state[0:5;0:2] is first user win
state[0:5;0:5] is first user win
state[0:5;1:1] is first user win
state[0:5;1:3] is first user win
state[0:5;1:4] is first user win
state[0:5;1:5] is first user win
state[0:5;1:8] is first user win
state[0:5;2:5] is first user win
state[0:5;5:5] is first user win
state[1:1;0:0] is first user lost
state[1:1;0:4] is first user win
state[1:1;0:6] is first user lost
state[1:1;0:8] is first user lost
state[1:1;0:9] is first user lost
state[1:1;1:9] is first user win
state[1:1;6:9] is first user win
state[1:1;7:9] is first user win
state[1:1;9:9] is first user win
state[1:2;0:0] is first user lost
state[1:2;0:8] is first user win
state[1:2;7:9] is first user win
state[1:2;8:8] is first user win
state[1:2;9:9] is first user win
state[1:3;0:0] is first user lost
state[1:3;0:6] is first user lost
state[1:3;0:8] is first user lost
state[1:3;0:9] is first user lost
state[1:3;7:9] is first user win
state[1:4;0:0] is first user lost
state[1:4;0:6] is first user win
state[1:4;0:9] is first user lost
state[1:4;2:9] is first user win
state[1:4;3:9] is first user win
state[1:4;6:9] is first user win
state[1:4;7:9] is first user win
state[1:4;9:9] is first user win
state[1:5;0:0] is first user lost
state[1:5;0:2] is first user win
state[1:5;0:5] is first user win
state[1:5;0:9] is first user win
state[1:5;1:9] is first user win
state[1:6;0:0] is first user lost
state[1:6;0:4] is first user lost
state[1:6;0:9] is first user win
state[1:6;4:4] is first user win
state[1:6;4:9] is first user win
state[1:8;0:0] is first user lost
state[1:8;0:3] is first user win
state[1:8;0:6] is first user lost
state[1:8;0:9] is first user win
state[1:8;3:9] is first user win
state[1:9;0:0] is first user lost
state[1:9;0:1] is first user lost
state[1:9;0:5] is first user lost
state[1:9;1:9] is first user win
state[2:2;0:0] is first user lost
state[2:2;0:2] is first user lost
state[2:2;0:3] is first user lost
state[2:2;0:4] is first user lost
state[2:2;0:6] is first user lost
state[2:2;0:8] is first user lost
state[2:2;0:9] is first user lost
state[2:2;2:8] is first user win
state[2:2;3:8] is first user win
state[2:2;5:8] is first user win
state[2:2;8:8] is first user win
state[2:4;0:0] is first user lost
state[2:4;0:4] is first user lost
state[2:4;0:6] is first user win
state[2:4;2:6] is first user win
state[2:4;2:8] is first user win
state[2:4;4:6] is first user win
state[2:4;6:6] is first user win
state[2:4;6:7] is first user win
state[2:4;8:8] is first user win
state[2:5;0:0] is first user lost
state[2:5;0:5] is first user lost
state[2:5;0:8] is first user lost
state[2:5;2:8] is first user win
state[2:5;5:8] is first user win
state[2:8;0:0] is first user lost
state[2:8;0:2] is first user lost
state[2:8;0:4] is first user lost
state[2:8;0:5] is first user lost
state[2:8;2:2] is first user win
state[2:8;2:6] is first user win
state[2:8;2:8] is first user win
state[5:5;0:0] is first user lost
state[5:5;0:5] is first user lost
state[5:5;2:5] is first user win
state[5:5;5:5] is first user win
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-13 11:09:46 | 显示全部楼层

标题

17# hujunhua
(0,0,a,b)局面的初值我没有设置,直接在程序里判断,能变化成该局面的f值为2.,当然,把它们设成初值为0也行。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-5-4 10:45 , Processed in 0.065593 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表