1

I'm working on a hobby project. I'm attempting to make a hangman game in Python. So far everything works nice. There's just one problem. If I type a letter that appears in the word two times, I can't get the second letter to appear. I've been toying around with string.find and string.count methods but to no avail. Does anyone have an idea how I would go about doing this? I'm stumped.

#!bin/bash/python

import os
import time

word = 'megalopolis'
l = len(word)
list = []
n=0
while n!=l:
    list.append('-')
    n+=1
os.system('cls' if os.name=='nt' else 'clear')
print list

i=3

while i!=0:
    x = raw_input('Enter a letter: ')
    if x in word and x!='':
        print 'Good choice!'
        count=word.count(x)
        loc=word.find(x)
        print count 
        print loc 
        list[loc]=x
        os.system('cls' if os.name=='nt' else 'clear')
        if '-' not in list:
            break
        print list
    else:
        print 'Sorry...'
        i-=1
        if i==2:
            print 'You have '+`i`+' more chances.'
        if i==1:
            print 'You have '+`i`+' more chance!'
        time.sleep(1)
        os.system('cls' if os.name=='nt' else 'clear')
        print list

if '-' not in list:
    print 'YOU WIN!!'
else:
    print 'GAME OVER!!'

x = raw_input('press enter')
Darkc0de
  • 53
  • 1
  • 5

3 Answers3

2

If you just need the index of every character occurence:

indexes = [idx for idx, ch in enumerate(word) if ch == x]

Perhaps you should use Unidecode to keep the accents in words, it might be useful depending on the language (if not English). Also, you can use str.lower() or str.upper() methods to ensure every word and trial is in the same case.

The string module has useful constants for you (e.g. ascii_uppercase).

However, in this game you don't need to worry about any index. I've made another version for you:

#!/usr/bin/env python
from string import ascii_uppercase

word = "megalopolis".upper() # Top-secret!
trial = 3 # Total trials available (number of mistakes to lose the game)
typed = set() # Typed characters
word_letters = set(word)

while trial:
    print
    print "".join(ch if ch in typed else "-" for ch in word)

    # Winning condition
    if typed.issuperset(word_letters):
        break

    # Data input
    x = raw_input("Enter a letter: ").upper()

    # Error cases
    if len(x) != 1:
        print "Invalid input."
        continue
    if x in typed:
        print "Already typed."
        continue
    if x not in ascii_uppercase:
        print "What you typed isn't a letter."
        continue

    # Valid data cases
    typed.add(x)
    if x in word:
        print "Good choice!"
    else:
        print "{} not found!".format(x),
        trial -= 1
        if trial == 1:
            print "You have one more chance!"
        elif trial > 1:
            print "You have {} more chances.".format(trial)
        else:
            print 'Sorry...'

# Ending message
print
if trial:
    print "YOU WIN!!"
else:
    print "GAME OVER!!"
  1. Hashbang: Your shebang should usually start with "#!/". You're probably using Windows, so the "bin" as a relative directory wasn't used by you.
  2. "l" / l as a variable name should be avoided! It might be seen as one or lower "L" (PEP8), or even a pipe "|". PS: At the beginning of this item, I typed the same letter here twice.
  3. There's no need to use "list" as a variable name here, and you shouldn't do, as that's a built-in name.
  4. Multiplication like "txt" * 3 returns "txttxttxt" (it repeats the data) for both strings and lists
  5. Neither "cls" nor "clear" worked here, showing

    "TERM environment variable not set."

    instead of clearing the console screen. I replaced these with an empty "print", and removed the time sleep. Look for subprocess if you want to call something from console (although I'd also look for curses if there's a need to do some CLI visualization).

  6. Suppose x is a string. When x == "", bool(x) is False, else bool(x) is True.
  7. Suppose x is an integer. When x == 0, bool(x) is False, else bool(x) is True.
  8. Avoid backticks (`). No one uses them today in Python, they doesn't exist in Python 3 and you can use the repr built-in instead. However, you probably wanted something like str(trial), "%d" % trial or "{}".format(trial).
  9. The last "press enter" probably has to do with an operating system "auto-close-after-finish" behaviour, but you [at least] didn't need to store it in x.
  10. I've used a generator expression. You should read here about list comprehensions if the "for" in the middle of one line is confusing for you. Python developers use generator expressions and list comprehensions all the time, you shouldn't avoid learning about them.
  11. I replaced the original winning evaluation to a comparison between the set of characters the word originally has and the set of typed characters (both uppercase).

If there's something here you didn't understand, please ask a new question.

H.D.
  • 4,168
  • 1
  • 18
  • 15
1

This SO question ought to cover it for you:

Finding multiple occurrences of a string within a string in Python

It should work just as well for individual characters as strings, considering how easy it is to form the second from the first.

Community
  • 1
  • 1
Mattsjo
  • 627
  • 5
  • 11
0

So in the end, I wound up doing it this way:

    if x in word and x!='':

        count=word.count(x)
        loc=0
        while count==1 or count>1:
            loc=word.find(x,loc)
            list[loc]=x
            loc+=1
            count-=1  
        print 'Good choice!'

Thanks for your help everyone. I definitely learned something.

Darkc0de
  • 53
  • 1
  • 5