KeepYourChinUp
Badges: 17
Rep:
?
#1
Report Thread starter 5 years ago
#1
I've been programming as a hobby for a few months and wanted to share my first proper game. It's just hangman so nothing fancy and I decided to go with lives instead of adding limbs to the hangman figure, keeps it simpler.

It's python 3.4 so it won't work if your python interpreter is 2.x I've included a list of words for your convience as well. Just make sure to type the location of the words.txt for example C:\Users\Jake\Desktop/words.txt

Code:
import string
import random

class Hangman:

    #lives:     How many lives remaining.

    #word:      Word to be guess.

    #guesses:   True or false if the word is either guessed or not.

    #HiddenWord: List of guessed letters and the hidden letters are marked with an underscore.

    def __init__(self, word, lives):

        self._lives = lives
        self._hiddenWord = ['_ ' for i in word]
        self._word = word
        self._guesses = False

    def __str__(self):

        if self._hiddenWordString() == self._word:
            return "Word: {0}".format(self._word)
        else:
            return "Word: {0}; You have {1} lives left".format(
                    self._hiddenWordString(), self._lives)

    def livesRemaining(self):
        return self._lives

    #Returns the string representation of list hiddenWord.
    def _hiddenWordString(self):
        return "".join([ch for ch in self._hiddenWord])


    #Checks if the letter exists and updates the underscore to the letter.
    def updateGameStatus(self, char):
        if char in self._word:#Char is the letter typed in by the user.
            for i in range(len(self._word)):
                if self._word[i] == char:
                    self._hiddenWord[i] = char
        else:
            self._lives -= 1
        if self._word == self._hiddenWordString():
            self._guesses = True
        return self._word.count(char)


    def guesses(self):
        return self._guesses


def removeLineEndings(string):
    return string.replace('\n' if '\n' in string else '\n', '')


#Counts how many times a letter occurs in a word. Allows for nine of the same letters.
def charToString(num):
    return ['once', 'twice', 'three times', 'four times', 'five times',
             'six times', 'seven times', 'eight times', 'nine times'][num - 1]


def play(word, lives):
    #Main part of the game that deals with user input and output.
    hm = Hangman(word, lives)
    guessesLetters = []
    while hm.livesRemaining() > 0 and not hm.guesses():
        print(hm)
        ch = input('\nEnter a letter: ').upper()
        if ch in string.ascii_uppercase:
            if ch in guessesLetters:
                print('You have already entered the letter {0}\n'.format(ch))
            else:
                guessesLetters.append(ch)
                charCount = hm.updateGameStatus(ch)
                if charCount is 0:
                    print('The letter {0} does not occur in the word!'.format(ch))
                else:
                    print('The letter {0} occurs {1} in the word!'.format(ch,#For how many times it occurs
                        charToString(charCount)))
    if hm.guesses():
        print(hm, '\nWell done - you have guessed the word correctly')
    else:
        print('You have no lives left - you have been hung!')
        print('The word was', word)


#Selects a random word.
#User can choose which difficulty they want.
#After the game finishes it asks the user if they want to play again.
def main():
    fileName = input('Enter fileName: ')
    words = []
    try:
        f = open(fileName)
        words = [removeLineEndings(line.upper()) for line in f.readlines()]#Makes words uppercase
        f.close()
    except IOError:
        print('File does not exist!')
        main()
    while True:
        choice = None
        while choice == None:
            try:
                choice = int(input("""
                
Please select your difficulty.
[1] Easy         -   10 lives
[2] Intermediate -   7 lives
[3] Hard         -   5 lives
[4] Impossible   -   0 lives

> """))
                break
            except ValueError:
                print('\nInvalid input!')

        play(random.choice(words),#Picks random word from file
        (10, 7, 5, 1)[choice - 1])#10, 7, 5, 1 represent number of lives
        again = input('Another game? [Y|N]: ')
        if again in ('n', 'N'):
            print("\nThanks for playing!")
            exit(0)
main()
Comments and criticism welcome.
Attached files
0
reply
Push_More_Button
Badges: 10
Rep:
?
#2
Report 5 years ago
#2
(Original post by KeepYourChinUp)
Comments and criticism welcome.
I've just had a quick look at it (not attempted to run) but I have to say as you've only being learning programming for a few months you've done a great job on this.

Few small comments:
- Being really picky on style: Looks like you've read PEP8 but there are a few places where your lines are too long (12, 58, 78, 80, 97) and your naming convention isn't right. There's one or two places where you're indentation on linebreaks isn't clean (line 119 play() for instance), as well as some spacing between comments to make them a bit more readable.

