Hangman (first full project)

This is the place to post any code that you want to share with the community. Only completed scripts should be posted here.

Hangman (first full project)

Postby Scherf » Thu May 01, 2014 4:51 am

I finished a basic hangman game late last year, and built off of it.
I ended up adding in word management (never got around to adding in ability to check if words are in the dictionary sadly), and leaderboards!

This was my first project, so the code is really not so great. The initial product was very sloppy, and when I wanted to add more onto it I had to make due with what I had already made. So, lots of global variables, poor function structure and general messiness. But it works, and thats what I care most about.

The game reads words and hiscores information from lists (Short.txt , Medium.txt, and Long.txt) all of which can be edited manually of with the in-game

Bash my work, praise it, do whatever, I'd just like to hear some opinions on it!!

Code: Select all
#Hangman
import random
import timeit
from sys import argv

print "\n  Hangman - Josh Scherf 3.31.14\n"
default = timeit.default_timer()

print "  Select Mode:"
print "  1. Play"
print "  2. Leaderboard"
print "  3. Word Manager"
print "  4. Quit"

rt, hs2, sths, hs, wm, wmg1, wmg2, upd, t, li, ni = (0, )*11
ws, ns, flt = (1, )*3
tried = [' ']
pndlist = []

def modeCheck():
   global w
   global hs2
   global wcd
   print "\n  Select Difficulty:"
   print "  1. Easy" 
   print "  2. Medium"
   print "  3. Hard"
   Diff1  = raw_input('  >').lower()
   if Diff1 == '1':
      w = open('easy.txt', 'a+')
      wcd = 'Easy'
   elif Diff1 == '2':
      w = open('medium.txt', 'a+')
      wcd = 'Medium'
   elif Diff1 == '3':
      w = open('hard.txt.', 'a+')
      wcd = 'Hard'
   else:
      print "  Input error: Invalid input"
      modeCheck()
   if sths or hs2:
      choice()
   elif wmg2:
      choice()
   
def select():
   global hs, mode, wm
   mode = raw_input('  >').lower()
   if mode == '1':
      hs = 0
   elif mode == '2':   
      hs = 1
   elif mode == '3':
      wm = 1
   elif mode == '4':
      print "\n  Terminating.\n"
      exit()
   else:
      print "  Input error: Invalid input"
      select()

select()
modeCheck()

def scores():
   global di
   l1 = list_words
   l2 = list_scores
   l3 = list_names
   l4 = []
   fls = float(list_scores[wi])
   if not upd:
      if t < fls:
         di = li - t
         print "  You beat %s's highscore of %r seconds by %r seconds!" % ( ni, li, di )
         print"\n  Enter your name:"
         nmi = raw_input('  >').lower()
         list_scores[wi] = str(t)
         list_names[wi] = nmi
   for i in l1:
      index = l1.index(i)
      i1 = l1[index]
      i2 = l2[index]
      i3 = l3[index]
      l4.append(i1)
      l4.append(i2)
      l4.append(i3)
   for i,x in enumerate(l4):
      if not '\n' in x:
         l4[i] = x+'\n'
   #begin file overwrite
   w.seek(0)
   w.truncate()
   for i in l4:
      w.write(i)
   if upd:
      print "\n  Changes applied."
      print "  Terminating.\n"
      exit()
   else:   
      ext()

def choice():
   global raw_list, list_words, list_names, list_scores, word, wi, wmg2
   #parse new words into list
   raw_list = w.readlines()
   list_words = [ x for i,x in enumerate(raw_list) if i % 3 == 0 ]
   #set up random choice of word
   word = random.choice(list_words)
   wi = list_words.index(word)
   #remove new line escape from end of list      
   word = word[:-1]
   list_names = [ x for i,x in enumerate(raw_list) if (i-2) % 3 == 0 ]
   list_names = [ x[:-1] for i,x in enumerate(list_names)]
   ni = list_names[wi]
   list_scores = [ x for i,x in enumerate(raw_list) if (i-1) % 3 == 0 ]
   list_scores = [ x[:-1] for i,x in enumerate(list_scores)]
   li = float(list_scores[wi])
   li = round(li, 3)
   li = float(li)
   if hs:
      highScores(list_scores)
   elif wm or wmg2:
      wordManager()
      wmg2 = 0
   
