3.19python学堂在线,四号习题集,第一部分hand游戏

@TOC

使用伪代码,来检查你的错误,使得设计变得更简单

为什么要使用伪代码?

这是学堂在线的帮助文件
http://www.xuetangx.com/asset-v1:MITx+6_00_1x+sp+type@asset+block/files_ps04_files_WhyPseudocode.pdf

学习问题的好方法,读别人的代码

<kbd>hand = {'a':1, 'q':1, 'l':2, 'm':1, 'u':1, 'i':1} </kbd>
Notice how the repeated letter 'l' is represented. Remember that with a dictionary, the usual way to access a value is hand['a'], where 'a' is the key we want to find. However, this only works if the key is in the dictionary; otherwise, we get a KeyError. To avoid this, we can use the call hand.get('a',0). This is the "safe" way to access a value if we are not sure the key is in the dictionary. d.get(key,default) returns the value for key if key is in the dictionary d, else default. If default is not given, it returns None, so that this method never raises a KeyError. For example:
<kbd>>>> hand['e'] #这种方式可能会导致错误发生
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'e'
>>> hand.get('e', 0) #这种方式就没有错误
0
</kbd>

设计playHand游戏

第一部分模块,已经给了你,帮助你获得词频和读取单词列表以待查询

# 6.00x Problem Set 4A Template
#
# The 6.00 Word Game
# Created by: Kevin Luu <luuk> and Jenna Wiens <jwiens>
# Modified by: Sarina Canelake <sarina>
#
'''
Scrabble游戏的字母分值如下:

1 A, E, I, L, N, O, R, S, T, U
2 D, G
3 B, C, M, P
4 F, H, V, W, Y
5 K
8 j, X
10 Q, Z
分值是按照字母出现的频率来计分,字母出现的频率越频繁,分值越低
'''

'''
你可以假设输入总是小写字母串或者空串 "".

'''



import random
import string

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
HAND_SIZE = 7

SCRABBLE_LETTER_VALUES = {
    'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10
}

# -----------------------------------
# Helper code
# (you don't need to understand this helper code)

WORDLIST_FILENAME = "words.txt"

def loadWords():
    """
    Returns a list of valid words. Words are strings of lowercase letters.
    
    Depending on the size of the word list, this function may
    take a while to finish.
    """
    print ("Loading word list from file...")
    # inFile: file
    inFile = open(WORDLIST_FILENAME, 'r')
    # wordList: list of strings
    wordList = []
    for line in inFile:
        wordList.append(line.strip().lower())
    print ("  ", len(wordList), "words loaded.")
    return wordList

def getFrequencyDict(sequence):
    """
    Returns a dictionary where the keys are elements of the sequence
    and the values are integer counts, for the number of times that
    an element is repeated in the sequence.

    sequence: string or list
    return: dictionary
    """
    # freqs: dictionary (element_type -> int)
    freq = {}
    for x in sequence:
        freq[x] = freq.get(x,0) + 1
    return freq
    

# (end of helper code)
# -----------------------------------

#
# Problem #1: Scoring a word
#


获取字符串模块

def getWordScore(word, n):
    """
    Returns the score for a word. Assumes the word is a valid word.

    The score for a word is the sum of the points for letters in the
    word, multiplied by the length of the word, PLUS 50 points if all n
    letters are used on the first turn.

    Letters are scored as in Scrabble; A is worth 1, B is worth 3, C is
    worth 3, D is worth 2, E is worth 1, and so on (see SCRABBLE_LETTER_VALUES)

    word: string (lowercase letters)
    n: integer (HAND_SIZE; i.e., hand size required for additional points)
    returns: int >= 0
    """

    for i in word:
        assert (i in string.ascii_lowercase or ''),'必须输入小写字母或空字符串'

            
    score=0
    for l in word:
        SCRABBLE_LETTER_VALUES[l]
        print('The score of letter ',l,' is',SCRABBLE_LETTER_VALUES[l])
        score+=SCRABBLE_LETTER_VALUES[l]
    return score*len(word)+(len(word)==n)*50
 

