Code Golf:Tic Tac Toe

Ais*_*ina 42 code-golf tic-tac-toe rosetta-stone

按字符数发布您的最短代码,以检查玩家是否赢了,如果是,那么.

假设你在变量b(board)中有一个整数数组,它包含Tic Tac Toe板,以及玩家的移动:

  • 0 =没有设置
  • 1 =玩家1(X)
  • 2 =玩家2(O)

所以,鉴于阵列b = [ 1, 2, 1, 0, 1, 2, 1, 0, 2 ]将代表董事会

X|O|X
-+-+-
 |X|O
-+-+-
X| |O
Run Code Online (Sandbox Code Playgroud)

对于这种情况,您的代码应该输出1以指示玩家1赢了.如果没有人赢了你可以输出0false.

我自己的(Ruby)解决方案即将推出.

编辑:对不起,忘了将其标记为社区维基.您可以假设输入格式正确,不必进行错误检查.


更新:请以函数的形式发布您的解决方案.大多数人已经这样做了,但有些人没有,这不完全公平.电路板作为参数提供给您的功能.结果应该由函数返回.该函数可以具有您选择的名称.

esw*_*ald 37

疯狂的Python解决方案 - 79个字符

max([b[x] for x in range(9) for y in range(x) for z in range(y)
    if x+y+z==12 and b[x]==b[y]==b[z]] + [0])
Run Code Online (Sandbox Code Playgroud)

但是,这假设b中的董事会职位的顺序不同:

 5 | 0 | 7
---+---+---
 6 | 4 | 2
---+---+---
 1 | 8 | 3
Run Code Online (Sandbox Code Playgroud)

也就是说,b[5]代表左上角,依此类推.

为了尽量减少上述情况

r=range
max([b[x]for x in r(9)for y in r(x)for z in r(y)if x+y+z==12and b[x]==b[y]==b[z]]+[0])
Run Code Online (Sandbox Code Playgroud)

93个字符和换行符.

更新:使用按位AND技巧,最多79个字符和换行符:

r=range
max([b[x]&b[y]&b[z]for x in r(9)for y in r(x)for z in r(y)if x+y+z==12])
Run Code Online (Sandbox Code Playgroud)

  • 非常聪明......但不符合要求;) (17认同)
  • 放置数字是为了让所有工作(有趣)总和等于12.所以他做了一个循环,当总和等于12时,比较三个案例的内容 (5认同)

ken*_*ytm 22

C,77(83)个字符

这是dmckee解决方案的变体,除了Compact Coding中的每对数字现在是ASCII字符的基数为9的数字.

77 -char版本,不会对MSVC工作:

// "J)9\t8\r=,\0" == 82,45,63,10,62,14,67,48,00 in base 9.
char*k="J)9 8\r=,",c;f(int*b){return(c=*k++)?b[c/9]&b[c%9]&b[*k--%9]|f(b):0;}
Run Code Online (Sandbox Code Playgroud)

这个83 -char版本应该适用于每个C编译器:

f(int*b){char*k="J)9    8\r=,",s=0,c;while(c=*k++)s|=b[c%9]&b[c/9]&b[*k%9];return s;}
Run Code Online (Sandbox Code Playgroud)

(请注意,9和8之间的空格应该是一个选项卡.StackOverflow将所有选项卡转换为空格.)


测试用例:

#include <stdio.h>  
void check(int* b) {
    int h0 = b[0]&b[1]&b[2];
    int h1 = b[3]&b[4]&b[5];
    int h2 = b[6]&b[7]&b[8];
    int h3 = b[0]&b[3]&b[6];
    int h4 = b[1]&b[4]&b[7];
    int h5 = b[2]&b[5]&b[8];
    int h6 = b[0]&b[4]&b[8];
    int h7 = b[2]&b[4]&b[6];
    int res = h0|h1|h2|h3|h4|h5|h6|h7;
    int value = f(b);
    if (value != res)
        printf("Assuming f({%d,%d,%d, %d,%d,%d, %d,%d,%d}) == %d; got %d instead.\n", 
            b[0],b[1],b[2], b[3],b[4],b[5], b[6],b[7],b[8], res, value);
}
#define MAKEFOR(i) for(b[(i)]=0;b[(i)]<=2;++b[(i)])