def wordManager():
   global pndlist, list_words, wmg1, wmg2, wcd
   print "\n  [-- Word Management --]  \n"
   print "  Current List: ", wcd, '\n'
   if not wmg1:
      list_words = [ i[:-1] for i in list_words ]
      wmg1 = 1
   for i,x in enumerate(list_words):
      if i % 3 == 0 and i > 1:
         li3 = len(list_words[i-3])
         li2 = len(list_words[i-2])
         if wcd == 'Easy':
            print ' ', list_words[i-3], ' '*(7-li3), list_words[i-2], ' '*(7-li2),  list_words[i-1]
         elif wcd == 'Medium':
            print ' ', list_words[i-3], ' '*(10-li3), list_words[i-2], ' '*(10-li2),  list_words[i-1]
         elif wcd == 'Hard':
            print ' ', list_words[i-3], ' '*(15-li3), list_words[i-2], ' '*(15-li2),  list_words[i-1]
   print "\n  Pending Changes:"
   for i,x in enumerate(pndlist):
      print "     " + x
   if len(pndlist) < 1:
      print "     None"
   print "\n  1. Change Lists"
   print "  2. Reset a score"
   print "  3. Change a word"
   print "  4. Save and exit"
   print "  5. Exit without saving."
   wmg = raw_input('  >').lower()
   if wmg == '1':
      if len(pndlist) > 0:
         print "  You have pending changes and cannot change lists until you save them."
         wordManager()
      wmg2 = 1
      wmg1 = 0
      modeCheck()
   elif wmg == '2':
      print "\n  Enter a word:"
      userw = raw_input('  >').lower()
      wmgli = -1
      for i,x in enumerate(list_words):
         if userw == x:
            wmgli = i
      if wmgli < 0:
         print "\n  Input Error: Invalid input."
         wordManager()
      wmgli2 = list_words[wmgli]
      wmgsi = list_scores[wmgli]
      wmgni = list_names[wmgli]
      print "  The current score for %s is %r by %s." % ( wmgli2, wmgsi, wmgni )
      print "  Are you sure you wish to reset this score?"
      print "  1. Yes"
      print "  2. No"
      sel = raw_input('  >').lower()
      if sel == '1':
         list_names[wmgli] = 'Josh Scherf'
         list_scores[wmgli] = '100'
         wmgsi = list_scores[wmgli]
         wmgni = list_names[wmgli]
         wmgtba = "-Reset score for %s" % userw
         pndlist.insert(0, wmgtba)
         wordManager()
      elif sel == '2':
         wordManager()
      else:
         print "  Input Error: Invalid input"
         wordManager()
      exit()
   elif wmg == '3':
      global upd
      print "  Enter a word to be replaced:"
      wrp = raw_input('  >').lower()
      wmgck = 0
      for i,x in enumerate(list_words):
         if wrp == x:
            wrpli = i
            wrpw = x
            wmgck = 1
      if not wmgck:
         print "  Input Error: Word does not exist in list %s" % wcd
         wordManager()
      print "  Enter a word to replace %s:" % wrpw
      wrp2 = raw_input('  >').lower()
      wrp2 = wrp2.lower()
      #Add in word verification here...
      for i,x in enumerate(wrp2):
         if not x.isalpha():
            print "  Input Error: Invalid input."
            wordManager()
      if wcd == 'Easy' and not 3 <= len(wrp2) <= 5:
         print "  Input Error: Word length must be 3-5 characters for list %s." % wcd
         wordManager()
      elif wcd == 'Medium' and not 8 <= len(wrp2) <= 9:
         print "  Input Error: Word length must be 8-9 characters for list %s." % wcd
         wordManager()
      elif wcd == 'Hard' and not 10 <= len(wrp2) <= 17:
         print "  Input Error: Word length must be 10-17 characters for list %s." % wcd
         wordManager()
      print "  Replacing this word will reset the score."
      print "  The current score for %s is %r by %s."  % ( wrpw, list_scores[wrpli], list_names[wrpli] )
      print "  Are you sure you wish to continue?\n"
      print "  1. Yes"
      print "  2. No"
      wrpchk = raw_input('  >').lower()
      if wrpchk == '1':
         list_scores[wrpli] = '100'
         list_names[wrpli] =  'Josh Scherf'
         list_words[wrpli] = wrp2
         wmgtba = '-Replace %s with %s' % ( wrpw, wrp2 )
         pndlist.insert(0, wmgtba)
         wordManager()
      elif wrpchk == "2":
         wordManager()
      else:
         print " Input Error: Invalid input."
         wordManager()
   elif wmg == '4':
      if len(pndlist) < 1:
         print "\n  No changes queued."
         print "  Terminating.\n"
         quit()
      else:
         print "  Are you sure you wish to continue?"
         print "  1. Yes"
         print "  2. No"
         conf = raw_input("  >")
         if conf == "1":
            upd = 1
            scores()
         elif conf == "2":
            wordManager()
         else:
            print "Input Error: Invalid input"
            wordManager()
      print "The following changes are about to be applied:"
      for i,x in enumerate(pndlist):
         print x
   elif wmg == '5':
      print "\n  No changes will be applied."
      print "  Terminating.\n"
      exit()
   else:
      print " Input Error: Invalid input."
      wordManager()

