2010-07-05 76 views
1

我一直在用各種語言編寫井字遊戲作爲練習,而且出現的一種模式是每個表示I已經爲定義有效的獲勝行提出了令人失望的硬編碼。他們已經通常分爲兩類:在井字格網格中表示所有有效「行」的緊湊方式

首先,板被表示爲一維或二維陣列,並且行由位置的三聯明確定義(編號爲空的空間):

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 

這具有非神奇的明確性的優點,但它似乎冗長。

另一種方法是使用數組數組和map +減少行數。它稍微好一點,但沒有讓我一路:

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,但請隨時發佈您喜歡的任何語言。我看到了tic-tac-toe代碼的高爾夫球場,雖然其中一些解決方案非常巧妙(尤其是魔術方塊!),但我正在尋找一些不太模糊的東西。

回答

1

一個速度更快,更緊湊的系統是每個方塊使用一個位。當前位置可以保存在兩個變量中: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 
+0

嗯,有趣。在該方案中進行移動時,我也可以使用'board | = 2 ** space'。檢查佔用的空間變成'xboard&oboard&2 ** space'。不知道我會稱之爲非混淆:)但它確實是緊湊的。 – seriousken 2010-07-06 15:33:54