第二部分模块,在deaLHand为了得到至少n/3个元音字母,使用了int方法,并且修改了一部分代码以使得能够使用,为下一个部分模块的删改和游戏运行模块打基础
这里涉及到,怎么让多个零散在不同位置的print输出到同一行??
事实上,print('')不仅会输出空字符串,而且自带换行符
如果我们改成print('',end='')那么它就会以end里面的属性结尾,从而不换行!

#
# Problem #2: Make sure you understand how this function works and what it does!
#
def displayHand(hand):
    """
    Displays the letters currently in the hand.

    For example:
    >>> displayHand({'a':1, 'x':2, 'l':3, 'e':1})
    Should print out something like:
       a x x l l l e
    The order of the letters is unimportant.

    hand: dictionary (string -> int)
    """
    for letter in hand.keys():
#        print(letter)
        for j in range(hand[letter]):
             print (letter,end=' ')
    print('')              # print all on the same line

#

下面的模块能够给你随机发n个牌组成的一手牌

# Problem #2: Make sure you understand how this function works and what it does!
#
def dealHand(n):
    """
    Returns a random hand containing n lowercase letters.
    At least n/3 the letters in the hand should be VOWELS.

    Hands are represented as dictionaries. The keys are
    letters and the values are the number of times the
    particular letter is repeated in that hand.

    n: int >= 0
    returns: dictionary (string -> int)
    """
    hand={}
    numVowels = n / 3
    
    for i in range(int(numVowels)+1):
        x = VOWELS[random.randrange(0,len(VOWELS))]
        hand[x] = hand.get(x, 0) + 1
        
    for i in range(int(numVowels)+1, n):    
        x = CONSONANTS[random.randrange(0,len(CONSONANTS))]
        hand[x] = hand.get(x, 0) + 1
        
    return hand

#

第三部分模块,hand删减模块,在这里使用了字典操作语言,注意使用hand.get(i,0)不会在字典没有i键的时候报错,并且在不存在i键的时候自动生成该键并且赋值为0(不会修改字典,只是会返回0值或者设定好的值)

a={}
a.get('s',0)
Out[41]: 0
--------------------------
a
Out[42]: {}
--------------------------
a.get('s',23124)
Out[43]: 23124

updateHand模块,注意使用的时候它并不会修改hand的值,所以还要使用hand=updataHand(hand,word)来修改hand值


# Problem #2: Update a hand by removing letters
#
def updateHand(hand, word):
    """
    Assumes that 'hand' has all the letters in word.
    In other words, this assumes that however many times
    a letter appears in 'word', 'hand' has at least as
    many of that letter in it. 

    Updates the hand: uses up the letters in the given word
    and returns the new hand, without those letters in it.

    Has no side effects: does not modify hand.

    word: string
    hand: dictionary (string -> int)    
    returns: dictionary (string -> int)
    """

    newhand={}   #不能使用newhand=hand,因为这种赋值实际上是给了hand一个别名,在改动
    #newhand的时候也会同时改动hand,从而不能满足要求
    for i in hand:
        newhand[i]=hand[i]

    for i in word:
        if newhand.get(i,0)!=0:
            newhand[i]=newhand.get(i,0) - 1
    return newhand

isValidWord模块

#
# Problem #3: Test word validity
#
def isValidWord(word, hand, wordList):
    """
    Returns True if word is in the wordList and is entirely
    composed of letters in the hand. Otherwise, returns False.

    Does not mutate hand or wordList.
   
    word: string
    hand: dictionary (string -> int)
    wordList: list of lowercase strings
    """
    newhand={}
    for i in hand:
        newhand[i]=hand[i]

    for i in word:
        if newhand.get(i,0)==0:
            return False
        else:
            newhand[i]=newhand[i]-1
    return word in wordList

