Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # 6.00 Problem Set 3A Solutions
- #
- # The 6.00 Word Game
- # Created by: Kevin Luu <luuk> and Jenna Wiens <jwiens>
- #
- #
- import random
- import string
- import sys
- 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 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)
- # wordlist: list of strings
- wordlist = []
- for line in inFile:
- wordlist.append(line.strip().lower())
- print " ", len(wordlist), "words loaded."
- return wordlist
- # We dont need this -Nix
- #word_list = load_words()
- 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)
- # -----------------------------------
- #
- # Problem #1: Scoring a word
- #
- def get_word_score(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 go.
- 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.
- word: string (lowercase letters)
- returns: int >= 0
- """
- sum = 0
- #if is_valid_word is true
- for e in word:
- sum += SCRABBLE_LETTER_VALUES[e]
- score = len(word)*sum
- if len(word) == n:
- score += 50
- return score
- # TO DO...
- #
- # Make sure you understand how this function works and what it does!
- #
- 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
- #
- # Make sure you understand how this function works and what it does!
- #
- 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[random.randrange(0,len(VOWELS))]
- hand[x] = hand.get(x, 0) + 1
- for i in range(num_vowels, n):
- x = CONSONANTS[random.randrange(0,len(CONSONANTS))]
- hand[x] = hand.get(x, 0) + 1
- return hand
- #
- # Problem #2: Update a hand by removing letters
- #
- def update_hand(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)
- """
- # The update_hand() isn't working quite as intended.
- # It will remove all instances of a letter in the players hand, no matter
- # how many of those letters the player uses.
- # E.g.:-
- # My hand: l u c k y y x
- # I play: lucky
- # Leftover letters: x
- #
- # - Nix
- # for letter in word:
- # hand[letter] -= 1
- # for letter in hand.keys():
- # if hand[letter] == 0:
- # hand.pop(letter, 0)
- # return hand
- for letter in word:
- hand[letter] -= 1
- if hand[letter] < 1:
- hand.pop(letter)
- return hand
- #
- # Problem #3: Test word validity
- #
- 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.
- Does not mutate hand or word_list.
- word: string
- hand: dictionary (string -> int)
- word_list: list of lowercase strings
- """
- hand1 = hand
- if word in word_list:
- for letter in word:
- if letter in hand1 and hand1[letter] > 0:
- hand1[letter] -= 1
- else:
- return False
- return True
- else:
- return False
- def calculate_handlen(hand):
- handlen = 0
- for v in hand.values():
- handlen += v
- return handlen
- #
- # Problem #4: Playing a hand
- #
- def play_hand(hand, word_list):
- '''Allows the user to play a single, randomnly generated hand'''
- total = 0
- while True:
- display_hand(hand)
- word = raw_input('Enter a word compiled from the characters above or a period to end the hand:')
- if word == '.':
- break
- else:
- if is_valid_word(word, hand, word_list) == False:
- print 'Invalid word, please enter another word.'
- else:
- score = get_word_score(word, len(hand))
- total += score
- print '"'+word+'"','earned',score,'points. Total:',total,'points.'
- update_hand(hand, word)
- print "Total score:",total
- #play_hand(word_list, 7)
- #
- # Problem #5: Playing a game
- # Make sure you understand how this code works!
- #
- # I've re-written your play_game();
- # we don't need to take in 'hand' or 'n' in the function
- #
- # 'n' is just the number of characters you have in your hand, and is only
- # really useful to us when we want to add the bonus 50pts. So, I've just left
- # it local to the scoring function, instead of being passed around like a cheap
- # hooker.
- # play_game() is the "main" game function, so we don't want to take hand in
- # as a variable, we want to create the hand inside! I like to think of this
- # function as the "conductor" to the whole game, if that makes sense?
- #
- # Also, be careful with variable contents over the conditional loops.
- # You had it so the current player hand wasn't refreshed if they decided to
- # play with the same hand again.
- #
- # -Nix
- #def play_game(hand, word_list, n):
- # hand1 = hand.copy()
- # while True:
- # play_hand(hand, word_list, n)
- # print 'Input "n" to play a new hand, "r" to play the last hand again, "e" to exit the game.'
- # choice = raw_input('')
- # if choice != 'n' and choice != 'r' and choice != 'e':
- # print 'Entry invalid, try again.'
- # elif choice == 'n':
- # play_game(deal_hand(n), word_list, n)
- # elif choice == 'r':
- # play_game(hand1, word_list, n)
- # else:
- # sys.exit()
- def play_game(word_list):
- delt_hand = deal_hand(7)
- current_hand = delt_hand.copy()
- while True:
- display_hand(current_hand)
- choice = raw_input('Input "n" to play a new hand, "r" to play the last hand again, "e" to exit the game: ')
- if choice.lower() == 'n':
- delt_hand = deal_hand(7)
- current_hand = delt_hand.copy()
- play_hand(current_hand, word_list)
- elif choice.lower() == 'r':
- current_hand = delt_hand.copy()
- play_hand(current_hand, word_list)
- elif choice.lower() == 'e':
- sys.exit()
- else:
- print 'Entry invalid, try again.'
- #play_game(deal_hand(7), word_list, 7)
- #
- # Build data structures used for entire session and play game
- #
- if __name__ == '__main__':
- word_list = load_words()
- play_game(word_list)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement