To download Hangman.exe
click here.
This is my final project for the CS50P course at Harvard Online
You can find the final project instructions here
The original repository is here
The original certificate can be found here
Date format DD-MM-YYYY
🗓️ Version 1.0.1 - 26-01-2024 (commit 5208b7b)
Hangman.exe
has been added so now you can easily run the game on any machine !!!resource_path.py
inutils
folder is used to load images, fonts, sound and CSV files to allow it to work properly as an exe file.
game_screen.py
,hangman_game.py
,start_screen.py
,play_sound.py
andget_font.py
changed to take advantage ofresource_path.py
to make it passable to run as an exe file.
🗓️ Version 1.0.0 - 31-12-2023 (commit 993f36a) Happy new 2024 year 🎄🎇✨
is_letter_guessed()
added inproject.py
. The function is called byguess_letter()
inhangman_game.py
.
If the letter was guessed correctly, the function will return True, otherwise, the function will return False.make_restart_and_exit_clickable()
added inpygame.py
. It is called bygame_logic()
inhangman_game.py
.
This function ensures that the Exit and Restart buttons are clickable on the game screen. This helps to solve a bug.make_all_main_screen_button_unclickable()
added inproject.py
. The function is called byguess_letter()
inhangman_game.py
.
When the game screen starts, it makes all the buttons on the main screen unclickable. Otherwise, you can click on their rect on another screen.
button_clicked()
andget_button_instance()
moved to a new file calledutil_functions.py
inside theutils
folder.- Comments, docstring and type annotations were added all over the code.
- The dimensions of the buttons in
render_letter_buttons()
ingame_screen.py
are no longer defined by a specific number but a percentage, meaning now
the size of the buttons will look the same (proportionally) on all screen sizes.render_v_or_x_image()
changed accordingly.
🗓️ Version 0.9.9 release candidate - 28-12-2023 (commit a6e5516)
- In the
project.py
inif __name__ == "__main__"
a big change was made.- All the code that happens only once during the game initialization is now inside the
if __name__ == "__main__"
block.
Examples of this arepygame.init()
,pygame.display.set_caption
, screen initialization andpygame.quit()
This was done to make level restarts passable.
main()
is called to start a new level but all the things like pygame initialization and screen creation are done only once.
- All the code that happens only once during the game initialization is now inside the
- In
project.py
,get_button_instance()
returns the Button instance given the name of the button. - In
project.py
,exit_or_restart()
determines whether the user wants to exit the game or restart it based on the button clicked. - In
game_screen.py
,render_restart_button()
implemented. - In
hangman_game.py
, different sounds fromplay_sounds.py
(insounds
folder) are played usingpygame.mixer
at different events along the game. - In
update_the_hangman()
when the user fails 7 guesses, the game is over and the word is revealed using a for loop andword.guessed_letters_index[i] = True
.
- In
Word
class, when settingword.word
, the word is all uppercase using.upper()
. - In
start_screen.py
, when loading the buttons, the name of the buttons changed to work with the new picture files.
e.glevel 1.png
->easy.png
etc.
🗓️ Version 0.9.2 - 26-12-2023 (commit 3d8ccb6)
- In
game_screen.py
,render_the_hangman()
implemented.
It renders the hangman image on the screen. hangman_attempts
variable introduced. It may be found inhangman_game.py
as well asgame_screen.py
.
Its purpose is to count how many failed attempts the user had to guess the word. If more than 7 failed attempts are made, the game will end.guess_letter()
getshangman_attempts
, increases the count of failed attempts made, and returns the updated number.- If a guess was made, be it successful or not,
update_the_hangman()
will update the screen. try_guessing
indicated if a guess attempt happened or not.is_guessed
indicates if the guess attempt was successful or not.- If more the 7 failed attempts are made,
render_game_over()
will render GAME OVER! on the screen.
Also, it will make all the buttons, except the exit button, unclickable.
🗓️ Version 0.9.1 - 26-12-2023 (commit f98a664)
- In
game_screen.py
,put_v_or_x()
was implemented.
Every time we rerender the game screen, it puts the green V or red X on the buttons that were previously clicked, depending on whether the letter is in the word or not. - In
game_screen.py
,render_v_or_x_image()
was implemented.
It renders the green V or red X over the letter button after they were clicked, depending on whether the letter is in the word or not. - In
hangman_game.py
,get_button_instance()
was implemented. It returns the instance of a Button class based on the button name(this_button.name). - In
hangman_game.py
,guess_letter()
was reimplemented to useput_v_or_x()
.
- Button class changed
letter_button_clicked
: bool - If it is not a letter button then it will remain False for the whole duration.position
: tuple[int, int] - The position of the button on the screen (X, Y)
- In
game_screen.py
,word_cls
was changed toword
- In
game_screen.py
,render_alphabet_buttons()
andrender_letter_buttons()
merged in torender_letter_buttons()
. No functionality change.
- In
game_screen.py
,render_letter_buttons()
type annotations changed from-> tuple[Button]
to-> None
.
🗓️ Version 0.9.0 - 25-12-2023 (commit 3c5b924)
-
The hangman game functionality.
- Letter buttons are clickable.
- When the correct letter is guessed, the mask word will update and reveal the guessed word.
-
guess_letter()
was implemented insidehangman_game.py
.
It takes the guessed letter and checks if it is one of the letters of the word.
If it is,word.guessed_letters_index
is changed toTrue
in the corresponding index.
- In
start_screen.py
, what previously wasrender_screen()
was not changed torender_bg
to better represent its updated purpose. render_bg()
no longer returnsscreen
but instead takes ascreen
parameter.
This is becausescreen
is no longer created inside the function.- Masked word font size changed from
0.25
to0.1
percent of the screen.
It was done to suit better the new font. - In
hangman_game.py
,word_cls
changed toword
render_alphabet_buttons
ingame_screen.py
no longer returnsbutton[]
as it is no longer needed
- Screen flickering when re-rendering screen fixed
- It was caused by
screen = pygame.display.set_mode((0, 0), pygame.RESIZABLE)
being placed insiderender_start_screen()
instart_screen
, so the screen was created each time this function was called.
Nowscreen = pygame.display.set_mode((0, 0), pygame.RESIZABLE)
is called once at the start ofmain()
.
- It was caused by
🗓️ Version 0.2.5 - 25-12-2023 (commit 91293f4)
- The game loop of the game screen is now working as it should.
- The loop is located in
hangman_game.py
in thegame_logic
function. - The main game loop inside
main()
inproject.py
changed to work with the new game screen game loop. render_game_screen()
ingame_screen.py
now also returns the exit button (Button
class) to be later used int thegame_logic
insidehangman_game.py
.
button_clicked()
function inproject.py
was refactored to be more efficient- Filter out non-clickable buttons before the loop.
Iterates just over the clickable buttons usingclickable_buttons[]
list - Type annotation changed to -> str.
It was mistakenly set to -> int. mouse_click = pygame.mouse.get_pressed()
is out of the for loop, otherwise it would be called every time the loop iterates.
- Filter out non-clickable buttons before the loop.
🗓️ Version 0.2.0 - 24-12-2023 (commit ee4ce10)
- Game screen added in
game_screen.py
- The background and the exit button code imported from
start_screen.py
- The topic of the guessed word is displayed at the top of the screen
- The masked word is displayed at the center of the screen.
i.e ( _ _ _ _ _ ) - All the letters of the alphabet are displayed as buttons (
Button
class instances) in 2 rows, A-M and N-Z at the bottom of the screen (Not yet clickable)
- The background and the exit button code imported from
Word
class created- The class contains for following attributes:
word
(str) - The guessed wordtopic
(str) - The topic of the wordguessed_letters_index
(bool) - If a letter was guessed then its index will be True, otherwise it will be Falsemasked_word
(str) - The masked word i.e ( _ _ _ _ _ )
- Also, there is a property
get_masked_word
.
As its name implies, it returns the masked word str based on the values ofguessed_letter_index
.
- The class contains for following attributes:
button_clicked()
implemented insideproject.py
.
The function returns thebutton.name
of the button that was clicked.- game loop updated to include the game screen
hangman_game.py
added to include the game logic
pygame.display.flip()
changed topygame.display.update()
as it is more resource efficientmouse_pos = pygame.mouse.get_pos()
moved out of the for event loop for better computational resource efficiency
- button instance clickability now can be changed using getters and setters
my_button.clickable
. is_clickable()
property deleted as it is no longer needed thanks to the newclickable
attribute.
🗓️ Version 0.1.2.1 - 15-12-2023 (commit 99ad8ab)
- All start screen rendering functionality moved to
start_screen.py
.
render_start_screen()
is called from themain()
, and the rest is done inside the file itself. main()
made more readable thanks to the enhancement described above.
- Objects on the screen scale according to the device screen size and not a fixed number.
🗓️ Version 0.1.2 - 13-12-2023 (commit a08d2e3)
-
Button class created
- Depending on the current page, the button may be clickable or unclickable using
is_clickable()
boolean. - All the buttons have to be images
- You get and set the following attributes of the button:
top
left
bottom
right
collidepoint
position
x
y
width
hight
- Depending on the current page, the button may be clickable or unclickable using
-
all_button_instances[]
list added in project.py- When a button is created it is appended to the list.
it is done so you can access all the buttons in one place.
- When a button is created it is appended to the list.
-
The game exits when pressing Alt+F4 or by pressing the in-game X button or the ESC button on the keyboard.
- Button creating process changed to take advantage of the
Button
class- All the buttons are images saved in the
images
folder. - Initially, you load the image and then give it as input to the
Button
class to create a button instance of that image. Button
class also takes the dimensions of the button.- After the button instance is created it needs to be drawn using
.draw
method.
- All the buttons are images saved in the
mouse_when_over_button()
ingame_loop.py
refactored to take advantage of the newButton
class.
It made the code more readable and less prone to bugs when adding new buttons.
All you need to do is to ensure all the buttons are in theall_button_instances[]
list.- Method comments changed to a new format
🗓️ Version 0.1.1 - 10-12-2023 (commit 449a3ad)
- Type annotations added to
project.py
,game_loop.py
,start_screen.py
🗓️ Version 0.1.0 - 06-12-2023 (commit 556477f)
- Title added
- X exit button added
- X button functionality implemented
- Background image added
- The screen is set to fullscreen
- Level buttons added (not clickable yet)
- When mouse over a button, a hand courser appears