输出字典hand的字母个数,先转换成列表再计算个数

def calculateHandlen(hand):
    return sum(hand.values())
    #或
    #return sum([hand.get(i,0) for i in hand]) 

下面就是给玩家交互的代码了,这一块可能有一点复杂


def playHand(hand, wordList, n):
    #这是玩一手牌的设计,仅玩一次
    """
    Allows the user to play the given hand, as follows:

    * The hand is displayed.
    * The user may input a word or a single period (the string ".") 
      to indicate they're done playing
    * Invalid words are rejected, and a message is displayed asking
      the user to choose another word until they enter a valid word or "."
    * When a valid word is entered, it uses up letters from the hand.
    * After every valid word: the score for that word is displayed,
      the remaining letters in the hand are displayed, and the user
      is asked to input another word.
    * The sum of the word scores is displayed when the hand finishes.
    * The hand finishes when there are no more unused letters or the user
      inputs a "."

      hand: dictionary (string -> int)
      wordList: list of lowercase strings
      n: integer (HAND_SIZE; i.e., hand size required for additional points)
      
    """
    total=0 
    while calculateHandlen(hand)!=0:
        displayHand(hand)
        word=input('Enter word, or a "." to indicate that you are finished: ')
        if word=='.':
            print('Goodbye! Total score:',total,'points.')
            break
        if isValidWord(word, hand, wordList)==False:
            print('Invalid word, please try again.')
            print('                                                        ')
        else:
            total+=getWordScore(word, n)
            print('"',word,'" earned ',getWordScore(word, n),'points. Total:',total,'points.')
            print('                                                        ')
            hand=updateHand(hand, word)
            if calculateHandlen(hand)==0:
                print('Run out of letters. Total score:',total,'points.')
                break

新增游戏模式的代码,上面是单一游戏模式,在这里我们升级到了可选择游戏模式

def playGame(wordList):
    """
    Allow the user to play an arbitrary number of hands.

    1) Asks the user to input 'n' or 'r' or 'e'.
      * If the user inputs 'n', let the user play a new (random) hand.
      * If the user inputs 'r', let the user play the last hand again.
      * If the user inputs 'e', exit the game.
      * If the user inputs anything else, tell them their input was invalid.
 
    2) When done playing the hand, repeat from step 1    
    """
    pr=0
    while True:
        mode=input('Enter n to deal a new hand, r to replay the last hand, or e to end game: ')
        if mode=='r':
            if pr==0:
                print('You have not played a hand yet. Please play a new hand first!')
                continue
            else:
                playHand(hand,wordList,n)
                continue
        if mode=='n':
            n=HAND_SIZE
            hand=dealHand(n)
            playHand(hand,wordList,n)
            pr+=1
            continue
        if mode=='e':
            break
        else:
            print('Invalid command.',end='')
    

#
# Build data structures used for entire session and play game
#
if __name__ == '__main__':
    wordList = loadWords()
    playGame(wordList)

剩下贴完整代码,也许能够在SoloLearnPython的控制台里面很容易开始玩

import random
import string

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
HAND_SIZE = 7

SCRABBLE_LETTER_VALUES = {
    'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10
}


WORDLIST_FILENAME = "words.txt"

def loadWords():
    print ("Loading word list from file...")
    inFile = open(WORDLIST_FILENAME, 'r')
    wordList = []
    for line in inFile:
        wordList.append(line.strip().lower())
    print ("  ", len(wordList), "words loaded.")
    print('                                                        ')
    return wordList

def getFrequencyDict(sequence):
    freq = {}
    for x in sequence:
        freq[x] = freq.get(x,0) + 1
    return freq

def getWordScore(word, n):

    for i in word:
        assert (i in string.ascii_lowercase or ''),'必须输入小写字母或空字符串'
    score=0
    for l in word:
        SCRABBLE_LETTER_VALUES[l]
        score+=SCRABBLE_LETTER_VALUES[l]
    return score*len(word)+(len(word)==n)*50

