我创建这个程序是为了让我学习红宝石。它是一个随机名称生成器,它定义了一组规则,以生成相当体面的、通常是可宣布的名称。Ruby并不是我最喜欢的语言,但我需要学习它。产生的名称既包括拉丁文字母,也包括一些非拉丁符号,如奥、阿和格。
代码是相当直接的,但我怀疑我在代码中做的一些事情并不是很好的实践。在我学习ruby的过程中,它将有助于对我的程序进行代码评审:
require 'unicode'
# Constants containing all consonants and vowels in the latin alphabet + some
# extra non-latin letters. The number after each letter represents how common
# a letter should be
CONS_LATIN = ['b']*100 + ['c']*100 + ['d']*100 + ['f']*100 + ['g']*100 + ['h']*100 + ['j']*100 + ['k']*100 + ['l']*100 + ['m']*100 + ['n']*100 + ['p']*100 + ['q']*85 + ['r']*100 + ['s']*100 + ['t']*100 + ['v']*100 + ['w']*50 + ['x']*75 + ['z']*50
VOWS_LATIN = ['a']*100 + ['e']*100 + ['i']*100 + ['o']*100 + ['u']*100 + ['y']*75
VOWS_EXTRA = ['ij']*75 + ['å']*100 + ['ä']*100 + ['ö']*100 + ['ø']*75 + ['æ']*60
# Banned combinations which are hard to pronounce or look weird
BANNED_COMBOS = [['g','j'],['f','k'],['b','k'],['q','p'],['w','q'],['q','g'],['x','x'],['q', 'q'],['d','b']]
def getRandomVowel
# Only 10% chance to generate random "non-latin" vowel
if rand() <= 0.1
return VOWS_EXTRA.sample
else
return VOWS_LATIN.sample
end
end
def getRandomVowelNoDuplicates(str:)
# Generate a random vowel and if it a non-latin vowel
# then we only use it if it has not been previously used in str
vowel = getRandomVowel
while VOWS_EXTRA.include? vowel and str.include? vowel
vowel = getRandomVowel
end
return vowel
end
def getRandomConsonante
return CONS_LATIN.sample
end
def getLastCharactersFromString(str:, numChars:)
return Unicode::downcase (str[-numChars, numChars].to_s)
end
def isVowel(chr:)
return ((VOWS_LATIN.include? (Unicode::downcase chr)) or
(VOWS_EXTRA.include? (Unicode::downcase chr)))
end
def isConsonant(chr:)
return (CONS_LATIN.include? (Unicode::downcase chr))
end
def generateLetter(currentName:)
if currentName.empty?
# We have a 60% chance to generate a vowel as the first letter
if rand() <= 0.6
return Unicode::upcase getRandomVowel
else
return Unicode::upcase getRandomConsonante
end
end
if currentName.length < 2
# Append random vowel or consonant in beginning to
# prevent program from crashing if length of name is
# less than 2
if rand() <= 0.5
chr = getRandomVowelNoDuplicates(str: currentName)
else
chr = getRandomConsonante
end
lastCharacters = chr + getLastCharactersFromString(str: currentName.join(""), numChars: 1)
else
lastCharacters = getLastCharactersFromString(str: currentName.join(""), numChars: 2)
end
# Apply rules
#
# 30% chance that there will be a double vowel
# unless the last vowel is a non-latin vowel
if isConsonant(chr: lastCharacters[0]) and isVowel(chr: lastCharacters[1])
if rand() <= 0.3 and (VOWS_LATIN.include? lastCharacters[1])
return lastCharacters[1]
end
end
# No more than 2 consonants in a row
if isConsonant(chr: lastCharacters[0]) and isConsonant(chr: lastCharacters[1])
# Exception for 'chr' and 'sch'
cons = getRandomConsonante
if (lastCharacters == "ch" and cons == 'r') or
(lastCharacters == "sc" and cons == 'h')
return cons
else
return getRandomVowelNoDuplicates(str: currentName)
end
end
# No more than 2 vowels in a row
if isVowel(chr: lastCharacters[0]) and isVowel(chr: lastCharacters[1])
return getRandomConsonante
end
# If no condition above is met we have a 40% chance to generate a vowel
# and a 60% chance to generate a consonante
if rand() <= 0.4
return getRandomVowelNoDuplicates(str: currentName)
else
# Prevent weird combinations like gj, fk or bk.
cons = getRandomConsonante
for combo in BANNED_COMBOS
while (lastCharacters[1] == combo[0] and cons == combo[1])
cons = getRandomConsonante
end
end
return cons
end
end
def generateRandomName
# Generate a number between 3 and 12
# The reason we have 9 instead of 12
# is because rand()*12 could give 12
# and when we add 3, we would get 15
# which would be greater than 12 (9+3 == 12)
nameLength = (rand()*9+3).round
# Create new list and initialize counter to 0
name = []
counter = 0
# We loop nameLength times
# So if nameLength equals 9 we loop
# 9 times. We put the result of
# generateLetter into our name list
# at position counter. Counter will
# be increased AFTER we put the result
# into our name list
currentName = ""
nameLength.times do
name[counter] = generateLetter(currentName: currentName)
currentName = name
counter = counter + 1
end
# Convert the list of characters to a string using join("")
return name.join("")
end
def askForNumber
begin
puts "Enter number of names to generate"
num = gets.chomp
end while num.to_i.to_s != num # check if num is a valid number
return num.to_i
end
# Generate amount of names the user enters
num = askForNumber
num.times do
puts generateRandomName
end下面是程序的一个示例输出(生成10个名称):
Eznogio
Ool
Ekv
Elqepzea
Ypbovdioszom
Ghagy
Uggua
Owsieg
Ujgenmybho
Saomyehzod发布于 2016-09-17 11:18:03
应该将所有这些函数转换为类RandomNameGenerator的方法。这使得代码的其他部分看不到它们。
不要使用全局rand函数,而是在类中创建一个新的Random字段。为了进行测试,可以使用常量随机种子初始化此字段。
https://codereview.stackexchange.com/questions/141460
复制相似问题