井字棋解法

题目:井字棋

两个玩家,一个打圈(O),一个打叉(X),轮流在3乘3的井字格上打自己的符号,最先以任意一行、一列或对角线连成一线则为胜。规定X先手。

一个终局棋谱(MOVES)指的是从开始下子到一方获胜或者下完9个子出现平局,从头到尾的下子情况。一方获胜后,本局即终止。不得提前认输。

格子从上到下,从左到右,依次编号1-9

MOVES的第一位表示第一子位置,第二位表示第二子位置,......如果一方获胜,MOVES的长度有可能<9。

局面(BOARD)表示棋盘上呈现的局面,也是按照从上到下,从左到右排列。用X和0填入相应的格子。减号“-” 表示空位。

这里有个棋局:


表示出来是:

MOVES=3175968,

BOARD=XOXOXOX,

WINNER=X



我觉得这个首先把先手,后手所有的排列组合列出来,然后设定胜利条件,最后过滤.

因为先后手交替落子,假设我有三个格子,落手的排列组合如下.
  1. with nums as (  
  2.     select level id from dual connect by level<=3  
  3. ),  
  4. MOVES as(  
  5.     select n1.id||n2.id||n3.id moves,  
  6.     n1.id||n3.id X,  
  7.     n2.id O   
  8.     from   
  9.     nums n1,  
  10.     nums n2,  
  11.     nums n3  
  12.     where   
  13.     (n1.id!=n2.id and n1.id!=n3.id ) and   
  14.     (n2.id!=n1.id and n2.id!=n3.id ) and   
  15.     (n3.id!=n2.id and n3.id!=n1.id)  
  16. )  
  17. select * from moves;  

结果如下:


那么井字棋所有的排列组合如下:
  1. with nums as (  
  2.     select level id from dual connect by level<=9  
  3. ),  
  4. MOVES as(  
  5.     select n1.id||n2.id||n3.id||n4.id||n5.id||n6.id||n7.id||n8.id||n9.id moves,  
  6.   n1.id||n3.id||n5.id||n7.id||n9.id X,  
  7.   n2.id||n4.id||n6.id||n8.id||n9.id O  
  8.   from   
  9.     nums n1,  
  10.     nums n2,  
  11.     nums n3,  
  12.     nums n4,  
  13.     nums n5,  
  14.     nums n6,  
  15.     nums n7,  
  16.     nums n8,  
  17.     nums n9  
  18.     where   
  19.     (n1.id!=n2.id and n1.id!=n3.id and n1.id!=n4.id and n1.id!=n5.id and n1.id!=n6.id and n1.id!=n7.id and n1.id!=n8.id and n1.id!=n9.id) and   
  20.     (n2.id!=n1.id and n2.id!=n3.id and n2.id!=n4.id and n2.id!=n5.id and n2.id!=n6.id and n2.id!=n7.id and n2.id!=n8.id and n2.id!=n9.id) and   
  21.     (n3.id!=n2.id and n3.id!=n1.id and n3.id!=n4.id and n3.id!=n5.id and n3.id!=n6.id and n3.id!=n7.id and n3.id!=n8.id and n3.id!=n9.id) and   
  22.     (n4.id!=n2.id and n4.id!=n3.id and n4.id!=n1.id and n4.id!=n5.id and n4.id!=n6.id and n4.id!=n7.id and n4.id!=n8.id and n4.id!=n9.id) and   
  23.     (n5.id!=n2.id and n5.id!=n3.id and n5.id!=n4.id and n5.id!=n1.id and n5.id!=n6.id and n5.id!=n7.id and n5.id!=n8.id and n5.id!=n9.id) and   
  24.     (n6.id!=n2.id and n6.id!=n3.id and n6.id!=n4.id and n6.id!=n5.id and n6.id!=n1.id and n6.id!=n7.id and n6.id!=n8.id and n6.id!=n9.id) and   
  25.     (n7.id!=n2.id and n7.id!=n3.id and n7.id!=n4.id and n7.id!=n5.id and n7.id!=n6.id and n7.id!=n1.id and n7.id!=n8.id and n7.id!=n9.id) and   
  26.     (n8.id!=n1.id and n8.id!=n3.id and n8.id!=n4.id and n8.id!=n5.id and n8.id!=n6.id and n8.id!=n7.id and n8.id!=n2.id and n8.id!=n9.id) and  
  27.     (n9.id!=n2.id and n9.id!=n3.id and n9.id!=n4.id and n9.id!=n5.id and n9.id!=n6.id and n9.id!=n7.id and n9.id!=n8.id and n9.id!=n1.id)    
  28. )  
  29. select * from moves;  

部分结果如下:


moves表示先后手顺序的落子顺序,X表示先手的落子,O表示后手的落子.