- You'd probably benefit from getting into the habit of putting your comments as doc strings ready for when you're building larger applications.

- Rather than calling main() when you run the Python file it should be like the following:
Code:
if __name__ == "__main__":
    main()
This means you can import your file (and use your hangman class) elsewhere - like if you decided to move your game onto the web, etc.

- The method removeLineEndings() would be better replaced with rstrip() as it's cross-platform. (And it's currently clashing with the string module you've imported.

All in all, great job.


(Original post by Async)
Python has to be the most ugliest programming language.
a) Not helpful.
b) Wrong. It uses plain English and favours simplicity and readability, both rather beautiful concepts in a programming language.

I'm rather interested in your programming experience if Python is the most ugliest language [you've come across]...
2
reply
Async
Badges: 19
Rep:
?
#3
Report 5 years ago
#3
(Original post by Push_More_Button)
a) Not helpful.
b) Wrong. It uses plain English and favours simplicity and readability, both rather beautiful concepts in a programming language.

I'm rather interested in your programming experience if Python is the most ugliest language [you've come across]...
By ugly I mean the syntax. The syntax looks ugly. It just looks horrifying to me. The way they name their variables & methods is just so urgh.
0
reply
Push_More_Button
Badges: 10
Rep:
?
#4
Report 5 years ago
#4
(Original post by Async)
By ugly I mean the syntax. The syntax looks ugly. It just looks horrifying to me. The way they name their variables & methods is just so urgh.
But the naming convention has nothing to do with the syntax, that's purely stylistic and ultimately you can choose to name your variables whatever you like.
0
reply
KeepYourChinUp
Badges: 17
Rep:
?
#5
Report Thread starter 5 years ago
#5
(Original post by Push_More_Button)
...
Thanks for the comments. I'll take some of the stuff you suggested on board. The indentation you mentioned is fine, if you look it is under the while True: block and is needed for the code to loop.
0
reply
Push_More_Button
Badges: 10
Rep:
?
#6
Report 5 years ago
#6
(Original post by KeepYourChinUp)
The indentation you mentioned is fine, if you look it is under the while True: block and is needed for the code to loop.
Yes it works fine, but for readabilities sake it's often better to indent your second line further so it's immediately obvious it's an argument and not another statement.

Compare your original:
Code:
play(random.choice(words),#Picks random word from file
(10, 7, 5, 1)[choice - 1])#10, 7, 5, 1 represent number of lives
To this:
Code:
play(random.choice(words), #Picks random word from file
    (10, 7, 5, 1)[choice - 1]) #10, 7, 5, 1 represent number of lives
I initially didn't spot the comma at the end of the first line so wondered what the second line is doing, but with a bit of spacing and indenting it's a little less cluttered.

Obviously it doesn't alter functionality in any way, I'm just really picky of style after recently going through a few thousand lines of someone elses code that wasn't properly formatted so was a little difficult and time consuming to read.

As I said before, it looks pretty solid, well done.
0
reply
elohssa
Badges: 3
Rep:
?
#7
Report 5 years ago
#7
125 lines of code for hangman is pretty good; it shows you're being lazy (which is good) and reusing code. I've never done hangman but I wrote a Sudoku solver in <200 lines of c++. I'm wanting to do a chess AI sometime (would probs look good on CV), but finding the motivation + time is hard (unlike Sudoku, chess would take at least a whole weekend). You planning on doing any other games/projects?
0
reply
KeepYourChinUp
Badges: 17
Rep:
?
#8
Report Thread starter 5 years ago
#8
(Original post by elohssa)
125 lines of code for hangman is pretty good; it shows you're being lazy (which is good) and reusing code. I've never done hangman but I wrote a Sudoku solver in <200 lines of c++. I'm wanting to do a chess AI sometime (would probs look good on CV), but finding the motivation + time is hard (unlike Sudoku, chess would take at least a whole weekend). You planning on doing any other games/projects?
A chess AI is way out of my ability at the moment. I downloaded the Houdini and Stockfish engines which are coded in C++ and had a quick look, pretty intense stuff and definitely too complex, I still have much to learn. chess engines also rely heavily on algorithms which I've yet to dive into.

I doubt Python would be very good for a chess engine anyway, where speed is critical.
0
reply
elohssa
Badges: 3
Rep:
?
#9
Report 5 years ago
#9
(Original post by KeepYourChinUp)
A chess AI is way out of my ability at the moment. I downloaded the Houdini and Stockfish engines which are coded in C++ and had a quick look, pretty intense stuff and definitely too complex, I still have much to learn. chess engines also rely heavily on algorithms which I've yet to dive into.

