1

私は演習としてさまざまな言語で三目並べを書いてきましたが、1 つのパターンとして、有効な勝者の行を定義するために思いついたすべての表現が、残念なことにハードコーディングされているということがあります。それらは一般的に次の 2 つのカテゴリに分類されます。

まず、ボードは 1 次元または 2 次元の配列として表され、行は位置のトリプレットによって明示的に定義されます (数字は空のスペースです)。

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

これには、非魔法的な明示性という利点がありますが、冗長に見えます。

もう 1 つのアプローチは、配列の配列を使用し、行を map+reduce することです。それは少し良いですが、私を完全に理解することはできません:

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

はるかに高速でコンパクトなシステムは、すべての正方形に 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 に答える