def displayHand(hand):
    print('Current Hand:  ',end='')
    for letter in hand.keys():

        for j in range(hand[letter]):
             print(letter,end=' ')

def dealHand(n):
    hand={}
    numVowels = n / 3
    
    for i in range(int(numVowels)+1):
        x = VOWELS[random.randrange(0,len(VOWELS))]
        hand[x] = hand.get(x, 0) + 1
        
    for i in range(int(numVowels)+1, n):    
        x = CONSONANTS[random.randrange(0,len(CONSONANTS))]
        hand[x] = hand.get(x, 0) + 1
    return hand

def updateHand(hand, word):

    newhand={}   #不能使用newhand=hand,因为这种赋值实际上是给了hand一个别名,在改动
    #newhand的时候也会同时改动hand,从而不能满足要求
    for i in hand:
        newhand[i]=hand[i]

    for i in word:
        if newhand.get(i,0)!=0:
            newhand[i]=newhand.get(i,0) - 1
    return newhand

def isValidWord(word, hand, wordList):

    newhand={}
    for i in hand:
        newhand[i]=hand[i]

    for i in word:
        if newhand.get(i,0)==0:
            return False
        else:
            newhand[i]=newhand[i]-1
    return word in wordList

def calculateHandlen(hand):
    return sum([hand.get(i,0) for i in hand])

def playHand(hand, wordList, n):
    total=0 
    while calculateHandlen(hand)!=0:
        displayHand(hand)
        word=input('Enter word, or a "." to indicate that you are finished: ')
        if word=='.':
            print('Goodbye! Total score:',total,'points.')
            break
        if isValidWord(word, hand, wordList)==False:
            print('Invalid word, please try again.')
            print('                                                        ')
        else:
            total+=getWordScore(word, n)
            print('"',word,'" earned ',getWordScore(word, n),'points. Total:',total,'points.')
            print('                                                        ')
            hand=updateHand(hand, word)
            if calculateHandlen(hand)==0:
                print('Run out of letters. Total score:',total,'points.')
                break

def playGame(wordList):
    pr=0
    while True:
        mode=input('Enter n to deal a new hand, r to replay the last hand, or e to end game: ')
        if mode=='r':
            if pr==0:
                print('You have not played a hand yet. Please play a new hand first!')
                continue
            else:
                playHand(hand,wordList,n)
                continue
        if mode=='n':
            n=HAND_SIZE
            hand=dealHand(n)
            playHand(hand,wordList,n)
            pr+=1
            continue
        if mode=='e':
            break
        else:
            print('Invalid command.',end='')
    
if __name__ == '__main__':
    wordList = loadWords()
    playGame(wordList)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,848评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,529评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,824评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,329评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,227评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,879评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,218评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,877评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,159评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,155评论 2 315
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,987评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,736评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,273评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,407评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,663评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,158评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,517评论 2 339

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,263评论 0 10
  • 刘润110 目标管理 目标管理:企业必须先把自己的使命和任务转化为目标,再用KPI等绩效管理工具将目标转化成指标,...
    BarryZhang阅读 791评论 0 0
  • 我们好像在哪见过,又好像从没见过。匆匆地擦肩而过…… 昔日里畅聊天地的旧友,或是一起埋头做题的同学,那时的如胶似漆...
    10_20bd阅读 330评论 3 5
  • 儿子上初中作业开始多起来,有时候甚至要做到晚上十一点多。问了班级里其他家长大家快慢不一,快的学生九点多就能做完,慢...
    蝶恋花5阅读 608评论 2 4
  • 2018年的第一场雪,终于来了!是在人们都睡着了的半夜悄悄潜入的。没有风、没有雨、没有簌簌的雪花飘落,只...
    陌上花开_986b阅读 309评论 0 2