I doubt Python would be very good for a chess engine anyway, where speed is critical.
I'm more interested in doing it as a proof on concept rather then trying to make it competitive against proper engines. I often like to do something without any research, then later look how far my algorithms/logic differed from what was eventually found optimal by other people after years of research.
0
reply
Push_More_Button
Badges: 10
Rep:
?
#10
Report 5 years ago
#10
(Original post by KeepYourChinUp)
I doubt Python would be very good for a chess engine anyway, where speed is critical.
Python's quicker than you think...
0
reply
KeepYourChinUp
Badges: 17
Rep:
?
#11
Report Thread starter 5 years ago
#11
(Original post by Push_More_Button)
Python's quicker than you think...
C++ is actually about 100x faster than Python and up to 400x times faster at data sorting. Python is great and very robust and quick for most things but when you're crunching millions of combinations C++ wins hands down. You can test it for yourself with a factorial example. Make one in C++ and one in Python and compare the speed difference with a sufficiently large number.
0
reply
Planto
Badges: 16
Rep:
?
#12
Report 5 years ago
#12
(Original post by KeepYourChinUp)
C++ is actually about 100x faster than Python and up to 400x times faster at data sorting.
This is nonsense.

To be clear - I don't just mean it's incorrect, I mean it's nonsense. Meaningless.

What is wild assertion based on?
0
reply
KeepYourChinUp
Badges: 17
Rep:
?
#13
Report Thread starter 5 years ago
#13
(Original post by Planto)
This is nonsense.

To be clear - I don't just mean it's incorrect, I mean it's nonsense. Meaningless.

What is wild assertion based on?
http://benchmarksgame.alioth.debian....=gpp&data=u32q

They show that Python is up to about 400 times slower than C++ and with the exception of a single case, Python is more of a memory hog. There are many reasons for this, the major ones being: a) Python is interpreted, while C++ is compiled; b) Python has no primitives, everything including the built in types (int, float, etc.) are objects; c) a Python list can hold objects of different type, so each entry has to store additional data about its type. These all severely hinder both runtime and memory consumption.

Just one that jumped out at me was binary trees

Python - 139.26 seconds
C++ - 5.05 seconds.

I'd ask for a refund on your degree, don't computer science students usually learn this sort of stuff in year 1?
0
reply
Planto
Badges: 16
Rep:
?
#14
Report 5 years ago
#14
(Original post by KeepYourChinUp)
They show that Python is up to about 400 times slower than C++ and with the exception of a single case, Python is more of a memory hog.
"Faster" and "slower" as absolute terms are ambiguous to the point of meaninglessness in the context of programming languages. What these tests show is the difference between those implementations of those algorithms on those runtimes on those platforms on those machines.

C++ itself can run on countless different runtimes - what you must remember is that a programming language is just a specification of behaviour; implementation is everything.

Nobody is disputing that C++ in general is more optimized for low-level computation than Python but drawing direct comparisons between programming languages is almost impossible because there is rarely a clear mapping between equivalent operations and saying one language is "faster" than another (and even producing a ridiculous magic number) is a gross oversimplification.

There are many reasons for this, the major ones being: a) Python is interpreted, while C++ is compiled; b) Python has no primitives, everything including the built in types (int, float, etc.) are objects; c) a Python list can hold objects of different type, so each entry has to store additional data about its type. These all severely hinder both runtime and memory consumption.
None of these things inherently "severely hinder runtime and memory consumption" and I think your understanding of the implications of dynamic typing is a little confused.

But I'm just a professional software engineer, so what do I know? You know better with your "couple of months" worth of programming experience, I'm sure.
1
reply
KeepYourChinUp
Badges: 17
Rep:
?
#15
Report Thread starter 5 years ago
#15
(Original post by Planto)
...
The figures speak for themselves... C++ is clearly faster in each of those tests and I'm assuming those tests are designed to measure computational / algorithmic speed. Obviously you could be biased and make the Python program elegant and compact and make the C++ program sloppy which could lead to Python being faster in that specific instance but these test programs are obviously coded to the exact same equality otherwise the test data would be, as you say, meaningless.
0
reply
Planto
Badges: 16
Rep:
?
#16
Report 5 years ago
#16
(Original post by KeepYourChinUp)
The figures speak for themselves... C++ is clearly faster in each of those tests and I'm assuming those tests are designed to measure computational / algorithmic speed. Obviously you could be biased and make the Python program elegant and compact an make the C++ program sloppy which could lead to Python being faster in that specific instance but these test programs are obviously coded to the exact same equality otherwise the test data would be, as you say, meaningless.
Yes, they speak for themselves. And not much else. That is the point: there is no well defined concept of what constitutes "faster" or "slower" and there is certainly no canonical measure of the magnitude of those differences. Any test or assertion of either is only valid in the scope of itself.

