Google Play、Apple Store 和 Facebook 平台上有许多类似 Boggle 的游戏。我如何生成像那些游戏一样的可玩棋盘?
问问题
2368 次
2 回答
4
最简单的方法是生成一个均匀选择的随机字符网格。但这不会给你很多话:
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 等。
最后,当然,您可以只记下 boggle 中使用的骰子上的字母,然后从每个字母中随机选择,完全模仿游戏。
linux上的所有代码python 3。
于 2013-10-18T21:08:26.747 回答
1
您可以在骰子上搜索“Boggle letter distribution”。4x4 和 5x5 板的分布不同。同样尺寸的板也有变化。其中一些是在Wikipedia 的 Boggle 讨论页上给出的(这不是永久性的,所以现在就抓住它们)。请注意,字母 Q 算作两个字母 QU,但在分配表中写为单个字母。
于 2013-10-19T13:31:03.053 回答