首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >红宝石中随机名的生成

红宝石中随机名的生成
EN

Code Review用户
提问于 2016-09-15 19:08:32
回答 1查看 1K关注 0票数 6

我创建这个程序是为了让我学习红宝石。它是一个随机名称生成器,它定义了一组规则,以生成相当体面的、通常是可宣布的名称。Ruby并不是我最喜欢的语言,但我需要学习它。产生的名称既包括拉丁文字母,也包括一些非拉丁符号,如奥、阿和格。

代码是相当直接的,但我怀疑我在代码中做的一些事情并不是很好的实践。在我学习ruby的过程中,它将有助于对我的程序进行代码评审:

代码语言:javascript
复制
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个名称):

代码语言:javascript
复制
Eznogio
Ool
Ekv
Elqepzea
Ypbovdioszom
Ghagy
Uggua
Owsieg
Ujgenmybho
Saomyehzod
EN

回答 1

Code Review用户

发布于 2016-09-17 11:18:03

应该将所有这些函数转换为类RandomNameGenerator的方法。这使得代码的其他部分看不到它们。

不要使用全局rand函数,而是在类中创建一个新的Random字段。为了进行测试,可以使用常量随机种子初始化此字段。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/141460

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档