int main() {
    int b[9];

    MAKEFOR(0)
    MAKEFOR(1)
    MAKEFOR(2)
    MAKEFOR(3)
    MAKEFOR(4)
    MAKEFOR(5)
    MAKEFOR(6)
    MAKEFOR(7)
    MAKEFOR(8)
        check(b);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @Alex为什么要浪费一个角色? (3认同)

mob*_*mob 12

Python 80(69)char

不是最短的Python解决方案,但我喜欢它如何将"DICE"引入到tic-tac-toe游戏中:

W=lambda b:max([b[c/5-9]&b[c/5+c%5-9]&b[c/5-c%5-9]for c in map(ord,"DICE>3BQ")])
Run Code Online (Sandbox Code Playgroud)

简单表达的69个字符:

max([b[c/5-9]&b[c/5+c%5-9]&b[c/5-c%5-9]for c in map(ord,"DICE>3BQ")])
Run Code Online (Sandbox Code Playgroud)


mer*_*tor 10

Perl,87 85 人物

当然,使用正则表达式返回0,1或2的函数(换行符仅用于避免滚动条):

sub V{$"='';$x='(1|2)';"@_"=~
/^(...)*$x\2\2|^..$x.\3.\3|$x..\4..\4|$x...\5...\5/?$^N:0}
Run Code Online (Sandbox Code Playgroud)

V(@b)例如,它可以被称为.

  • 读完之后,我的头骨开裂了,光束在裂缝中闪耀. (5认同)

小智 10

J,50个字符

w=:3 : '{.>:I.+./"1*./"1]1 2=/y{~2 4 6,0 4 8,i,|:i=.i.3 3'
Run Code Online (Sandbox Code Playgroud)


Sap*_*pph 9

我不喜欢重复自己(水平/垂直和对角线),但我认为这是一个公平的开始.

C#w/LINQ:

public static int GetVictor(int[] b)
{
    var r = Enumerable.Range(0, 3);
    return r.Select(i => r.Aggregate(3, (s, j) => s & b[i * 3 + j])).Concat(
        r.Select(i => r.Aggregate(3, (s, j) => s & b[j * 3 + i]))).Aggregate(
        r.Aggregate(3, (s, i) => s & b[i * 3 + i]) | r.Aggregate(3, (s, i) => s & b[i * 3 + (2 - i)]),
        (s, i) => s | i);
}
Run Code Online (Sandbox Code Playgroud)

策略:AND将行/列/对角线的每个元素与其他元素(以3作为种子)OR相加,以获得该子集的胜利者,并将它们全部放在一起.


Jor*_*ing 8

Ruby,115个字符

哎呀:不知怎的,我误解了很多.这实际上是115个字符,而不是79个字符.

def t(b)[1,2].find{|p|[448,56,7,292,146,73,273,84].any?{|k|(k^b.inject(0){|m,i|m*2+((i==p)?1:0)})&k==0}}||false end

# Usage:
b = [ 1, 2, 1,
      0, 1, 2,
      1, 0, 2 ]
t(b) # => 1

b = [ 1, 1, 0,
      2, 2, 2,
      0, 2, 1 ]
t(b) # => 2

b = [ 0, 0, 1,
      2, 2, 0,
      0, 1, 1 ]
t(b) # => false
Run Code Online (Sandbox Code Playgroud)

和扩展代码,用于教育目的:

def tic(board)
  # all the winning board positions for a player as bitmasks
  wins = [ 0b111_000_000,  # 448
           0b000_111_000,  #  56
           0b000_000_111,  #   7
           0b100_100_100,  # 292
           0b010_010_010,  # 146
           0b001_001_001,  #  73
           0b100_010_001,  # 273
           0b001_010_100 ] #  84

  [1, 2].find do |player| # find the player who's won
    # for the winning player, one of the win positions will be true for :
    wins.any? do |win|
      # make a bitmask from the current player's moves
      moves = board.inject(0) { |acc, square|
        # shift it to the left and add one if this square matches the player number
        (acc * 2) + ((square == player) ? 1 : 0)
      }
      # some logic evaluates to 0 if the moves match the win mask
      (win ^ moves) & win == 0
    end
  end || false # return false if the find returns nil (no winner)
end
Run Code Online (Sandbox Code Playgroud)

我敢肯定这可以缩短,特别是大阵列以及可能用于获得玩家动作的位掩码的代码 - 这三元素让我感到烦恼 - 但我认为这对现在来说非常好.