Ruby,修订版B 121字节
提交是匿名函数,减去f=
。在测试程序中显示以说明用法。
f=->n{["~mK)\7","}uYwQO"][l=n%2].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m/2*257>>j&255==126-t&&t+j%2!=119&&l=m}}}
l}
puts g=f[gets.to_i]
puts
[7,6,5,
8,0,4,
1,2,3].each{|i|print g>>i&1; puts if i/3==1}
通过使中心正方形成为最低有效位而不是最高有效位,可以节省2个字节(用/2
代替,而不是%256
。)通过重组可接受的动作表来节省剩余空间。组织为自由/占用的中心正方形而不是按X的总数进行组织,可以简化测试。而且,现在数组中只有2个字符串,因此%w{string1 string2}
语法被放弃,以支持["string1","string2"]
语法。这样可以\7
包含不可打印的字符,从而可以使用更简单的编码:126-t
代替(36-t)%120
。
Ruby,修订版143字节
->n{l=r=("%b"%n).sum%8
%w{$ %5 - I+Wy Q S#}[r].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m%256*257>>j&255==(t-36)%120&&t+j%2!=43&&l=m}}}
l}
这是一个匿名函数。输入/输出格式保持打开状态,因此我准备使用9位二进制数。512位代表中心,其余位围绕它呈螺旋形旋转(1位被认为是一个角。)
可能的输入比可接受的输出要多得多,因此该算法将尝试所有移动,并找到适合可接受输出模式的移动。每个X数量可接受的输出模式都经过硬编码。
删除有关中心正方形的信息,并将剩余的8位乘以257以复制它们。然后通过右移使该图案旋转超过可接受的图案。
找到样式后,循环不会退出,因此返回的样式将是找到的最后一个可接受的样式。因此,首选模式(有偏好的模式)会出现在列表的后面。
考虑到“骑士移动”策略,图案是否旋转45度并不重要。未打高尔夫球的版本遵循骑士移动策略,因此无需区分拐角正方形和边角正方形:无论如何都要避免连续三个。
但是,我发现这并不总是最好的策略,因为存在以下技巧。如果您的对手先走并取得中锋,他应该获胜。但是在他的第二步中,他犯了一个错误,那就是让您做出一个2x2的正方形,这是您应该采取的做法,因为这可以使您迫使他连续制造三个。这是在高尔夫球版中实现的。在这种情况下,需要一点额外的代码来区分拐角处的三个X(迫使对手丢失)和沿一个边缘的3个X(立即自杀)。
取消测试程序
非高尔夫版本遵循问题中表达的逻辑。
在高尔夫球版本中,桌子进行了略微的修改,[[0],[1,17],[9],[37,7,51,85],[45],[47,119]]
以实现与表壳略有不同的行为r=3
。然后将其压缩为可打印的ASCII(需要解码(t-36)%120
)。在表条目7的情况下,需要额外的逻辑来区分拐角处的三个X和沿边的三个X:&&t+j%2!=43
f=->n{l=r=("%b"%n).sum%8 #convert input to text, take character checksum to count 1's(ASCII 49.)
#0 is ASCII 48, so %8 removes unwanted checksum bloat of 48 per char.
#l must be initialised here for scoping reasons.
[[0],[1,17],[9],[11,13,37,51,85],[45],[47,119]][r].each{|t| #according to r, find the list of acceptable perimeter bitmaps, and search for a solution.
9.times{|i|(m=n|1<<i)==n|| #OR 1<<i with input. if result == n, existing X overwritten, no good.
#ELSE new X is in vacant square, good. So..
8.times{|j|m%256*257>>j&255==t&&l=m}} #%256 to strip off middle square. *257 to duplicate bitmap.
#rightshift, see if pattern matches t. If so, write to l
}
l} #return l (the last acceptable solution found) as the answer.
#call function and pretty print output (not part of submission)
puts g=f[gets.to_i]
puts
[6,7,0,
5,8,1,
4,3,2].each{|i|print g>>i&1; puts if i<3}
测试程序输出
电脑播放时会发生这种情况。
C:\ Users \ steve> ruby tictac.rb
0
256
000
010
000
C:\ Users \ steve> ruby tictac.rb
256
384
010
010
000
C:\ Users \ steve> ruby tictac.rb
384
400
010
010
100
C:\ Users \ steve> ruby tictac.rb
400
404
010
010
101
C:\ Users \ steve> ruby tictac.rb
404
436
010
110
101
C:\ Users \ steve> ruby tictac.rb
436
444
010
110
111
游戏分析第一
这实际上是非常简单且线性的。
在开始比赛时,中间的方块将始终是第一个方块。
r = 0
... binary representation 0
.X.
...
r = 2
X.. binary representation 1001=9
.XX
...
r = 4
X.. binary representation 101101=45
.XX
XX.
在不结束游戏的情况下,只有一种方法(可以对称)具有五个X(包括棋盘上的中间方块)。中间的正方形有一个X,每个对角线一个(彼此成90度),每个水平/垂直中心线一个(彼此成90度)。由于不能占据整个边缘,所以上面是唯一的可能的安排。其他玩家必须在下一步行动中输掉。
游戏分析第二
玩法完全不同,具体取决于其他玩家是否选择中间方块。
r = 1
中间广场占领
.X. X.. binary representation 1
.X. .X.
... ...
中间广场免费
X.. .X. binary representation 10001=17
... ...
..X .X.
r = 3
中间方格,如果其他玩家在您的最后一个X附近玩
XX. .XX binary representation 1011=11
.X. XX. or mirror image 1101=13
X.. ...
但是,上述方法并非最佳选择,高尔夫版本不支持上述方法。最好的举动如下,迫使下一轮获胜:
XX. binary representation 111=7. XXX
XX. Only to be used where j is odd. .X.
... Even j would look like image to right. ...
如果其他玩家以与您最后一个X呈90度或135度的角度进行游戏,则占据中间方格(扮演骑士的步伐)。
X.X .X. binary representation 100101=37
.X. .XX
.X. X..
中间广场免费
X.X .X. XX. binary representations:
... X.X ... 1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)
r = 5
中间广场占领。由于上面在r = 4中所述的原因,有四个可能的动作,所有这些动作都失败了。仅支持一个:101111 = 47。
中间广场免费。如下所示,只有一个可能的板达到对称。其他玩家必须在下一步行动中输掉,因此无需支持r> 5。
XX. binary representation 1110111=119
X.X
.XX