2013-10-18 104 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

只适用于英语。 –