To make a claim that "x is y times faster than z" you need a number of well established premises that you don't have.

A valid metric

There is no well-defined metric that will give you a valid and consistent comparison between two programming languages. How do you measure the relative speed of two programming languages over a particular algorithm, as the size of the input scales?

If C++ takes 5 units of time to perform algorithm A over an input size of 100 and Python takes 200 units of time, but at an input size of 100,000 C++ takes 1000 units of time and Python takes 1300, how many times slower than C++ is Python? 40 or 1.3?

No comparison you can draw up will scale proportionally, no metric you can define will be complete and no test you can run will be isolated.

A well defined equivalence

Even if you could define a metric, you cannot produce a valid claim that two implementations are performing the same computation.

At what level of abstraction do you define two implementations equivalent? Go low enough and they will always be different so the test will always be invalid. How do you decide what built in types are equivalent? A Python list is not the same as a C++ list in a different language, they are functionally different - if you try and draw direct comparisons, you are actually measuring two different tests.

Even if you could define an equivalence between built-in operations, how do you do so between implementations that aren't built in? What if it's built in in one language? What defines what constitutes an equivalent implementation in the other? And what about I-O, concurrency, asynchrony... the factors to be considered in determining a valid comparison are endless and are contextually sensitive. What are you measuring?

This is not even scratching the surface of the problem - I could write for days on end - but I hope it will start to demonstrate the problem; you cannot compare speed without first defining speed and "speed" is impossible to define except in a very constrained scope (so constrained that it would not be meaningful in any practical scenario).

I am not arguing that saying "C++ is 400x faster than Python" is wrong, I am arguing quite literally that - as a sentence - it doesn't actually mean anything. Hence my original statement; "this is nonsense."

Certainly, if you had suggested that C++ provides you with a better toolset for creating performance-optimised code in the context of low-level computation, nobody would have contested it (and really, if anything, that is all that is supported by your link). But you didn't.
0
reply
Push_More_Button
Badges: 10
Rep:
?
#17
Report 5 years ago
#17
(Original post by KeepYourChinUp)
I'd ask for a refund on your degree, don't computer science students usually learn this sort of stuff in year 1?
Wow. Why so aggressive?

All I said is Python is faster than you think, i.e. it would be capable of creating a chess engine.

Fair enough, you've found some benchmarks that prove C++ is faster than Python (which I wasn't denying...), but does that really matter? No.

The only statistics you need to be worried about are those concerning your production systems in the real world. Who cares if C++ is 400x faster than Python if Python is fast enough?
0
reply
KeepYourChinUp
Badges: 17
Rep:
?
#18
Report Thread starter 5 years ago
#18
(Original post by Push_More_Button)
Wow. Why so aggressive?

All I said is Python is faster than you think, i.e. it would be capable of creating a chess engine.

Fair enough, you've found some benchmarks that prove C++ is faster than Python (which I wasn't denying...), but does that really matter? No.

The only statistics you need to be worried about are those concerning your production systems in the real world. Who cares if C++ is 400x faster than Python if Python is fast enough?
Yeah I know, my response to you was civil? The sarcasm was directed at Planto.
0
reply
mos182
Badges: 6
Rep:
?
#19
Report 5 years ago
#19
Yes it is well known that C++ is one of the fastest programming languages but it's down to personal preferences. If a programmer (especially a relatively new one) doesn't like C++ and prefers python, then let them code in python.

Back on topic. I must say that to create a python hangman game from only a couple of months of programming is definitely a great achievement. A lot of people don't have the patience to start a project and see it through so congrats on building this
0
reply
X

Quick Reply

Attached files
Write a reply...
Reply
new posts
Back
to top
Latest
My Feed

See more of what you like on
The Student Room

You can personalise what you see on TSR. Tell us a little about yourself to get started.

Personalise

Current uni students - are you thinking of dropping out of university?

Yes, I'm seriously considering dropping out (66)
14.54%
I'm not sure (16)
3.52%
No, I'm going to stick it out for now (153)
33.7%
I have already dropped out (8)
1.76%
I'm not a current university student (211)
46.48%

Watched Threads

View All
Latest
My Feed