42

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

假设您在变量(棋盘)中有一个整数数组b,其中包含井字棋盘和玩家的移动,其中:

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

所以,给定数组b = [ 1, 2, 1, 0, 1, 2, 1, 0, 2 ]将代表棋盘

X|O|X
-+-+-
 |X|O
-+-+-
X| |O

对于这种情况,您的代码应输出1以指示玩家 1 已获胜。如果没有人获胜,您可以输出0false

我自己的(Ruby)解决方案将很快推出。

编辑:抱歉,忘记将其标记为社区 wiki。您可以假设输入格式正确,不必进行错误检查。


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

4

35 回答 35

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])

但是,这假设 b 中棋盘位置的顺序不同:

 5 | 0 | 7
---+---+---
 6 | 4 | 2
---+---+---
 1 | 8 | 3

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])

93 个字符和一个换行符。

更新:使用按位与技巧减少到 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])
于 2010-02-11T16:44:54.877 回答
22

C, 77 (83) 个字符

这是dmckee解决方案的一个变体,除了 Compact Coding 中的每一对数字现在都是 ASCII 字符的 base-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;}

这个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;}

(注意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;
}
于 2010-02-11T19:29:04.420 回答
12

Python 80 (69) 字符

不是最短的 Python 解决方案,但我喜欢它如何将“DICE”引入井字游戏:

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")])

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")])
于 2010-02-12T16:29:37.457 回答
10

珀尔,8785人物

一个使用正则表达式返回 0、1 或 2 的函数,当然(换行符只是为了避免滚动条):

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

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

于 2010-02-12T00:45:55.653 回答
10

J,50 个字符

w=:3 : '{.>:I.+./"1*./"1]1 2=/y{~2 4 6,0 4 8,i,|:i=.i.3 3'
于 2010-02-15T10:08:26.853 回答
9

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

带有 LINQ 的 C#:

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);
}

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

于 2010-02-11T17:07:45.343 回答
8

红宝石,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

以及用于教育目的的扩展代码:

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

我确信这可以缩短,尤其是大数组,可能还有用于获取玩家动作位掩码的代码——三元组让我很烦——但我认为现在这很好。

于 2010-02-11T22:25:11.537 回答
4

Octave/Matlab,97 个字符,包括空格和换行符。如果没有获胜者,则输出 0,如果玩家 1 获胜,则输出 1,如果玩家 2 获胜,则输出 2,如果两个玩家都“获胜”,则输出 2.0801:

function r=d(b)
a=reshape(b,3,3)
s=prod([diag(a) diag(fliplr(a)) a a'])
r=sum(s(s==1|s==8))^(1/3)

如果我们更改规范并从一开始就将 b 作为 3x3 矩阵传递,我们可以删除 reshape 行,使其减少到 80 个字符。

于 2010-02-12T23:32:08.930 回答
4

Perl,76 个字符

sub W{$n=$u=0;map{$n++;$u|=$_[$_-$n]&$_[$_]&$_[$_+$n]for/./g}147,4,345,4;$u}

横向取胜的三种方式:

0,1,2   ==>   1-1, 1, 1+1
3,4,5   ==>   4-1, 4, 4+1
6,7,8   ==>   7-1, 7, 7+1

从左下角到右上角对角线获胜的一种方法:

2,4,6   ==>   4-2, 4, 4+2

垂直取胜的三种方式:

0,3,6   ==>   3-3, 3, 3+3
1,4,7   ==>   4-3, 4, 4+3
2,5,8   ==>   5-3, 5, 5+3

从左上角到右下角对角线获胜的一种方法:

0,4,8   ==>   4-4, 4, 4+4

阅读中间的列以获得神奇的数字。

于 2010-02-12T16:36:29.267 回答
3

因为正确播放时没有人在tictactoe中获胜我认为这是最短的代码

echo 0; 

7 个字符

更新: bash 的一个更好的条目是:

86 个字符或 81 个字符,不包括函数定义 (win())。

win()for q in 1 28 55 3 12 21 4 20;{ [[ 3*w -eq B[f=q/8]+B[g=q%8]+B[g+g-f] ]]&&break;}

但是,这是来自 bash 井字棋程序的代码,所以它不太符合规范。

# player is passed in caller's w variable. I use O=0 and X=2 and empty=8 or 9
# if a winner is found, last result is true (and loop halts) else false
# since biggest test position is 7 I'll use base 8. could use 9 as well but 10 adds 2 characters to code length
# test cases are integers made from first 2 positions of each row
# eg. first row (0 1 2) is 0*8+1 = 1
# eg. diagonal (2 4 6) is 2*8+4 = 20
# to convert test cases to board positions use X/8, X%8, and X%8+(X%8-X/8)
# for each test case, test that sum of each tuplet is 3*player value
于 2010-02-11T21:14:09.063 回答
2

红宝石,85 个字符

def X(b)
u=0
[2,6,7,8,9,13,21,-9].each do|c|u|=b[n=c/5+3]&b[n+c%5]&b[n-c%5]end
u
end

如果输入让两个玩家都赢了,例如

     X | ○ | X
    ---+---+---
     X | ○ | ○
    ---+---+---
     X | ○ | X

那么输出是3。

于 2010-02-12T16:25:42.037 回答
2

(铁)python,75个字符

完整功能 75 个字符

T=lambda a:max(a[b/6]&a[b/6+b%6]&a[b/6+b%6*2]for b in[1,3,4,9,14,15,19,37])

如果您像其他人所做的那样省略函数定义,则为 66 个字符

r=max(a[b/6]&a[b/6+b%6]&a[b/6+b%6*2]for b in[1,3,4,9,14,15,19,37])

8 个不同的方向由起始值 + 增量器表示,压缩成一个数字,可以使用除法和模数提取。例如 2,5,8 = 2*6 + 3 = 15。

使用 & 运算符检查一行是否包含三个相等的值。(如果它们不相等,则结果为零)。max 用于寻找可能的获胜者。

于 2010-02-12T13:19:42.987 回答
2

C,99 个字符

不是赢家,但也许还有改进的余地。以前从来没有这样做过。原始概念,初稿。

#define l w|=*b&b[s]&b[2*s];b+=3/s;s
f(int*b){int s=4,w=0;l=3;l;l;l=2;--b;l=1;b-=3;l;l;return l;}

感谢 KennyTM 提供的一些想法和测试工具。

“开发版”:

#define l w|=*b&b[s]&b[2*s];b+=3/s;s // check one possible win
f( int *b ) {
        int s=4,w=0; // s = stride, w = winner
        l=3;     // check stride 4 and set to 3
        l;l;l=2; // check stride 3, set to 2
        --b;l=1; // check stride 2, set to 1
        b-=3;l;l; return l; // check stride 1
}
于 2010-02-13T02:51:29.557 回答
2

Haskell,假设上面的幻方。77 个字符

77 不包括进口和定义 b。

import Data.Bits
import Data.Array

b = listArray (0,8) [2,1,0,1,1,1,2,2,0]
w b = maximum[b!x.&.b!y.&.b!z|x<-[0..8],y<-[x+1..8],z<-[12-x-y],z<8,z>=0,z/=y]

或 82 假设正常排序:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.Bits
import Data.Array

b = listArray (0,8) [1,2,1,0,1,2,1,0,2]
w b = maximum[b!x.&.b!y.&.b!z|x<-[0..8],d<-[1..4],y<-[x+d],z<-[y+d],d/=2||x==2,z<9]
于 2010-02-11T22:01:47.653 回答
1

JavaScript - 下面的函数“w”是 114 个字符

<html>   
<body>
<script type="text/javascript">

var t = [0,0,2,0,2,0,2,0,0];

function w(b){
    i = '012345678036147258048642';
    for (l=0;l<=21;l+=3){
        v = b[i[l]];
        if (v == b[i[l+1]]) if (v == b[i[l+2]]) return v;   
    }
}

alert(w(t));

</script>
</body>
</html>
于 2010-02-12T16:29:38.923 回答
1

J, 97 characters.

1+1 i.~,+./"2>>(0 4 8,2 4 6,(],|:)3 3$i.9)&(e.~)&.>&.>(]<@:#"1~[:#:[:i.2^#)&.>(I.@(1&=);I.@(2&=))

I was planning to post an explanation of how this works, but that was yesterday and now I can't read this code.

The idea is we create a list of all possible winning triples (048,246,012,345,678,036,147,258), then make the powerset of the squares each player has and then intersect the two lists. If there's a match, that's the winner.

于 2010-04-15T18:57:23.007 回答
1

Visual Basic 275 254 个(松散类型)字符

 Function W(ByVal b())

    Dim r

    For p = 1 To 2

            If b(0) = b(1) = b(2) = p Then r = p
            If b(3) = b(4) = b(5) = p Then r = p
            If b(6) = b(7) = b(8) = p Then r = p
            If b(0) = b(3) = b(6) = p Then r = p
            If b(1) = b(4) = b(7) = p Then r = p
            If b(2) = b(5) = b(8) = p Then r = p
            If b(0) = b(4) = b(8) = p Then r = p
            If b(6) = b(4) = b(2) = p Then r = p

    Next

    Return r

End Function
于 2010-02-12T15:49:35.587 回答
1

Lua,130 个字符

130 个字符只是函数大小。如果没有找到匹配,该函数不返回任何内容,这在 Lua 中类似于返回 false。

function f(t)z={7,1,4,1,1,3,2,3,3}for b=1,#z-1 do
i=z[b]x=t[i]n=z[b+1]if 0<x and x==t[i+n]and x==t[i+n+n]then
return x end end end

assert(f{1,2,1,0,1,2,1,0,2}==1)
assert(f{1,2,1,0,0,2,1,0,2}==nil)
assert(f{1,1,2,0,1,2,1,0,2}==2)
assert(f{2,1,2,1,2,1,2,1,2}==2)
assert(f{2,1,2,1,0,2,2,2,1}==nil)
assert(f{1,2,0,1,2,0,1,2,0}~=nil)
assert(f{0,2,0,0,2,0,0,2,0}==2)
assert(f{0,2,2,0,0,0,0,2,0}==nil)

assert(f{0,0,0,0,0,0,0,0,0}==nil)
assert(f{1,1,1,0,0,0,0,0,0}==1)
assert(f{0,0,0,1,1,1,0,0,0}==1)
assert(f{0,0,0,0,0,0,1,1,1}==1)
assert(f{1,0,0,1,0,0,1,0,0}==1)
assert(f{0,1,0,0,1,0,0,1,0}==1)
assert(f{0,0,1,0,0,1,0,0,1}==1)
assert(f{1,0,0,0,1,0,0,0,1}==1)
assert(f{0,0,1,0,1,0,1,0,0}==1)
于 2010-02-12T00:44:09.403 回答
1

Python,285 字节

b,p,q,r=["."]*9,"1","2",range
while"."in b:
 w=[b[i*3:i*3+3]for i in r(3)]+[b[i::3]for i in r(3)]+[b[::4],b[2:8:2]]
 for i in w[:3]:print i
 if["o"]*3 in w or["x"]*3 in w:exit(q)
 while 1:
  m=map(lambda x:x%3-x+x%3+7,r(9)).index(input())
  if"."==b[m]:b[m]=".xo"[int(p)];p,q=q,p;break

...哦,这不是你说“代码高尔夫:井字游戏”时的意思吗?;)(输入小键盘数字以放置 x 或 o,即 7 是西北)

长版

board = ["."]*9   # the board
currentname = "1" # the current player
othername = "2"   # the other player

numpad_dict = {7:0, 8:1, 9:2, # the lambda function really does this!
               4:3, 5:4, 6:5,
               1:6, 2:7, 3:8}

while "." in board:
    # Create an array of possible wins: horizontal, vertical, diagonal
    wins = [board[i*3:i*3+3] for i in range(3)] + \ # horizontal
           [board[i::3]      for i in range(3)] + \ # vertical
           [board[::4], board[2:8:2]]               # diagonal

    for i in wins[:3]: # wins contains the horizontals first,
        print i        # so we use it to print the current board

    if ["o"]*3 in wins or ["x"]*3 in wins: # somebody won!
        exit(othername)                    # print the name of the winner
                                           # (we changed player), and exit
    while True: # wait for the player to make a valid move
        position = numpad_dict[input()] 
        if board[position] == ".": # still empty -> change board
            if currentname == "1":
                board[position] = "x"
            else:
                board[position] = "o"
            currentname, othername = othername, currentname # swap values
于 2010-06-20T00:26:05.240 回答
1

C 中的解决方案(162 个字符):

这利用了玩家一值 (1) 和玩家二值 (2) 具有独立位设置的事实。因此,您可以将三个测试框的值按位与在一起——如果该值不为零,则所有三个值必须相同。此外,结果值 == 获胜的玩家。

到目前为止,这不是最短的解决方案,而是我能做的最好的解决方案:

void fn(){
    int L[]={1,0,1,3,1,6,3,0,3,1,3,2,4,0,2,2,0};
    int s,t,p,j,i=0;
    while (s=L[i++]){
        p=L[i++],t=3;
        for(j=0;j<3;p+=s,j++)t&=b[p];
        if(t)putc(t+'0',stdout);}
}

更易读的版本:

void fn2(void)
{
    // Lines[] defines the 8 lines that must be tested
    //  The first value is the "Skip Count" for forming the line
    //  The second value is the starting position for the line
    int Lines[] = { 1,0, 1,3, 1,6, 3,0, 3,1, 3,2, 4,0, 2,2, 0 };

    int Skip, Test, Pos, j, i = 0;
    while (Skip = Lines[i++])
    {
        Pos = Lines[i++];   // get starting position
        Test = 3;           // pre-set to 0x03 (player 1 & 2 values bitwise OR'd together)

        // search each of the three boxes in this line
        for (j = 0; j < 3; Pos+= Skip, j++)
        {
            // Bitwise AND the square with the previous value
            //  We make use of the fact that player 1 is 0x01 and 2 is 0x02
            //  Therefore, if any bits are set in the result, it must be all 1's or all 2's
            Test &= b[Pos];
        }

        // All three squares same (and non-zero)?
        if (Test)
            putc(Test+'0',stdout);
    }
}
于 2010-02-11T17:34:34.637 回答
1

Python,102 个字符

由于您没有真正指定如何获取输入和输出,因此这是可能必须包装到函数中的“原始”版本。b是输入列表;r是输出(0、1 或 2)。

r=0
for a,c in zip("03601202","11133342"):s=set(b[int(a):9:int(c)][:3]);q=s.pop();r=r if s or r else q
于 2010-02-11T21:15:23.780 回答
1

Python - 75 个字符 (64)

我想出了 2 个表达式,每个 64 个字符:

max(a[c/8]&a[c/8+c%8]&a[c/8-c%8]for c in map(ord,'\t\33$#"!+9'))

max(a[c/5]&a[c/5+c%5]&a[c/5+c%5*2]for c in[1,3,4,8,12,13,16,31])

当您添加“W = lambda b:”以使其成为函数时,会产生 75 个字符。迄今为止最短的 Python?

于 2010-05-18T08:54:35.533 回答
0

C、113 个字符

f(int*b){char*s="012345678036147258048264\0";int r=0;while(!r&&*s){int q=r=3;while(q--)r&=b[*s++-'0'];}return r;}

我认为它有效?我的第一个代码高尔夫,要温柔。

每 3 个数字编码 3 个需要匹配的单元格。内部 while 检查一个三元组。外部 while 检查所有 8。

于 2010-02-12T20:38:14.503 回答
0

C#, 154 163 170 177 characters

Borrowing a couple of techniques from other submissions. (didn't know C# let you init arrays like that)

static int V(int[] b)
{
   int[] a={0,1,3,1,6,1,0,3,1,3,2,3,0,4,2,2};
   int r=0,i=-2;
   while((i+=2)<16&&(r|=b[a[i]]&b[a[i]+a[i+1]]&b[a[i]+a[i+1]*2])==0){}
   return r;
}
于 2010-02-11T18:37:34.783 回答
0

Common Lisp,171 个字符

高尔夫模式:

(defun x(b)(find-if-not 'null(mapcar(lambda(r)(let((v(mapcar(lambda(c)(elt b c))r)))(if(apply '= v)(car v))))'((0 1 2)(3 4 5)(6 7 8)(0 3 6)(1 4 7)(2 5 8)(0 4 8)(2 4 6)))))

可读模式:

(defun ttt-winner (board)
  (find-if-not 'null
          (mapcar (lambda (row)
                    (let ((vals (mapcar (lambda (cell) (elt board cell)) row)))
                      (if (apply '= vals) (car vals))))
              '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6)))))
于 2010-04-16T07:45:56.347 回答
0

林Q 236

如果没有函数声明,在 C# 中可能会减少;)

Function P(ByVal b())
    Dim s() = "012.048.036.147.258.345.678".Split(".")
    If (From x In s Where b(Val(x(0))) & b(Val(x(1))) & b(Val(x(2))) = "111").Any Then Return 1
    If (From x In s Where b(Val(x(0))) & b(Val(x(1))) & b(Val(x(2))) = "222").Any Then Return 2
    Return 0
End Function
于 2010-03-31T19:00:48.570 回答
0

Python,140 个字符

我的第一个代码高尔夫,重达 140 个字符(重要声明,我否认你!):

import operator as o

def c(t):return({1:1,8:2}.get(reduce(o.mul,t[:3]),0))
def g(t):return max([c(t[x::y]) for x,y in zip((0,0,0,1,2,2,3,6),(1,3,4,3,3,2,1,1))])

稍微不那么晦涩的 g:

def g(t):return max([c(t[x::y]) for x,y in [[0,1],[0,3],[0,4],[1,3],[2,3],[2,2],[3,1],[6,1]]])
于 2010-02-12T15:45:59.873 回答
0

C# 解决方案。

将每行中的值相乘,列和对角线。如果结果 == 1,则 X 获胜。如果结果 == 8,则 O 获胜。

int v(int[] b)
{
    var i = new[] { new[]{0,1,2}, new[]{3,4,5}, new[]{6,7,8}, new[]{0,3,6}, new[]{1,4,7}, new[]{2,5,8}, new[]{0,4,8}, new[]{2,4,6} };
    foreach(var a in i)
    {
        var n = b[a[0]] * b[a[1]] * b[a[2]];
        if(n==1) return 1;
        if(n==8) return 2;
    }
    return 0;
}
于 2010-02-12T17:19:13.397 回答
0

红宝石,149 个字符

def s(b)(0..8).to_a+[0,3,6,1,4,7,2,5,8,0,4,8,2,4,6].each_slice(3){|m|if b.values_at(*m).uniq.length<2&&b[m[0]]!=0;return b[m[0]];end}return false;end

这是一个相当简单的解决方案,我相信我可以进一步减少它。这是一个可读的版本:

def someone_won(b)
    helper = (0..8).to_a + [ 0, 3, 6, 1, 4, 7, 2, 5, 8, 0, 4, 8, 2, 4, 6]
    helper.each_slice(3) { |m|
        if b.values_at(*m).uniq.length < 2 && b[m[0]] != 0
            return b[m[0]]
        end
    }

    return false
end
于 2010-02-11T17:21:45.403 回答
0

C#,180 个字符:

var s=new[]{0,0,0,1,2,2,3,6};
var t=new[]{1,3,4,3,2,3,1,1};
return(s.Select((p,i)=>new[]{g[p],g[p+t[i]],g[p+2*t[i]]}).FirstOrDefault(l=>l.Distinct().Count()==1)??new[]{0}).First();

g作为网格)

可能会有所改进......我仍在努力;)

于 2010-02-12T00:06:40.927 回答
0

C#,我认为是 148。

 int[] m={0,1,3,1,6,1,0,3,1,3,2,3,0,4,2,2};int i,s,w,r=0,o;for(i=0;i<16;i+=2){s=m[i];w=m[i+1];o=v[s];if((o==v[w+s])&&(o==v[s+(w*2)])){r=o;}}return r;
于 2010-02-13T00:28:31.043 回答
0

Java,155 个字符

在我的第一个代码高尔夫上辛勤工作后,我能够将函数减少到 155 个字符(诅咒你的数组括号!)。通过一些数学技巧,我能够概括出水平、垂直和对角线的三单元格检查。此外,我独立发现了我看到的 Eric Pi 也注意到的关于使用按位与测试三元组等价的内容。我的方法:

int i=-1,j,w=0;int[]a={0,0,2,0,9,3,3,1,3,1,1,1,1,3,2,4};while(++i<4)for(j=a[i];j<a[i+4];j+=a[i+8])if((g[j]&g[j+a[i+12]]&g[j+2*a[i+12]])>0)w=g[j];return w;

另外,我创建了一个类来生成所有有效的测试板(不像听起来那么简单)。对于那些有兴趣尝试在 Java 中达到最佳 155 的人,这是我的测试课程:

public class TicTacToe
{
public static void main(String[] args)
{
    int[][] boards = generateBoards();

    for(int i = 0; i < boards.length; ++i)
    {
        int winner = getWinner(boards[i]);

        System.out.println(winner + "  " + boards[i][0] + " " + boards[i][1] + " " + boards[i][2]);
        System.out.println(        "   " + boards[i][3] + " " + boards[i][4] + " " + boards[i][5]);
        System.out.println(        "   " + boards[i][6] + " " + boards[i][7] + " " + boards[i][8]);
        System.out.println();
    }
}

public static int getWinner(int[] g)
{
    int i=-1,j,w=0;int[]a={0,0,2,0,9,3,3,1,3,1,1,1,1,3,2,4};while(++i<4)for(j=a[i];j<a[i+4];j+=a[i+8])if((g[j]&g[j+a[i+12]]&g[j+2*a[i+12]])>0)w=g[j];return w;
}

public static boolean isValid(int[] board)
{
    // O = 0 : X = 1
    int counts[] = new int[2];

    // Count the number of Xs and Os
    for(int i = 0; i < 9; ++i)
        if(board[i] > 0)
            ++counts[board[i] - 1];

    // Make sure the counts make sense. If not return "no"
    if(!(counts[1] == counts[0] || counts[1] == counts[0] + 1))
        return false;

    // Now we're going to total the number of horizontal/vertical wins
    int wins[] = new int[2];

    // Check rows
    if(board[0] != 0 && board[0] == board[1] && board[1] == board[2]) ++wins[board[0] - 1];
    if(board[3] != 0 && board[3] == board[4] && board[4] == board[5]) ++wins[board[3] - 1];
    if(board[6] != 0 && board[6] == board[7] && board[7] == board[8]) ++wins[board[6] - 1];

    // Check columns
    if(board[0] != 0 && board[0] == board[3] && board[3] == board[6]) ++wins[board[0] - 1];
    if(board[1] != 0 && board[1] == board[4] && board[4] == board[7]) ++wins[board[1] - 1];
    if(board[2] != 0 && board[2] == board[5] && board[5] == board[8]) ++wins[board[2] - 1];

    // Make sure the win counts make sense
    if(wins[0] > 1 && wins[1] > 1)
        return false;

    // Hmmmm... I guess it's a valid board
    return true;
}

public static int[][] generateBoards()
{
    int boardSize = 9;
    int permutationCount = (int)Math.pow(4, 9);
    int[][] boards = new int[permutationCount][boardSize];
    int actualIndex = 0;

    for(int i = 0; i < permutationCount; ++i)
    {
        boolean isUnique = true;

        for(int j = 0; j < boardSize; ++j)
        {
            int x = (i >>> j) & 3;

            if(x == 3)
                isUnique = false;

            boards[actualIndex][j] = x;
        }

        if(isUnique && isValid(boards[actualIndex]))
            ++actualIndex;
    }

    return Arrays.copyOf(boards, actualIndex);
}
}

我想对于没有任何外来函数调用的简单 java 来说还不错。享受!

于 2010-04-02T07:23:38.853 回答
0

c -- 144 个字符

缩小:

#define A(x) a[b[x%16]]
int c,b[]={4,8,0,1,2,4,6,0,3,4,5,2,8,6,7,2};int
T(int*a){for(c=0;c<16;c+=2)if(A(c)&A(c+1)&A(c+2))return A(c);return 0;}

两者都返回计数(一个是必需的,另一个需要用空格替换)。

从偶数位置开始并采用 mod 16 的八种获胜方式的数组代码。

从Eric Pi偷来的按位和技巧。


更具可读性的形式:

#define A(x) a[b[x%16]]

// Compact coding of the ways to win.
//
// Each possible was starts a position N*2 and runs through N*2+2 all
// taken mod 16
int c,b[]={4,8,0,1,2,4,6,0,3,4,5,2,8,6,7,2};

int T(int*a){
  // Loop over the ways to win
  for(c=0;c<16;c+=2)
    // Test for a win
    if(A(c)&A(c+1)&A(c+2))return A(c);
  return 0;
}

测试支架:

#include <stdlib.h>
#include <stdio.h>

int T(int*);

int main(int argc, char**argv){
  int input[9]={0};
  int i, j;
  for (i=1; i<argc; ++i){
    input[i-1] = atoi(argv[i]);
  };
  for (i=0;i<3;++i){
    printf("%1i  %1i  %1i\n",input[3*i+0],input[3*i+1],input[3*i+2]);
  };
  if (i = T(input)){
    printf("%c wins!\n",(i==1)?'X':'O');
  } else {
    printf("No winner.\n");
  }
  return 0;
}
于 2010-02-11T19:22:30.893 回答
0

可能可以做得更好,但我现在感觉不是特别聪明。这只是为了确保Haskell得到代表......

假设b已经存在,这会将结果放入w.

import List
a l=2*minimum l-maximum l
z=take 3$unfoldr(Just .splitAt 3)b
w=maximum$0:map a(z++transpose z++[map(b!!)[0,4,8],map(b!!)[2,4,6]])

假设输入来自标准输入并输出到标准输出,

import List
a l=2*minimum l-maximum l
w b=maximum$0:map a(z++transpose z++[map(b!!)[0,4,8],map(b!!)[2,4,6]])where
 z=take 3$unfoldr(Just .splitAt 3)b
main=interact$show.w.read
于 2010-02-11T20:12:58.267 回答
0

我确信有一种更短的方法可以做到这一点,但是...... Perl,141 个字符(函数内有 134 个)

sub t{$r=0;@b=@_;@w=map{[split//]}split/,/,"012,345,678,036,147,258,048,246";for(@w){@z=map{$b[$_]}@$_;$r=$z[0]if!grep{!$_||$_!=$z[0]}@z;}$r;}
于 2010-02-11T16:47:51.317 回答