def highScores(list_scores):
   global hs2, list_words, rt, ws, list2, ns, list_names, flt
   sths = 1
   list_scores2 = [float(x) for x in list_scores]
   list_scores2.sort()
   print "\n  [-- High score lookup --]"
   print "\n  Difficulty: ", wcd
   print "\n  1. Word Search"
   print "  2. Name Search"
   print "  3. Fastest Times"
   print "  4. Change Difficulty"
   print "  5. Exit"
   hsm = raw_input('  >').low er()
   if ws:
      list2 = [ i[:-1] for i in list_words ]
      ws = 0
   if hsm == '1':
      print "\n  Enter word (lowercase):"
      search = raw_input('  >').lower()
      print "\n  [-- Fastest Time --]\n"
      for i,x in enumerate(list2):
         if search in x:
            lni = list_words[i]
            print "  %s - %r seconds by %s" % ( lni[:-1], float(list_scores[i]), list_names[i] )
      highScores(list_scores)
   elif hsm == '2':
      if flt :
         for i,x in enumerate(list_scores):
            list_scores[i] = float(x)
            flt = 0
      list_scores, list_words, list_names = zip(*sorted(zip(list_scores, list_words, list_names)))
      search2 = raw_input('  >').lower()
      if ns:
         ns = 0
      print "\n  [-- Fastest Times - %s --]\n" % wcd
      print "  *reload script to update*\n"
      for i,x in enumerate(list_scores):
         if search2 in list_names[i]:
            lwi = list_words[i]
            print "  %r - %r seconds by %r" % ( lwi[:-1], x, list_names[i] )
      highScores(list_scores)
   elif hsm == '3':
      hsc = 0
      print "\n  [-- Fastest Times - %s --]\n" % wcd
      print "  *reload script to update*\n"
      for i,x in enumerate(list_scores2):
         lst = list_words[i]
         print "  %s - %r seconds by %s" % ( lst[:-1], x, list_names[i] )
         hsc += 1
         if hsc >= 10:
            highScores(list_scores)
   elif hsm == '4':
      hs2 = 1
      ws = 1
      modeCheck()
   elif hsm == '5':
      print "\n  Terminating.\n"
      exit()
   else:
      print "  Input error: Invalid input"
      highScores(list_scores)
print "  Runnning choice"
choice()
time1 = timeit.default_timer()
begin = round(time1, 3)

#define guesses
if len(word) < 5:
   attempts = 7
else:
   attempts = len(word) + 2

count = 0

#set up display word
display = len(word) * "-"
d = []
for c in display:
   d.append(c)
d2 = ''.join(d)

print "\n  Word length: %r" % len(d2)
print "  Guesses remaining: %r" % attempts
print "  " + d2

list_names = [ x for i,x in enumerate(raw_list) if (i-2) % 3 == 0 ]
list_names = [ x[:-1] for i,x in enumerate(list_names)]
ni = list_names[wi]
list_scores = [ x for i,x in enumerate(raw_list) if (i-1) % 3 == 0 ]
list_scores = [ x[:-1] for i,x in enumerate(list_scores)]
li = float(list_scores[wi])
li = round(li, 3)
li = float(li)
   
#set up input location for new array contents
def start():
   if d2 == word:
      win()
   elif count >= attempts:
      fail()
   else:
      global input
      input = raw_input("  >")
      if len(input) != 1 or not input.isalpha():
         print "\n  Input error: Invalid input.\n"
         start()
      print "\n"
      guess()

def guess():
   global d2, count, input, tried
   g = 0
   input = input.lower()
   for i in tried:
      if i == input:
         print "  That letter has been guessed already"
         print "  Please guess another character.\n"
         start()
   tried.insert(1, input)
   #print tried
   for i, c in enumerate(word):
      if c == input:
         d.pop(i)
         d.insert(i, c)
         g = 1
   if g == 0:
      count += 1
   d2 = ''.join(d)
   print "  " + d2
   print "  Guesses remaining: %r" % (attempts - count)
   start()   
   
def fail():
    global stop
   print "\n  You failed to solve the word %s in %d guesses." % (word, attempts)
   ext()
   
