# 6.00 Problem Set 4 # # Word Game II: The Revenge # VOWELS = 'aeiou' CONSONANTS = 'bcdfghjklmnpqrstvwxyz' HAND_SIZE = 7 # ----------------------------------- # Helper code # (you don't need to understand this helper code) from random import randrange import string import time WORDLIST_FILENAME = "words.txt" def load_words(): """ 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', 0) # line: string line = inFile.readline() # wordlist: list of strings wordlist = string.split(line) print " ", len(wordlist), "words loaded." return wordlist def get_frequency_dict(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) # ----------------------------------- def get_word_score(word): """ Returns the score for a word. Assumes the word is a valid word. The score for a word is the sum of the scores of the individual letters, multiplied by the length of the word. Letters that are VOWELS get a score of 1. Letters that are CONSONANTS get a score of 2. word: string (lowercase letters) returns: int >= 0 """ score = 0 for ch in word: if ch in VOWELS: score += 1 else: score += 2 return score * len(word) def display_hand(hand): """ Displays the letters currently in the hand. For example: display_hand({'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(): for j in range(hand[letter]): print letter, # print all on the same line print # print an empty line def deal_hand(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={} num_vowels = n / 3 for i in range(num_vowels): x = VOWELS[randrange(0,len(VOWELS))] hand[x] = hand.get(x, 0) + 1 for i in range(num_vowels, n): x = CONSONANTS[randrange(0,len(CONSONANTS))] hand[x] = hand.get(x, 0) + 1 return hand def update_hand(hand, word): """ Updates the hand: uses up the letters in the given word and returns the new hand, without those letters in it. Assumes that 'word' is a valid word. Therefore, all the letters in 'word' are in the given hand. word: string hand: dictionary (string -> int) returns: dictionary (string -> int) """ for ch in word: hand[ch] -= 1 return hand def is_valid_word(word, hand, word_list): """ Returns True if word is in the word_list and is entirely composed of letters in the hand. Otherwise, returns False. word: string hand: dictionary (string -> int) word_list: list of strings """ if word in word_list: freq = get_frequency_dict(word) for letter in freq: count = freq[letter] if count > hand.get(letter, 0): return False return True else: return False def hand_has_letters(hand): """ return true if the hand still has letters in it """ for letter in hand: if hand[letter] > 0: return True return False ### New, Problem Set 4 code, begins here ### (None of the functions above here should ### come as a huge surprise to you -- though ### make sure you understand them) ## A helper function for you! def getYesNo(prompt): """ Prompts the user with the string, prompt, with '? ' appended to it. Returns: True if the user responds with something beginning with 'y' or 'Y' (e.g. 'yes') False otherwise """ response = raw_input(prompt + '? ') if len(response) and response[0] in 'yY': return True else: return False def get_word_from_human(prompt, hand, word_list): """ Asks a human to input a word. Returns: either a valid word, or '.' if the human has given up or run out of time. """ ### TODO: Problem 1 ### You'll want to add your timing code ### here -- return '.' if the user ### took too long in coming up with ### an answer. while True: word = raw_input(prompt) if is_valid_word(word, hand, word_list) or word == '.': return word else: print 'Invalid word, please try again.' def get_word_from_computer(hand, word_list): """ Computes the highest-scoring word that can be made, given the letters in 'hand', or '.' if no word can be made. After computing the optimal word, this function prints 'I guessed ', followed by the word. Returns: Optimal word that can be made out of 'hand', or '.', if no word can be made Runtime: ### TODO: Problem 3 ### ### Fill in the runtime, in terms ### of n and d, here """ ### TODO: Problem 3 ### Put your computer-player code here return None def play_hand(players, hand, word_list): """ Plays a hand of the 6.00 game. players: some sort of data structure containing information about the people playing the game (TODO: Problem 3: decide how you are going to do this, and adjust the specification accordingly) hand: the hand to be played word_list: list of all the valid words Returns: no return value, returns when game is finished """ ### TODO: Problem 2: ### You'll write a lot of code here to create ### a multiplayer version of this game ### (don't be afraid to delete the code in here already) total = 0 prompt = 'Enter word, or a . to indicate that you are finished: ' while hand_has_letters(hand): print 'Current Hand: ', display_hand(hand) word = get_word_from_human(prompt, hand, word_list) if word == '.': break # At this point, we know the word is valid, # because get_word_from_human ensures that update_hand(hand, word) score = get_word_score(word) total += score print word, 'earned', score, 'points. Total:', total, 'points' ### TODO: Problem 4: ### You'll probably want to put the scoreboard ### code here print 'Total score:', total, 'points' print return def play_game(word_list): while True: print "Welcome to the 6.00 word game!" ### TODO: Problem 2: ### You'll probably want to add code here ### that gathers information about the ### players, and then calls play_hand ### appropriately. ### ### Feel free to scrap the code ### that is currently here, if you ### don't like it. hand = deal_hand(HAND_SIZE) # Why are we passing in None? # Well, we're not using the 'players' # argument, but maybe you might want to? # (If you think it's appropriate, go ahead # and add other arguments, too # ... # in general, we don't like you # breaking interfaces by changing # function definitions, but here, # you're the only client of this function, # and it's not really designed for reuse, # so go for it) play_hand(None, hand, word_list) ### TODO: Problem 4: ### This is probably a good place ### to ask whether the user wants ### to specify a hand, or accept ### a randomly-generated one instead. again = getYesNo("Play again ") print if not again: break if __name__ == '__main__': word_list = load_words() play_game(word_list)