~callum/hangman

hangman/hangman.py -rw-r--r-- 5.1 KiB
0918c0faCallum Brown Added GPLv3 license 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import random

def find_all(s, ch):
    '''Get indexes of all occurences of a char in a str (or array)
        code from https://stackoverflow.com/a/11122355
    '''
    return [i for i, ltr in enumerate(s) if ltr == ch]


def get_words():
    '''Return a list of words for user to guess
       from user input or from words.txt
    '''
    word_source = ""
    while word_source not in ["m", "p"]:
        word_source = input("\n\nDo you want to enter a list of words manually (m) or use preset words (p)?\n    Please enter 'm' or 'p': ")
    if word_source == "p":
        return open("words.txt").read().splitlines()
    else:
        words_string = input("\nEnter words seperated by a space (' '):  ")
        return words_string.split()


def new_word():
    '''Get a random word from list
        then remove it from list so it's not picked again
    '''
    global words
    word = random.choice(words)
    words.remove(word)
    return word.lower()


def draw_hangman(lives_used):
    '''draw the gallows and man being hung'''
    
    #order: base, upright, horizontal, rope, diagonal, head, body, left arm, right arm, left leg, right leg
    #each sub list is the next step in drawing the gallows
    #each sub sub list is format [[x,y], character]
    order = [
        [[[15,0],"-"],[[15,1],"-"],[[15,2],"-"],[[15,3],"-"],[[15,4],"-"],[[15,5],"-"],[[15,6],"-"],[[15,7],"-"],[[15,8],"-"],[[15,9],"-"]],
        [[[14,3],"|"],[[13,3],"|"],[[12,3],"|"],[[11,3],"|"],[[10,3],"|"],[[9,3],"|"],[[8,3],"|"],[[7,3],"|"],[[6,3],"|"],[[5,3],"|"],[[4,3],"|"],[[3,3],"|"],[[2,3],"|"],[[1,3],"|"]],
        [[[0,3],"+"],[[0,4],"-"],[[0,5],"-"],[[0,6],"-"]],
        [[[0,7],"+"],[[1,7],"|"]],
        [[[3,4],"/"],[[2,5],"/"],[[1,6],"/"]],
        [[[2,7],"-"],[[3,6],"|"],[[3,8],"|"],[[4,7],"-"]],
        [[[5,7],"|"],[[6,7],"|"],[[7,7],"|"],[[8,7],"|"]],
        [[[5,6],"-"],[[6,5],"/"],[[7,5],"|"],[[8,5],"|"]],
        [[[5,8],"-"],[[6,9],"\\"],[[7,9],"|"],[[8,9],"|"]],
        [[[9,6],"/"],[[10,6],"|"],[[11,6],"|"],[[12,6],"|"],[[13,6],"/"]],
        [[[9,8],"\\"],[[10,8],"|"],[[11,8],"|"],[[12,8],"|"],[[13,8],"\\"]],
        ]
    
    #16x10 array
    toprint = [[" " for y in range(10)] for x in range(16)]
    
    #print out as many items in order as lives have been used
    for l in range(lives_used):
        step = order[l]
        for part in step:
            x = part[0][0]
            y = part[0][1]
            character = part[1]
            #add character to relevant position in toprint
            toprint[x][y] = character
    
    for m in toprint:
        for n in m:
            print(n, end="")
        print("")


def play():
    '''Play the actual game'''
    # random word as chars in a list
    word = list(new_word())
    # set guessed word to as many blanks as there are letters in word
    guessed_word = ["_"] * len(word)
    lives_used = 0
    guessed_letters = []
    
    # while user hasn't completley guessed word (will also be limited by lives_used in future)
    while guessed_word != word and lives_used < 11:
        print("\n\n")
        draw_hangman(lives_used)
        # print out the guessed_word so far and wrong letters guessed in nice format
        print(" ".join(guessed_word))
        print("You have already guessed: " + ", ".join(guessed_letters))
        
        guessed_letter = input("\nGuess a letter: ").lower()
        # only let user guess a single letter
        while len(guessed_letter) != 1 :
            print("Please enter a single letter.")
            guessed_letter = input("\nGuess a letter: ").lower()
        # only let user guess letters they haven't guessed already
        while guessed_letter in guessed_letters:
            print("You already guessed that letter.")
            guessed_letter = input("\nGuess a letter: ").lower()
        
        if guessed_letter in word:
            # get indexes in word that are guessed_letter
            letter_indexes = find_all(word, guessed_letter)
            for i in letter_indexes:
                # replace correct blanks with letter
                guessed_word[i] = guessed_letter
            print("Correct!")
        else:
            lives_used += 1
            print("Wrong! You have used %i lives" % lives_used)
            # in future: you have n lives left
            guessed_letters.append(guessed_letter)
    
    print("\n\n")
    if guessed_word == word:
        print(" ".join(guessed_word))
        print("Well done, you guessed the word! In total you used %i lives." % lives_used)
    elif lives_used == 11:
        draw_hangman(lives_used)
        print("You died! Better luck next time.")
        print("The word was: %s" % "".join(word))

input("Press any key to start.")

words = get_words()
play_again = 'y';

while len(words) > 0 and play_again =='y':
    print("\n\n")
    play()
    print("\n\n")
    
    play_again = ''
    # while user doesn't enter y or n
    while play_again not in ['y','n']:
        play_again = input("Play again? (y/n): ").lower()



print("\n")

# if user chose to play again but while ended because len(words) == 0   
if play_again == 'y':
    print("Sorry, I ran out of words.")
    
print("Bye.")