2013-10-18 46 views
0

在Google Play,Apple Store和Facebook平臺上有許多類似Boggle的遊戲。我如何生成像這些遊戲一樣的可玩棋盤?如何生成遊戲板,如boggle

+0

你心中有語言嗎?你想知道如何構造數據,或者如何創建接口?你的問題含糊不清。 –

+0

我只需要算法。語言沒有意義。 –

回答

3

最簡單的方法是生成一個統一選擇的隨機字符網格。但是這不會給你很多的話:

from random import randint 

N = 4 

def display(letters): 
    for row in letters: 
     print('+%s+' % '+'.join('-' * N)) 
     print('|%s|' % '|'.join(row)) 
    print('+%s+' % '+'.join('-' * N)) 

def uniform_char(): 
    return chr(ord('A') + randint(0, 25)) 

def to_array(fn): 
    return [[fn() for _ in range(N)] for _ in range(N)] 

display(to_array(uniform_char)) 

+-+-+-+-+ 
|B|G|C|Z| 
+-+-+-+-+ 
|G|B|T|K| 
+-+-+-+-+ 
|I|R|O|Q| 
+-+-+-+-+ 
|G|A|S|W| 
+-+-+-+-+ 

上的改進將重量再怎麼經常發生在英語(假設這是你想要的語言)文字:

from collections import Counter 

def letters(): 
    with open('/usr/share/dict/words', 'r') as words: 
     for word in words: 
      for letter in word.upper(): 
       if letter >= 'A' and letter <= 'Z': 
        yield letter 

letter_scores = Counter(letters()) 
print(letter_scores) 

# http://stackoverflow.com/questions/14992521/python-weighted-random/14992648 
def weighted_random(pairs): 
    total = sum(pair[1] for pair in pairs) 
    r = randint(1, total) 
    for (value, weight) in pairs: 
     r -= weight 
     if r <= 0: return value 

display(to_array(lambda: weighted_random(letter_scores.items()))) 

Counter({'E': 301968, 'S': 274630, 'I': 241084, 'A': 225091, 'R': 191386, 
'N': 191320, 'O': 184143, 'T': 177237, 'L': 151341, 'C': 111066, 
'U': 90838, 'D': 89014, 'M': 80645, 'P': 79507, 'G': 71689, 'H': 71423, 
'B': 52921, 'Y': 47941, 'F': 32114, 'V': 27918, 'K': 26797, 'W': 22635, 
'Z': 14022, 'X': 7861, 'J': 5130, 'Q': 4722}) 

+-+-+-+-+ 
|L|E|S|T| 
+-+-+-+-+ 
|O|A|C|P| 
+-+-+-+-+ 
|A|I|L|L| 
+-+-+-+-+ 
|N|G|S|I| 
+-+-+-+-+ 

更好的是使用n-gram(例如,普通字母對)和馬爾可夫鏈或者只是某種隨機採樣。在這裏,我從加權概率的字母開始(如上),然後設置幾個鄰居流行對(在mix我選擇一個隨機點,找到一個字母通常跟在那裏的字母,並設置一個鄰近的方塊):

def pairs(): 
    with open('/usr/share/dict/words', 'r') as words: 
     for word in words: 
      prev = None 
      for letter in word.upper(): 
       if letter >= 'A' and letter <= 'Z': 
        if prev: yield (prev, letter) 
        prev = letter 

pair_scores = Counter(pairs()) 
#print(pair_scores)                
start = to_array(lambda: weighted_random(letter_scores.items())) 

def mix(array): 
    x, y = randint(0, N-1), randint(0, N-1) 
    a = array[y][x] 
    neighbours = [(pair[1], score) 
        for (pair, score) in pair_scores.items() 
        if pair[0] == a] 
    if neighbours: 
     b = weighted_random(neighbours) 
     # print(a, b, neighbours)            
     array[(y+randint(-1,1))%N][(x+randint(-1,1))%N] = b 
    else: 
     print('no neighbours for', a) 

for _ in range(N*(N-1)//2): mix(start) 
display(start) 

+-+-+-+-+ 
|L|T|H|P| 
+-+-+-+-+ 
|S|S|S|O| 
+-+-+-+-+ 
|S|O|O|L| 
+-+-+-+-+ 
|E|S|A|E| 
+-+-+-+-+ 

不知道這是一個很大的進步,但要注意雙S,TH等

最後,當然,你可以只記下所用的骰子的字母從每個隨機選擇,完全模仿遊戲。

linux上的所有代碼python 3。

+1

(刪除以前的評論)對不起,我的遞歸掃描儀出了問題。我找到這些最長的單詞:完全隨機947個單詞,「TOBIAS」;完全加權1603字,「斯卡利亞」; digrams 1893字,「ALOOSE」。所以我猜digrams效果最好。 – usr2564301

+0

哦整齊。沒有想到測量。謝謝。 –

+0

啊!我計算了很多雙打。將總字數調整爲141,273和302.差異現在更小 - 但仍然很明顯。 – usr2564301

1

您可以谷歌搜索骰子上的「格格字母分佈」。對於4x4和5x5板卡的分配是不同的。同樣大小的板子也有不同的版本。其中一些在Wikipedia's Boggle talk page(這不是永久性的,所以現在抓住它們)給出。請注意,字母Q計爲兩個字母QU,但在分發表單中以單個字母形式表示。

+0

只適用於英語。 –