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

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

为什么要使用伪代码?

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

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

hand = {‘a’:1, ‘q’:1, ‘l’:2, ‘m’:1, ‘u’:1, ‘i’:1}
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:
>>> hand[‘e’] #这种方式可能会导致错误发生
Traceback (most recent call last):
File “”, line 1, in
KeyError: ‘e’
>>> hand.get(‘e’, 0) #这种方式就没有错误
0

设计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)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值