def win():
   global t
   print "\n  You won!"
   time2 = timeit.default_timer()
   stop = round(time2, 3)
   t =  float(stop - begin)
    print "  You solved the word %s in %s seconds!" % (word, t)
   scores()
   
def ext():
   global di
   fsi = list_scores[wi]
   fsi = int(fsi)
   print "  The fastest time for %s is %d seconds by %s." % ( word, fsi, list_names[wi] )
   print "\n  Press UP then ENTER to play again. (PowerShell) \n"
   exit()

start()   


The game requires the following lists:


NOTE: I have only tested this on Windows, python 2.7.x
Last edited by metulburr on Thu May 01, 2014 5:13 am, edited 1 time in total.
Reason: locked
Scherf
 
Posts: 6
Joined: Thu May 01, 2014 3:19 am

Re: Hangman (first full project)

Postby metulburr » Thu May 01, 2014 5:03 am

1)
Code: Select all
rt, hs2, sths, hs, wm, wmg1, wmg2, upd, t, li, ni = (0, )*11

its common convention to make meaningful names

2)
Code: Select all
   global raw_list, list_words, list_names, list_scores, word, wi, wmg2

Making use of classes would clean up the code a lot, plus a benefit of ditching the globals.

3)
Code: Select all
def modeCheck():
   ...
   if Diff1 == '1':
      w = open('easy.txt', 'a+')

common convention is also 4 spaces, not 3

4) The code looks like spaghetti code. Not that im bashing you, mine looked the same the first few projects. There are magic numbers all over the place. you have code between function defintions. Logic mixed with UI. etc.

5) Creating a repo for projects is a lot easier on the reader/gamer side. Though a large learning curve at first, it is also beneficial to the programmer although you wont see it at first. Read this. I didnt run your game because i didnt want to set up 4 different files, etc. However i would of downloaded it from githuib and ran it if one existed.
New Users, Read This
OS Ubuntu 14.04, Arch Linux, Gentoo, Windows 7/8
https://github.com/metulburr
steam
User avatar
metulburr
 
Posts: 1476
Joined: Thu Feb 07, 2013 4:47 pm
Location: Elmira, NY

Re: Hangman (first full project)

Postby Scherf » Thu May 01, 2014 5:52 am

I agree, it is spaghetti! But that's ok.

I'm aware of 1) and 2) Like I said, I started off very poorly (didn't know how to properly use classes) and just built off of it because I was too lazy to restructure.
I never intended for this to be viewed by anyone (sorry) so the variables are just abbreviations of things that I can easily remember.

As for the spacing, do you mean indentation? I use notepad++ and use the default tab indent size

I will try to get it on git ASAP
Scherf
 
Posts: 6
Joined: Thu May 01, 2014 3:19 am

Re: Hangman (first full project)

Postby Scherf » Thu May 01, 2014 3:19 pm

Here is the repo link, I hope I did this correctly.

https://github.com/Skerf/python-hangman-14/
Scherf
 
Posts: 6
Joined: Thu May 01, 2014 3:19 am

Re: Hangman (first full project)

Postby Jiten » Fri Aug 22, 2014 5:41 am

Your script in this scenerio throwing exception.

Hangman - Josh Scherf 3.31.14

Select Mode:
1. Play
2. Leaderboard
3. Word Manager
4. Quit
>1

Select Difficulty:
1. Short
2. Medium
3. Long
>1
Runnning choice

Word length: 4
Guesses remaining: 7
----
>a


-a--
Guesses remaining: 7
>s


-a--
Guesses remaining: 6
>f


-a--
Guesses remaining: 5
>g


-a--
Guesses remaining: 4
>e


-a--
Guesses remaining: 3
>t


-a--
Guesses remaining: 2
>q


-a--
Guesses remaining: 1
>c


-a--
Guesses remaining: 0

You failed to solve the word ball in 7 guesses.

Traceback (most recent call last):
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 425, in <module>
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 378, in start
guess()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 401, in guess
start()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 370, in start
fail()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 406, in fail
ext()
File "C:\Python27\Jiten\python-hangman-14-master\hangman.py", line 420, in ext
fsi = int(fsi)
ValueError: invalid literal for int() with base 10: '3.2'
Last edited by micseydel on Mon Aug 25, 2014 5:48 am, edited 1 time in total.
Reason: First post lock.
Jiten
 
Posts: 2
Joined: Fri Aug 22, 2014 5:18 am


Return to Completed Scripts

Who is online

Users browsing this forum: Bing [Bot] and 0 guests

cron