题目中示范图的落子顺序,在这个SQL中的结果如下
317596842 37982 15642
317596824 37984 15624

棋盘:
123
456
789
胜利条件,任何一方先包括下面所有的数字,则为胜利
横向:[123][456][789]
竖向:[147][258][369]
斜向:[159][357]
数字先后顺序不重要,只要某一方落子包括了上述数字组合,则应该认为可能胜利.
如果先后手,都满足了条件,则应该看谁先满足.

整个SQL如下:
  1. create table t1 as   
  2. with nums as (  
  3.     select level id from dual connect by level<=9  
  4. ),  
  5. MOVES as(  
  6.     select n1.id||n2.id||n3.id||n4.id||n5.id||n6.id||n7.id||n8.id||n9.id moves,  
  7.     n1.id||n3.id||n5.id||n7.id||n9.id X,  
  8.     n2.id||n4.id||n6.id||n8.id||n9.id O,   
  9.     'XOXOXOXOX' BOARD  
  10.     from   
  11.     nums n1,  
  12.     nums n2,  
  13.     nums n3,  
  14.     nums n4,  
  15.     nums n5,  
  16.     nums n6,  
  17.     nums n7,  
  18.     nums n8,  
  19.     nums n9  
  20.     where   
  21.     (n1.id!=n2.id and n1.id!=n3.id and n1.id!=n4.id and n1.id!=n5.id and n1.id!=n6.id and n1.id!=n7.id and n1.id!=n8.id and n1.id!=n9.id) and   
  22.     (n2.id!=n1.id and n2.id!=n3.id and n2.id!=n4.id and n2.id!=n5.id and n2.id!=n6.id and n2.id!=n7.id and n2.id!=n8.id and n2.id!=n9.id) and   
  23.     (n3.id!=n2.id and n3.id!=n1.id and n3.id!=n4.id and n3.id!=n5.id and n3.id!=n6.id and n3.id!=n7.id and n3.id!=n8.id and n3.id!=n9.id) and   
  24.     (n4.id!=n2.id and n4.id!=n3.id and n4.id!=n1.id and n4.id!=n5.id and n4.id!=n6.id and n4.id!=n7.id and n4.id!=n8.id and n4.id!=n9.id) and   
  25.     (n5.id!=n2.id and n5.id!=n3.id and n5.id!=n4.id and n5.id!=n1.id and n5.id!=n6.id and n5.id!=n7.id and n5.id!=n8.id and n5.id!=n9.id) and   
  26.     (n6.id!=n2.id and n6.id!=n3.id and n6.id!=n4.id and n6.id!=n5.id and n6.id!=n1.id and n6.id!=n7.id and n6.id!=n8.id and n6.id!=n9.id) and   
  27.     (n7.id!=n2.id and n7.id!=n3.id and n7.id!=n4.id and n7.id!=n5.id and n7.id!=n6.id and n7.id!=n1.id and n7.id!=n8.id and n7.id!=n9.id) and   
  28.     (n8.id!=n1.id and n8.id!=n3.id and n8.id!=n4.id and n8.id!=n5.id and n8.id!=n6.id and n8.id!=n7.id and n8.id!=n2.id and n8.id!=n9.id) and  
  29.     (n9.id!=n2.id and n9.id!=n3.id and n9.id!=n4.id and n9.id!=n5.id and n9.id!=n6.id and n9.id!=n7.id and n9.id!=n8.id and n9.id!=n1.id)    
  30. ),  
  31. v1 as (  
  32.     select m.*,  
  33.     translate(m.X,'123456789','1__4__7__') xc1,   
  34.     translate(m.X,'123456789','_2__5__8_') xc2,   
  35.     translate(m.X,'123456789','__3__6__9') xc3,   
  36.     translate(m.X,'123456789','1___5___9') xc4,   
  37.     translate(m.X,'123456789','__3_5_7__') xc5,  
  38.     translate(m.X,'123456789','123______') xc6,  
  39.     translate(m.X,'123456789','___456___') xc7,  
  40.     translate(m.X,'123456789','______789') xc8,  
  41.     translate(m.O,'123456789','1__4__7__') oc1,   
  42.     translate(m.O,'123456789','_2__5__8_') oc2,   
  43.     translate(m.O,'123456789','__3__6__9') oc3,   
  44.     translate(m.O,'123456789','1___5___9') oc4,   
  45.     translate(m.O,'123456789','__3_5_7__') oc5,  
  46.     translate(m.O,'123456789','123______') oc6,  
  47.     translate(m.O,'123456789','___456___') oc7,  
  48.     translate(m.O,'123456789','______789') oc8  
  49.     from moves m  
  50. ),  
  51. score as (  
  52.     select   
  53.     v1.*,  
  54.     least(  
  55.         decode(regexp_instr(xc1,'[1-9]',1,3) ,0,999,regexp_instr(xc1,'[1-9]',1,3)),  
  56.         decode(regexp_instr(xc2,'[1-9]',1,3) ,0,999,regexp_instr(xc2,'[1-9]',1,3)),  
  57.         decode(regexp_instr(xc3,'[1-9]',1,3) ,0,999,regexp_instr(xc3,'[1-9]',1,3)),  
  58.         decode(regexp_instr(xc4,'[1-9]',1,3) ,0,999,regexp_instr(xc4,'[1-9]',1,3)),  
  59.         decode(regexp_instr(xc5,'[1-9]',1,3) ,0,999,regexp_instr(xc5,'[1-9]',1,3)),  
  60.         decode(regexp_instr(xc6,'[1-9]',1,3) ,0,999,regexp_instr(xc6,'[1-9]',1,3)),  
  61.         decode(regexp_instr(xc7,'[1-9]',1,3) ,0,999,regexp_instr(xc7,'[1-9]',1,3)),  
  62.         decode(regexp_instr(xc8,'[1-9]',1,3) ,0,999,regexp_instr(xc8,'[1-9]',1,3))  
  63.   
  64.     ) xscore,  
  65.     least(  
  66.         decode(regexp_instr(oc1,'[1-9]',1,3) ,0,999,regexp_instr(oc1,'[1-9]',1,3)),  
  67.         decode(regexp_instr(oc2,'[1-9]',1,3) ,0,999,regexp_instr(oc2,'[1-9]',1,3)),  
  68.         decode(regexp_instr(oc3,'[1-9]',1,3) ,0,999,regexp_instr(oc3,'[1-9]',1,3)),  
  69.         decode(regexp_instr(oc4,'[1-9]',1,3) ,0,999,regexp_instr(oc4,'[1-9]',1,3)),  
  70.         decode(regexp_instr(oc5,'[1-9]',1,3) ,0,999,regexp_instr(oc5,'[1-9]',1,3)),  
  71.         decode(regexp_instr(oc6,'[1-9]',1,3) ,0,999,regexp_instr(oc6,'[1-9]',1,3)),  
  72.         decode(regexp_instr(oc7,'[1-9]',1,3) ,0,999,regexp_instr(oc7,'[1-9]',1,3)),  
  73.         decode(regexp_instr(oc8,'[1-9]',1,3) ,0,999,regexp_instr(oc8,'[1-9]',1,3))  
  74.     ) oscore  
  75.     from v1  
  76.     where   
  77.     regexp_instr(xc1,'[1-9]',1,3) !=0 or  
  78.     regexp_instr(xc2,'[1-9]',1,3) !=0 or  
  79.     regexp_instr(xc3,'[1-9]',1,3) !=0 or  
  80.     regexp_instr(xc4,'[1-9]',1,3) !=0 or  
  81.     regexp_instr(xc5,'[1-9]',1,3) !=0 or  
  82.     regexp_instr(xc6,'[1-9]',1,3) !=0 or  
  83.     regexp_instr(xc7,'[1-9]',1,3) !=0 or  
  84.     regexp_instr(xc8,'[1-9]',1,3) !=0 or  
  85.     regexp_instr(oc1,'[1-9]',1,3) !=0 or  
  86.     regexp_instr(oc2,'[1-9]',1,3) !=0 or  
  87.     regexp_instr(oc3,'[1-9]',1,3) !=0 or  
  88.     regexp_instr(oc4,'[1-9]',1,3) !=0 or  
  89.     regexp_instr(oc5,'[1-9]',1,3) !=0 or  
  90.     regexp_instr(oc6,'[1-9]',1,3) !=0 or  
  91.     regexp_instr(oc7,'[1-9]',1,3) !=0 or  
  92.     regexp_instr(oc8,'[1-9]',1,3) !=0   
  93. )  
  94. select distinct  
  95. case when xscore<=oscore then substr(score.moves,0,xscore*2-1) else substr(score.moves,0,2*oscore) end moves,  
  96. case when xscore<=oscore then substr(x,0,xscore) else substr(x,0,oscore) end x,  
  97. case when xscore<=oscore then substr(o,0,xscore-1) else substr(o,0,oscore) end o,  
  98. case when xscore<=oscore then 'X' else 'O' end winer  
  99. from score;  
  100.   
  101. select count(*) from t1;  

所有可能的组合为:232128
部分结果如下:


性能比较差,也不知道结果对不对.
moves视图 生成所有落子组合
v1视图    辅助生成胜利条件
score视图 计算先后手,最先达到胜利条件的位置
最后整理,
如果先手赢,后手落子数量少一个.
如果后手赢,先后后手落子数量相等. 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29254281/viewspace-1852817/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29254281/viewspace-1852817/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值