Scrabble游戏Python脚本调用报错:score_word未定义(Jupyter可运行)
解决Scrabble游戏中
score_word未定义的问题 问题背景
开发的Scrabble变体游戏在Jupyter Notebook中可正常运行,但从.py文件调用run_scrabble("BH*")时无法通过自动化测试,触发NameError提示score_word未定义。代码分为scrabble.py和wordscore.py两个文件。
报错信息
Test Failed: NameError("name 'score_word' is not defined",) is not false : Your program produced an exception: name 'score_word' is not defined
相关代码
scrabble.py
import wordscore import sys def run_scrabble(argv): """ This is a modified version of the traditional scrabble game. The user plays the game from the command promt by running run_scrabble and provides the 'rack' as the input. The rack is the selection of between 2-7 words and special characters (* or ? only) The highlights of the game are 1. Allow anywhere from 2-7 character tiles (letters A-Z, upper or lower case) 2. Do not restrict the number of same tiles (e.g., a user is allowed to input ZZZZZQQ). 3. There can be a total of only two wild cards in any user input that is, one of each character: one `*` and one `?`). Only use the `*` and `?` as wildcard characters. 4. A wildcard character can take any value A-Z. 5. Wildcard characters are scored as 0 points, just like in the real Scrabble game. A word that just consists of two wildcards can be made, should be outputted and scored as 0 points. """ ################ COMMAND LINE ARGS ################################### rack = argv #renamed argv to 'rack' just to make it easier for me to read ############### INITIALIZATION ################################ # converts the input rack to lower case rack_low = rack.lower() rack_letters = list(rack_low) # converts the rack to a list of letters valid_words = [] # An empty list that will eventually hold all valid words from the scrabble dictionary sowpods.txt valid_rack = True # A boolean condition the evaluates the contents of the rack as valid or not clean_rack = [] # this removes the special characters from the rack ################ VALIDATIONS ################################### if (rack_low.count('?') > 1 or rack_low.count('*')) > 1: return ("You have entered more than 2 special characters") valid_rack = False # checks the condition for only 1 of the special characters is allowed # ie the user cannot enter two * or two ? # the user can enter one * and one ? elif len(rack_low) > 7 or len(rack_low) < 2: return ("You have entered more than 7 characters or less than 2") valid_rack = False # checks the number of letters in the rack for a minimum of 2 and maximum of 7 ###################################################################### elif all(x.isalpha() or x in ('?', '*') for x in rack_low): valid_rack = True pass # checks if the contains only alphabets or special characters (* ?) else: return ('You have entered non-permitted characters. Please enter only alphabets and/or special characters * and ?') valid_rack = False # this condition needs rework # would ###################################################################### # Deprecated code: Replaced with condition above (would like to make this work # but condition is not tight enough # elif all(x.isalpha() == False and x not in ('?', '*') for x in rack_low): # valid_rack = False # return ('You have entered non-permitted characters. Please enter only alphabets and/or special characters * and ?') # # checks if the contains only alphabets or special characters (* ?) # else: # valid_rack = True # # this condition needs rework ###################################################################### if valid_rack: # reads the scrabble reference dictionary and creates a data list # after stripping the line breaks with open("sowpods.txt","r") as infile: raw_input = infile.readlines()#[0:1000] data = [datum.strip('\n') for datum in raw_input] # this is the matching algorithm that iterates through each word in the # scrabble dictionary (data) and checks whether the letters exists in the # user input (rack). This also accounts for the two special characters (*, ?) # and by a process of elimination is able to implicitly substitute them for # other alphabets for word in data: word_low = word.lower() temp_rack_letters = rack_letters.copy() for letter in word_low: if letter in temp_rack_letters : temp_rack_letters .remove(letter) elif '*' in temp_rack_letters : temp_rack_letters .remove('*') elif '?' in temp_rack_letters : temp_rack_letters .remove('?') else: break ####################### WILDCARD ZERO-ORIGINAL ################### # else: # valid_words.append([score_word(word_low), word_low.upper()]) ####################### WILDCARD ZERO-REWORK ######################## else: clean_rack = ''.join([i for i in rack_low if i.isalpha()]) # removes the special characters from the rack valid_words.append([score_word(clean_rack), word_low.upper()]) # returns the scores for the words in the clean_rack ###################################################################### # Sort the valid words list in descending order of score valid_words.sort(reverse = True) # this is the section where we print the score and word # note this is already in descending order in valid_words for entry in valid_words: score = entry[0] word_low = entry[1] print((score, word_low)) # this is the final print of the count of all valid words print(len(valid_words)) else: valid_rack = False
wordscore.py
def score_word(rack_low): # Deprecating the scores (from original dictionary) # scores = {"a": 1, "c": 3, "b": 3, "e": 1, "d": 2, "g": 2, # "f": 4, "i": 1, "h": 4, "k": 5, "j": 8, "m": 3, # "l": 1, "o": 1, "n": 1, "q": 10, "p": 3, "s": 1, # "r": 1, "u": 1, "t": 1, "w": 4, "v": 4, "y": 4, # "x": 8, "z": 10} # modifying scores to include the two special characters: ? and * scores = {"a": 1, "c": 3, "b": 3, "e": 1, "d": 2, "g": 2, "f": 4, "i": 1, "h": 4, "k": 5, "j": 8, "m": 3, "l": 1, "o": 1, "n": 1, "q": 10, "p": 3, "s": 1, "r": 1, "u": 1, "t": 1, "w": 4, "v": 4, "y": 4, "x": 8, "z": 10, "?": 0, "*": 0} total = 0 # this is the original code (with word_low) # for letter in word_low: # Run through all letters in the word and return the score (ie total) # trying to run program with letters from the rack for letter in rack_low: total = total + scores[letter] return total
问题原因与解决方法
核心原因
scrabble.py中仅通过import wordscore导入了模块,但调用score_word时未使用模块前缀(如wordscore.score_word()),导致Python无法识别该函数。Jupyter Notebook的环境特性(如自动模块加载、命名空间共享)掩盖了这个问题,但独立运行.py文件时严格遵循Python的模块导入规则,因此触发错误。
解决方法(二选一)
- 修改导入语句:直接导入
score_word函数,这样可以直接调用:from wordscore import score_word - 添加模块前缀:在调用函数时加上模块名:
valid_words.append([wordscore.score_word(clean_rack), word_low.upper()])
额外的代码修复建议
- 修正特殊字符校验逻辑:原代码中
if (rack_low.count('?') > 1 or rack_low.count('*')) > 1:的括号位置错误,会导致逻辑判断异常,应改为:if rack_low.count('?') > 1 or rack_low.count('*') > 1: - 调整return语句顺序:原代码中
return语句后的valid_rack = False永远不会执行,应先修改变量再返回:valid_rack = False return ("You have entered more than 2 special characters")
内容的提问来源于stack exchange,提问作者gaurav8936
相关产品推荐
相关产品推荐

