1

我一直在用各种语言编写井字游戏作为练习,并且出现的一种模式是,我为定义有效的获胜行提出的每个表示都被令人失望地硬编码。它们通常分为两类:

首先,棋盘表示为一维或二维数组,行由位置的三元组显式定义(数字为空格):

board = [1, x, 3, 4, o, 6, 7, 8, x]

def match3(x,y,z)
  board[x] == board[y] && board[y] == board[z]
end

def winner
  match3(1,2,3) || match3(4,5,6) || ...
end

这具有非神奇的明确性的优点,但它看起来很冗长。

另一种方法是使用数组数组并映射+减少行。它稍微好一点,但并没有让我一路走好:

board = [[nil, 1, nil], [nil, -1, nil], [nil, nil, 1]]

def diag(x,y,z)
  [board[x/3,x%3], board[y/3,y%3], board[z/3,z%3]]
end

def winner
  rows = board + board.transpose << diag(0,4,8) << diag(2,4,6)
  rows.map { |r| r.reduce(:&) }.reduce { |m,c| m || c }
end

垂直和水平匹配很棒,但我仍在对对角线进行硬编码。

任何人都可以想出一种方法来表征不依赖于显式地址的对角线(或完全不同的方法)吗?

我的伪代码是 Rubyish,但请随时以您喜欢的任何语言发布。我看到了井字游戏代码高尔夫,虽然其中一些解决方案很巧妙(尤其是魔方!)但我正在寻找一些不那么令人困惑的东西。

4

1 回答 1

2

一个更快、更紧凑的系统是为每个正方形使用一个位。当前位置可以保存在两个变量中:X 保存所有“X”标记,O 保存所有“O”标记。例如,9 个正方形的可能编码是

 1   2   4
 8  16  32
64 128 256

使用这种编码,第一行是1+2+4=7,上/左->下/右对角线是1+16+256=273

检查第一行的 X 是否获胜if ((X & 7) == 7),其他检查类似,但数字不同,而不是 7。完整的胜利检查例程变为......

def winner(p):
    for m in (7, 56, 448, 73, 146, 292, 273, 84):
        if p & m == m: return True
    return False
于 2010-07-05T23:32:37.953 回答