├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature-request.md ├── .gitignore ├── Games ├── .gitignore ├── General Quiz Game │ ├── README.md │ ├── quiz.py │ └── requirements.txt ├── README_template.md ├── auction │ ├── README.md │ ├── ascii_art.py │ └── auction.py ├── black_jack │ ├── README.md │ └── main.py ├── board_filling_game │ ├── README.md │ └── board_filling_game.py ├── checkers │ ├── README.md │ └── checkers.py ├── chin_chiro │ ├── README.md │ ├── chin_chiro.py │ ├── src │ │ ├── dice.py │ │ ├── game.py │ │ ├── logic.py │ │ └── player.py │ └── tests │ │ ├── __pycache__ │ │ ├── test_dice.cpython-312.pyc │ │ ├── test_logic.cpython-312.pyc │ │ └── test_player.cpython-312.pyc │ │ ├── test_dice.py │ │ ├── test_logic.py │ │ └── test_player.py ├── comp_sci_quiz │ ├── README.md │ ├── data.py │ ├── images │ │ ├── false.png │ │ └── true.png │ ├── main.py │ ├── question_model.py │ ├── quiz_brain.py │ └── ui.py ├── etch_a_sketch │ ├── README.md │ └── etch_a_sketch.py ├── gambler │ ├── README.md │ └── gambler.py ├── guess_the_number │ ├── README.md │ └── guess_the_num.py ├── hangman │ ├── README.md │ ├── asciiart.py │ └── hangman.py ├── ludo_king │ ├── ludo-king.py │ └── readme.md ├── memory_game │ ├── README.md │ └── memory-game.py ├── minesweeper │ ├── README.md │ └── minesweeper.py ├── pizza_palour │ ├── README.md │ ├── main.py │ ├── requirements.txt │ └── streamlit_main.py ├── pong │ ├── README.md │ ├── ball.py │ ├── bounce.wav │ ├── main.py │ ├── paddle.py │ └── score.py ├── road_crossing │ ├── README.md │ ├── animal.py │ ├── cars.py │ ├── level.py │ └── main.py ├── rock_paper_scissors │ ├── README.md │ └── rock_paper_scissors.py ├── slot_machine │ ├── README.md │ └── slot_machine.py ├── snake_game │ ├── README.md │ ├── constants.py │ ├── die.wav │ ├── eat.wav │ └── game.py ├── state_guessing │ ├── 50_states.csv │ ├── README.md │ ├── blank_states_img.gif │ ├── display.py │ └── main.py ├── tic_tac_toe │ ├── README.md │ └── tic_tac_toe.py ├── treasure_Island │ ├── README.md │ └── main.py └── turtle_racing_bet │ ├── README.md │ └── turtle_racing_bet.py ├── LICENSE ├── README.md ├── Tools ├── .gitignore ├── AutoWiFiCheck │ ├── README.md │ └── wifi_checker.py ├── Image encoding and decoding │ ├── README.md │ └── image_encoding_and_decoding.py ├── Image_resizer │ └── image_resize.py ├── NATO_alphabet_translator │ ├── README.md │ ├── nato_phonetic_alphabet.csv │ └── translator.py ├── Password_strength_checker │ └── main.py ├── README_template.md ├── bluetooth_scanner │ ├── README.md │ └── bluetooth_scanner.py ├── calculator │ ├── README.md │ └── calc.py ├── cookie_macro │ ├── README.md │ └── main.py ├── custom_password_generator │ └── custom_password_generator.py ├── distance_calculator │ ├── README.md │ └── main.py ├── encoding │ └── encode.py ├── kanye_says │ ├── README.md │ ├── Screenshot.png │ ├── background.png │ ├── kanye.png │ └── main.py ├── merge_pdf │ ├── README.md │ └── merge_pdf.py ├── pomodoro_timer │ ├── README.md │ ├── main.py │ ├── screen_shot.png │ └── tomato.png ├── qrcode_gen │ ├── README.md │ └── main.py ├── remove_duplicates │ ├── README.md │ ├── main.py │ └── main_gui.py ├── text_summarizer │ ├── README.md │ └── main.py └── tip_calculator │ ├── README.md │ └── main.py └── images ├── fork.png ├── logo.png ├── mainLogo.jpg ├── main_logo.JPG └── tools_logo.png /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "\U0001F41C [Bug] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Additional context** 17 | Add any other context about the problem here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "\U0001F30A [Feature] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv__pycache__/ 2 | .idea/ 3 | -------------------------------------------------------------------------------- /Games/.gitignore: -------------------------------------------------------------------------------- 1 | */__pycache__ -------------------------------------------------------------------------------- /Games/General Quiz Game/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Quiz Master, a fun and interactive quiz game built in Python using the Pygame library Streamlit. 2 | 3 | You can try out the game here =======> https://quiz-master.streamlit.app/ 4 | 5 | This README will provide you with all the information you need to understand the game's objective, rules, technology stack, and setup instructions. 6 | 7 | ## Game Objective and Rules 8 | 9 | The objective of this game is to answer the most questions correctly. Each round will have ten questions that will come from categories and difficulty levels of your choosing. Take your time as you answer the questions. There is no time limit. Above all else, have fun! You have full autonomy over the questions you receive. 10 | 11 | Step 1: Select a Category 12 | 13 | You will start the game by selecting the category you want your questions to be randomly generated from. These categories could range from Entertainment to Science. Please select a category that would provide the most enjoyable experience for this round. After the game starts, you can change your category if you desire for each question. 14 | 15 | When a category has been selected, the first question and corresponding answer choices will appear. You will have the opportunity to change your category after previewing a question. 16 | 17 | Step 2: Select the Level of Difficulty 18 | 19 | For the best experience, you should select the difficulty level after selecting the category. The first question will default to the easy difficulty level. The levels of difficulty range from Easy to Medium to Hard. Please be sure to pick a level of difficulty that would provide the most enjoyable experience for you. If you change from the default difficulty level, the question will change to reflect the new chosen level. 20 | 21 | Please review the question before you submit your answer. When an answer has been submitted, it will count towards your final score. You will not be able to go back and change the difficulty level or category for any previous question. 22 | 23 | Most importantly, challenge yourself and your friends and have fun! Correct answers will be displayed for every wrong answer. At the end of the game, your score will be revealed. To start a new round, please refresh the page. 24 | 25 | Will you be the next Quiz Master? Play this game and find out! 26 | 27 | 28 | 29 | ## Technology Stack 30 | 31 | The Quiz-Master game is developed in Python language and uses [Streamlit](https://streamlit.io/), which is an open-source Python library that is designed to make it easy to create web applications. It allows you to turn data scripts into shareable web apps quickly and with minimal effort. Streamlit is gaining popularity because it offers a simple and intuitive way to build interactive data-driven applications. It is mainly used for creating the user interface of the game. It allows for easy web app development with Python. Packages like Requests, used for making HTTP requests, JSON library is used for encoding and decoding JSON data are included in the project. Other general libraries like datetime, pandas, numpy, and plotly are used. 32 | 33 | The modules and functions used in the game development are discussed below: 34 | 35 | The code begins with import statements to bring in the necessary libraries and packages. 36 | 37 | get_category(): This function fetches all the available quiz categories from the Open Trivia Database API and returns them as a dictionary. 38 | 39 | get_question(): Based on the selected category and difficulty, it returns a list of questions. 40 | 41 | initialize_session_state(): It initializes the game state, which includes the current question index and player score, using Streamlit’s session state. 42 | 43 | update_score(): This function compares the player's choice with the correct answer and updates the player's score accordingly. If the player's choice matches the correct answer, the score is incremented. Streamlit components like "st.success" and "st.error" are used to provide feedback to the player 44 | 45 | UI Setup: The code sets up the user interface using Streamlit. It allows the user to select a quiz category, difficulty level, and provides options to answer questions and navigate through the quiz. 46 | 47 | calculate_score(): This function includes most of the functionality of the application. It calculates the player’s score by comparing their choices with the correct answer and then updates the session. This part has Streamlit’s UI components for creating the game, such as st.title, st.subheader, st.sidebar, st.radio, and st.button. Inside the function, it compares player_choice with correct_answer and decides whether to increase the player's score or not. The updated player score is stored in Streamlit’s session state so that it persists across different questions in the game. 48 | 49 | Category Selection: A Streamlit select box allows the user to choose from among the various categories that the code has retrieved. 50 | 51 | Selection of Difficulty Level: Using a choose box, the user may select between three difficulty levels: easy, medium, and hard. 52 | 53 | Question Fetching: Questions are retrieved from the API based on the chosen category and level of difficulty. The "quiz_questions" list is where these questions are processed and kept. 54 | 55 | Question Display: The code controls how questions are shown, letting the player choose their response by pressing a radio button. 56 | 57 | Answer Submission: The "calculate_score" function is triggered when the player submits an answer. 58 | 59 | Getting Around the Quiz: After submitting an answer, the code shows the next question, allowing players to move around the quiz. The quiz ends and the final score is shown once every question has been answered. 60 | 61 | 62 | 63 | ## Setup and Deployment Instructions 64 | 65 | 👨🏻‍💻 How to run the app? 66 | 67 | Step 1: Clone the repo 68 | 69 | Step 2: Create virtual environment: 'python -m venv ' 70 | 71 | Step 3: Activate the environment: '\Scripts\activate' 72 | 73 | Step 4: Install the dependencies: pip install -r requirements.txt 74 | 75 | step 5: Run it on local host: 'streamlit run QuizMaster.py' 76 | 77 | The Dashboard can be accessed via following link: https://quiz-master.streamlit.app/ 78 | 79 | ## Credits & Acknowledgements 80 | 81 | Streamlit v1.27.0 82 | https://streamlit.io | Copyright 2023 Snowflake Inc. All rights reserved. 83 | 84 | Numpy v1.19.1 85 | https://numpy.org/ | Harris, C.R., Millman, K.J., van der Walt, S.J. et al. Array programming with NumPy. Nature 585, 357–362 (2020). DOI: 10.1038/s41586-020-2649-2. (Publisher link). 86 | 87 | Pandas v1.2.0 88 | https://pandas.pydata.org/docs/index.html | 2023 pandas via NumFOCUS, Inc. Hosted by OVHcloud. 89 | 90 | Requests v2.24.0 91 | https://requests.readthedocs.io/en/latest/ | ©MMXVIX. A Kenneth Reitz Project. 92 | 93 | 94 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /Games/General Quiz Game/quiz.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Project 1: Web Based Game 3 | Author: Ruchit Tripathi 4 | ''' 5 | 6 | import streamlit as st 7 | import plotly.express as px 8 | import plotly.graph_objects as go 9 | import numpy as np 10 | import pandas as pd 11 | import json as js 12 | import requests as rq 13 | import time 14 | from datetime import datetime, timedelta 15 | import altair as alt 16 | import random 17 | 18 | # Logic to add background images (Future Enhancement) 19 | # def set_bg_hack_url(): 20 | # ''' 21 | # A function to unpack an image from url and set as bg. 22 | # Returns 23 | # ------- 24 | # The background. 25 | # ''' 26 | 27 | # st.markdown( 28 | # f""" 29 | # 35 | # """, 36 | # unsafe_allow_html=True 37 | # ) 38 | 39 | def get_category(): 40 | category_dict = dict() 41 | category_json_list = rq.get("https://opentdb.com/api_category.php").json() 42 | for item in category_json_list['trivia_categories']: 43 | category_dict[item['name']] = item['id'] 44 | return category_dict 45 | 46 | @st.cache_data(ttl= 75, max_entries=1) 47 | def get_question(category,difficulty): 48 | questions = rq.get("https://opentdb.com/api.php?amount=10"+"&category="+str(category)+"&difficulty="+str(difficulty)).json()["results"] 49 | return questions 50 | 51 | def initialize_session_state(): 52 | if 'current_question' not in st.session_state: 53 | st.session_state.current_question = 0 54 | # st.snow() 55 | if 'player_score' not in st.session_state: 56 | st.session_state.player_score = 0 57 | 58 | def update_score(player_choice, correct_answer): 59 | if str(player_choice) == str(correct_answer): 60 | st.success("It was a correct answer! Great Job! 😁✌") 61 | st.session_state.player_score += 1 62 | st.balloons() 63 | else: 64 | st.error("It was an incorrect answer! 😕") 65 | 66 | if "page" not in st.session_state: 67 | st.session_state.page = 0 68 | if "submit_key" in st.session_state and st.session_state.submit_key == True: 69 | st.session_state.running = True 70 | else: 71 | st.session_state.running = False 72 | 73 | if "running" not in st.session_state: 74 | st.session_state.running = False 75 | 76 | def nextpage(): st.session_state.page += 1 77 | def restart(): st.session_state.page = 0 78 | 79 | # set_bg_hack_url() 80 | st.markdown("",unsafe_allow_html = True) 81 | st.title(":orange[Welcome to the] :violet[QuizMaster!] 🧩") 82 | st.subheader("_Engage, Entertain, and Educate with QuizMaster - Where Knowledge Meets Fun!_", divider= 'rainbow') 83 | st.sidebar.title("Tune the Options to Play the Game") 84 | st.sidebar.markdown("---") 85 | initialize_session_state() 86 | 87 | def calculate_score(player_choice): 88 | correct_answer = quiz_questions[st.session_state.current_question]["answer"] 89 | # st.write("inside calculate_score" + str(correct_answer)) 90 | update_score(player_choice, correct_answer) 91 | st.session_state.current_question += 1 92 | 93 | categories_option = get_category() 94 | category = st.sidebar.selectbox("Category: ", list(categories_option.keys()), index= None, placeholder= "Select one: ", disabled=(st.session_state.running)) 95 | # st.session_state.disable_opt = True 96 | # category = st.sidebar.selectbox("Category: ", list(categories_option.keys()), index= None, placeholder= "Select one: ", disabled=(st.session_state.running)) 97 | if category is None: 98 | st.warning('Please select one category to start the game', icon="⚠️") 99 | else: 100 | levels = st.sidebar.selectbox("Difficulty Level: ", ['Easy', 'Medium', 'Hard'], disabled=(st.session_state.running)) 101 | QuestionList = get_question(categories_option[category], levels.lower()) 102 | # st.write(QuestionList) 103 | len_response = len(QuestionList) 104 | if len_response == 0: 105 | st.error("This Category has no question for the given difficulty mode at the source side! Please select another difficulty level or category to start the game! 😕😔") 106 | st.stop() 107 | quiz_questions = [] 108 | for item in range(len_response): 109 | temp_dict = dict() 110 | temp_dict['text'] = QuestionList[item].get("question") 111 | temp_dict['options'] = tuple(QuestionList[item].get("incorrect_answers") + [QuestionList[item].get("correct_answer")]) 112 | temp_dict['answer'] = QuestionList[item].get("correct_answer") 113 | quiz_questions.append(temp_dict) 114 | placeholder = st.empty() 115 | ind = st.session_state.current_question 116 | if ind > len(quiz_questions): 117 | st.stop() 118 | else: 119 | current_question = quiz_questions[ind] 120 | st.subheader(quiz_questions[ind]["text"]) 121 | player_choice = st.radio("Select your answer:", 122 | options= current_question["options"], 123 | key=f"question_{ind}", disabled=(st.session_state.running)) 124 | submitted = st.button("Submit", key="submit_key", disabled=(st.session_state.running)) 125 | if submitted: 126 | calculate_score(player_choice) 127 | st.markdown("Correct Answer: "+ current_question["answer"]) 128 | # st.empty() 129 | if st.button("Next",on_click=nextpage,disabled=(st.session_state.page >= 9)): 130 | if st.session_state.current_question < len(quiz_questions): 131 | st.rerun() 132 | if st.session_state.current_question >= len(quiz_questions): 133 | # st.session_state.clear 134 | st.empty() 135 | st.success("Quiz Finished!") 136 | st.subheader(f"_Your_ _Score_: :blue[{st.session_state.player_score}] :sunglasses:") 137 | st.snow() 138 | 139 | st.markdown("---") 140 | st.info("Reload the page or press F5 to restart the game!") 141 | st.sidebar.markdown("---") 142 | st.sidebar.markdown("### About Developer", unsafe_allow_html=True) 143 | st.sidebar.markdown("Visit Ruchit's LinkedIn and Github profiles for more information & updates.", unsafe_allow_html=True) 144 | st.sidebar.markdown("### About Contributors", unsafe_allow_html=True) 145 | st.sidebar.markdown("Stephanie's LinkedIn", unsafe_allow_html=True) 146 | st.sidebar.markdown("Gayatri's LinkedIn", unsafe_allow_html=True) 147 | st.sidebar.markdown("Thanks for visiting the site! 😃 Have Fun 😉") -------------------------------------------------------------------------------- /Games/General Quiz Game/requirements.txt: -------------------------------------------------------------------------------- 1 | pandas >=1.2.0 2 | plotly>=4.9.0 3 | requests==2.24.0 4 | numpy >=1.19.1 5 | streamlit>=1.27.0 6 | altair<5 -------------------------------------------------------------------------------- /Games/README_template.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Name of your game 8 | 9 | ## Rules 10 | 1. 11 | 2. 12 | 3. 13 | 14 | ## How to play 15 | 1. Fork the repo by clicking the fork logo on the top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 17 | 3. Head to the folder 18 | 4. Run the file using python command `python ` 19 | 20 | 21 | -------------------------------------------------------------------------------- /Games/auction/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Auction 9 | 10 | ## Rules 11 | 1. Each Player has to enter his/her name and their bid 12 | 2. Player with the clostest bid to average bid wins 13 | 3. The average bid calculation is `total bid / number of players` 14 | 15 | ## How to play 16 | 1. Fork the repo by clicking the fork logo the on top right 17 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 18 | 3. Head to the auction folder 19 | 4. Run the file using python command `python auction.py` 20 | 21 | -------------------------------------------------------------------------------- /Games/auction/ascii_art.py: -------------------------------------------------------------------------------- 1 | logo = ''' 2 | ___________ 3 | \ / 4 | )_______( 5 | |"""""""|_.-._,.---------.,_.-._ 6 | | | | | | | ''-. 7 | | |_| |_ _| |_..-' 8 | |_______| '-' `'---------'` '-' 9 | )"""""""( 10 | /_________\\ 11 | .-------------. 12 | /_______________\\ 13 | ''' -------------------------------------------------------------------------------- /Games/auction/auction.py: -------------------------------------------------------------------------------- 1 | import os 2 | from sys import platform 3 | from ascii_art import logo 4 | # Clears command line 5 | def clear(): 6 | if platform == "linux" or platform == "linux2": 7 | # linux 8 | os.system("clear") 9 | elif platform == "darwin": 10 | # OS X 11 | os.system("clear") 12 | elif platform == "win32": 13 | # Windows... 14 | os.system("CLS") 15 | 16 | # Global Val 17 | players = {} 18 | 19 | # Calculates average of total and selects winner 20 | def calcBid(players): 21 | totalBid = [] 22 | totalValue = 0 23 | 24 | for i in players: 25 | totalBid.append(players[i]) 26 | totalValue += players[i] 27 | 28 | mean = totalValue / len(players) 29 | winnerBid = min(totalBid, key=lambda x:abs(x-mean)) 30 | 31 | nameList = list(players.keys()) 32 | bidList = list(players.values()) 33 | 34 | position = bidList.index(winnerBid) 35 | 36 | winnerName = nameList[position] 37 | 38 | for i in players: 39 | print(f"{i} bid ${players[i]}") 40 | 41 | print(f"\nThe average of total comes to {mean}") 42 | print(f"Winner is {winnerName} with ${winnerBid}!!\n\n") 43 | 44 | clear() 45 | 46 | print(logo) 47 | # Adds player 48 | bidding = True 49 | while bidding: 50 | name = input("Enter your name\n") 51 | while True: 52 | bidAmount = input("Enter the bidding amount\n$") 53 | if bidAmount.isdigit(): 54 | bidAmount = int(bidAmount) 55 | if bidAmount > 0: 56 | break 57 | else: 58 | print("You have to bid more than $0") 59 | else: 60 | print(f"{bidAmount} is not a number") 61 | 62 | players[name] = bidAmount 63 | 64 | 65 | cont = (input("Add another player?\nEnter 'Yes' or 'No'\n")).lower() 66 | 67 | clear() 68 | 69 | if cont == "yes": 70 | continue 71 | if cont == "no": 72 | bidding = False 73 | 74 | calcBid(players) -------------------------------------------------------------------------------- /Games/black_jack/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # BlackJack 9 | 10 | ## Rules 11 | 1. Player and dealer draws two card from the deck 12 | 2. Dealer only shows one of the card 13 | 3. Player has to choose either hit (draw another card) or stand (continue without drawing) 14 | 4. Dealer will draw card until the total exceeds 17 15 | 5. The hand with the highest totals wins as long as it doesn't exceed 21 16 | 17 | 18 | - Ace will represent 11 or 1, King 19 | - King, Queen, and Jack represents 10 20 | 21 | ## How to play 22 | 1. Fork the repo by clicking the fork logo the on top right 23 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 24 | 3. Head to the blackjack folder 25 | 4. Run the file using python command `python main.py` 26 | -------------------------------------------------------------------------------- /Games/black_jack/main.py: -------------------------------------------------------------------------------- 1 | import random 2 | import os 3 | from sys import platform 4 | from colorama import Fore 5 | 6 | # Clears command line 7 | def clear(): 8 | if platform == "linux" or platform == "linux2": 9 | # linux 10 | os.system("clear") 11 | elif platform == "darwin": 12 | # OS X 13 | os.system("clear") 14 | elif platform == "win32": 15 | # Windows... 16 | os.system("CLS") 17 | 18 | # Global Val 19 | n_decks = 6 #standard casino's number 20 | suit = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10] 21 | 22 | def new_cards(): 23 | total = suit * 4 * n_decks 24 | 25 | return total 26 | 27 | balance = 0 28 | bet = 0 29 | 30 | # Gets player's deposit 31 | def deposit(): 32 | while True: 33 | balance = input("How much would you like to deposit? $") 34 | if balance.isdigit(): 35 | balance = int(balance) 36 | if balance > 0: 37 | break 38 | else: 39 | print("You can't deposit $0") 40 | else: 41 | print(f"{balance} is not a number") 42 | return balance 43 | 44 | # Gets player's bet amount 45 | def get_bet(): 46 | while True: 47 | amount = input("How much would you like to bet? $") 48 | if amount.isdigit(): 49 | amount = int(amount) 50 | if amount > balance: 51 | print(f"You cannot bet more than your current balance (${balance})") 52 | elif amount > 0: 53 | break 54 | else: 55 | print("You can't bet $0") 56 | else: 57 | print(f"{amount} is not a number") 58 | return amount 59 | 60 | # Draws card from the cards 61 | def deal_card(): 62 | card = random.choice(cards) 63 | cards.remove(card) 64 | return card 65 | 66 | # Calculates total hand 67 | def calcScore(hand): 68 | if sum(hand) == 21 and len(hand) == 2: 69 | return 0 70 | if 11 in hand and sum(hand) > 21: 71 | hand.remove(11) 72 | hand.append(1) 73 | return sum(hand) 74 | 75 | # Checks for winner 76 | def checkWinner(user_score, computer_score): 77 | if user_score > 21 and computer_score > 21: 78 | print(" You lose, you went over. 😤") 79 | print(f"{Fore.RED}Your updated balance is: {balance - bet}{Fore.RESET}") 80 | return balance - bet 81 | 82 | if user_score == computer_score: 83 | print(" Draw 🙃") 84 | print(Fore.YELLOW + f"Your updated balance is: {balance}{Fore.RESET}") 85 | return balance 86 | elif computer_score == 0: 87 | print(" You lose, dealer has Blackjack 😱") 88 | print(Fore.RED + f"Your updated balance is: {balance - bet}{Fore.RESET}") 89 | return balance - bet 90 | elif user_score == 0: 91 | print(" You Win with a Blackjack 😎") 92 | print(Fore.GREEN + f"Your updated balance is: {balance+int(bet * 1.5)}{Fore.RESET}") 93 | return balance + int(bet * 1.5) 94 | elif user_score > 21: 95 | print(" You lose, you went over 😭") 96 | print(Fore.RED + f"Your updated balance is: {balance+bet}{Fore.RESET}") 97 | return balance - bet 98 | elif computer_score > 21: 99 | print(" You win, dealer went over 😁") 100 | print(Fore.GREEN + f"Your updated balance is: {balance+bet}{Fore.RESET}") 101 | return balance + bet 102 | elif user_score > computer_score: 103 | print(" You win 😃") 104 | print(Fore.GREEN + f"Your updated balance is: {balance + bet}{Fore.RESET}") 105 | return balance + bet 106 | else: 107 | print(" You lose 😤") 108 | print(Fore.RED + f"Your updated balance is: {balance - bet}{Fore.RESET}") 109 | return balance - bet 110 | 111 | def play_game(): 112 | global balance 113 | global cards 114 | user_cards = [] 115 | computer_cards = [] 116 | is_game_over = False 117 | if not cards: 118 | cards = new_cards() 119 | 120 | for _ in range(2): 121 | user_cards.append(deal_card()) 122 | computer_cards.append(deal_card()) 123 | 124 | 125 | while not is_game_over: 126 | user_score = calcScore(user_cards) 127 | computer_score = calcScore(computer_cards) 128 | print(f"\n Your cards: {user_cards}, current score: {user_score}") 129 | print(f" Dealer's card: [{computer_cards[0]}, _ ]") 130 | 131 | if user_score == 0 or computer_score == 0 or user_score > 21: 132 | is_game_over = True 133 | else: 134 | user_should_deal = input("\nType 'y' to get another card, type 'n' to pass: ") 135 | if user_should_deal == "y": 136 | user_cards.append(deal_card()) 137 | else: 138 | is_game_over = True 139 | 140 | while computer_score != 0 and computer_score < 17: 141 | computer_cards.append(deal_card()) 142 | computer_score = calcScore(computer_cards) 143 | 144 | print(f"\n Your final hand: {user_cards}, final score: {user_score}") 145 | print(f" Computer's final hand: {computer_cards}, final score: {computer_score}") 146 | balance = checkWinner(user_score, computer_score) 147 | 148 | 149 | 150 | clear() 151 | balance = deposit() 152 | cards = new_cards() 153 | while True: 154 | if balance <= 0: 155 | print("\nYou've lost all of your money! 😭") 156 | input() 157 | quit() 158 | play = input("Press enter to play ('q' to quit)") 159 | clear() 160 | if play =="q": 161 | exit() 162 | balance = balance 163 | 164 | if len(cards) < 300: 165 | print("Time to shuffle the cards!") 166 | cards = new_cards() 167 | 168 | print(f"Your current balance is ${balance}\n") 169 | bet = get_bet() 170 | play_game() -------------------------------------------------------------------------------- /Games/board_filling_game/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Board filling game 9 | 10 | ## Rules 11 | 1. Enter coordinates to put the pieces on the board. 12 | 2. Try to fill the board in as few rounds as possible. 13 | 3. Enter (0, 0) to skip the round. 14 | 15 | ## How to play 16 | 1. Fork the repo by clicking the fork logo the on top right 17 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 18 | 3. Head to the board_filling_game folder 19 | 4. Run the file using python command `python board_filling_game.py` 20 | 21 | -------------------------------------------------------------------------------- /Games/board_filling_game/board_filling_game.py: -------------------------------------------------------------------------------- 1 | import os 2 | from sys import platform 3 | from random import randint 4 | 5 | # Clears command line 6 | def clear(): 7 | if platform == "linux" or platform == "linux2": 8 | # linux 9 | os.system("clear") 10 | elif platform == "darwin": 11 | # OS X 12 | os.system("clear") 13 | elif platform == "win32": 14 | # Windows 15 | os.system("CLS") 16 | 17 | # Welcomes the player and sets up the board sizes 18 | def welcome(): 19 | print("Welcome to Board Filling Game.") 20 | print("Rules: ") 21 | print("1. Enter coordinates to put the pieces on the board.") 22 | print("2. Enter (0, 0) to skip the round.") 23 | print("3. Try to fill the board in as few rounds as possible!\n") 24 | 25 | print("Please enter the board size you want.") 26 | height = 3 27 | width = 3 28 | try: 29 | height = int(input("Height (default: 3) -> ")) 30 | width = int(input("Width (default: 3) -> ")) 31 | except: 32 | print("Invalid height. Using a 3x3 board as default.") 33 | height = 3 34 | width = 3 35 | 36 | return height, width 37 | 38 | # Checks if there are any empty cells left 39 | def is_game_done(game_board): 40 | for row in game_board: 41 | for cell in row: 42 | if cell == "□": 43 | return False 44 | 45 | return True 46 | 47 | def print_board(game_board): 48 | for row in game_board: 49 | for cell in row: 50 | print(cell, end=" ") 51 | print() 52 | 53 | # Prints the piece onto the game screen 54 | def print_piece(current_piece): 55 | result = "" 56 | 57 | if current_piece == 0: 58 | result = "■" 59 | elif current_piece == 1: 60 | result = "■ ■" 61 | elif current_piece == 2: 62 | result = "■\n■" 63 | elif current_piece == 3: 64 | result = "■ ■ ■" 65 | elif current_piece == 4: 66 | result = "■\n■\n■" 67 | 68 | print(result) 69 | 70 | # Gets player input, retrying if necessary 71 | def get_player_input(): 72 | 73 | x = -1 74 | y = -1 75 | 76 | print() 77 | while x < 0 or y < 0: 78 | try: 79 | x = int(input("Column -> ")) 80 | y = int(input("Row -> ")) 81 | except: 82 | print("Invalid coordinates. Please re-enter.") 83 | 84 | return x, y 85 | 86 | # Updates the board 87 | def update_board(game_board, height, width, x, y, current_piece): 88 | # Convert from 1-indexed to 0-indexed coordinates 89 | x = x - 1 90 | y = y - 1 91 | 92 | # If the coordinates are out of range 93 | if x<-1 or x>=width or y<-1 or y>=height: 94 | print("Invalid coordinates. Skipping turn...") 95 | return game_board 96 | elif x == -1 or y == -1: 97 | print("Skipping turn...") 98 | 99 | # Coordinates are not out of range, check whether the piece fits into the board 100 | new_board = game_board 101 | 102 | # 0: x 103 | if current_piece == 0 and game_board[y][x]=="□": 104 | new_board[y][x] = "■" 105 | 106 | # 1: xx horizontal 107 | elif current_piece == 1 and x+1 2 | 3 | 4 | 5 |

6 | 7 | 8 | # Checkers 9 | 10 | ## Rules 11 | 1. Each piece can move diagonally once 12 | 2. Kings can move anywhere diagonally 13 | 3. A piece captures another if it can move behind it 14 | 4. A piece becomes king when reaching the opposite side of the board 15 | 5. Pieces can capture backwards 16 | 6. A team wins if the opponent no longer has pieces or if the opponent can no longer move 17 | 18 | ## How to play 19 | 1. Fork the repo by clicking the fork logo the on top right 20 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 21 | 3. Head to the checkers folder 22 | 4. Run the file using python command `python checkers.py` 23 | 24 | -------------------------------------------------------------------------------- /Games/chin_chiro/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # ChinChiro 9 | 10 | ## Rules 11 | 1. The dealer and player each roll three dice. 12 | 2. The outcome is determined by the combination of the dice. 13 | 3. If the player wins, the payout is calculated by the score of the role. 14 | 4. If the player loses, the bet is lost. 15 | 5. If the role a has negative score, the player loses the bet multiplied by the score. 16 | 17 | 18 | | **Role** | **Dice Combination** | **Score** | 19 | |:-----------:|:---------------------------------------------------------:|:---------:| 20 | | **Pinzoro** | 1 - 1 - 1 (A triplet of ones) | 5 | 21 | | **Triplet** | 2 - 2 - 2 / 3 - 3 - 3 / 4 - 4 - 4 / 5 - 5 - 5 / 6 - 6 - 6 | 3 | 22 | | **Jigoro** | 4 - 5 - 6 (A straight of 4, 5, 6) | 2 | 23 | | **Normal** | e.g., 2 - 2 - 5 | 1 | 24 | | **No Role** | e.g., 2 - 4 - 6 | -1 | 25 | | **Hifumi** | 1 - 2 - 3 (A straight of 1, 2, 3) | -2 | 26 | 27 | ### Same Role Comparison 28 | **Triplet**: The higher number wins. (e.g., 6 - 6 - 6 > 3 - 3 - 3) 29 | **Normal**: 30 | 1. The higher unique number wins. (e.g., 2 - 2 - 4 > 5 - 5 - 1) 31 | 2. If the unique numbers are the same, the higher total wins. (2 - 6 - 6 > 2 - 3 - 3) 32 | 33 | ## How to play 34 | 1. Fork the repo by clicking the fork logo the on top right 35 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 36 | 3. Head to the checkers folder 37 | 4. Run the file using python command `python chin_chiro.py` -------------------------------------------------------------------------------- /Games/chin_chiro/chin_chiro.py: -------------------------------------------------------------------------------- 1 | from game import GameLoop 2 | import os 3 | from sys import platform 4 | 5 | # Clears command line 6 | def clear(): 7 | if platform == "linux" or platform == "linux2": 8 | # linux 9 | os.system("clear") 10 | elif platform == "darwin": 11 | # OS X 12 | os.system("clear") 13 | elif platform == "win32": 14 | # Windows... 15 | os.system("CLS") 16 | 17 | 18 | if __name__ == "__main__": 19 | game = GameLoop() 20 | game.run_game() 21 | -------------------------------------------------------------------------------- /Games/chin_chiro/src/dice.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | class Dice: 5 | """ 6 | Dice class provides methods to simulate rolling three dice. 7 | The result are returned as a sorted list of random numbers between 1 and 6. 8 | """ 9 | @staticmethod 10 | def roll_dice(): 11 | """ 12 | Rolls three dice and returns their result sorted. 13 | All dice rolls are random and within the range of 1 to 6. 14 | 15 | Returns: 16 | list: A sorted integer list of dice rolls. 17 | """ 18 | a = random.randint(1, 6) 19 | b = random.randint(1, 6) 20 | c = random.randint(1, 6) 21 | dice = [a, b, c] 22 | dice = sorted(dice) 23 | return dice 24 | 25 | def get_player_dice(self): 26 | """ 27 | Rolls the dice for the player and returns the result. 28 | 29 | Returns: 30 | list: A sorted integer list of dice rolls. 31 | """ 32 | player_roll = Dice.roll_dice() 33 | return player_roll 34 | 35 | def get_dealer_dice(self): 36 | """ 37 | Rolls the dice for the dealer and returns the result. 38 | 39 | Returns: 40 | list: A sorted integer list of dice rolls. 41 | """ 42 | dealer_roll = Dice.roll_dice() 43 | return dealer_roll 44 | -------------------------------------------------------------------------------- /Games/chin_chiro/src/game.py: -------------------------------------------------------------------------------- 1 | from player import Player 2 | from dice import Dice 3 | from logic import Logic 4 | 5 | 6 | class GameLoop: 7 | """ 8 | GameLoop class manages the main game loop. 9 | The loop continues as long as the player has positive balance. 10 | """ 11 | def __init__(self, initial_balance=None): 12 | self.player = Player(initial_balance) 13 | self.dice = Dice() 14 | self.logic = Logic(self.player, self.dice) 15 | 16 | def run_game(self): 17 | """ 18 | Runs the game loop. 19 | The loop continues as long as the player has money and chooses to continue playing. 20 | """ 21 | # Continue the game if the player's balance is positive. 22 | while self.player.balance > 0: 23 | bet = self.player.set_bet() 24 | 25 | input('Press enter to roll the dice...') 26 | 27 | player_roll = self.dice.roll_dice() 28 | dealer_roll = self.dice.roll_dice() 29 | 30 | # Evaluate the player's roll and generate the result. 31 | player_result, player_message = self.logic.role_condition(player_roll) 32 | 33 | print(f'\nYour rolled: {player_message}') 34 | print(f'Dealer rolled: {dealer_roll[0]} - {dealer_roll[1]} - {dealer_roll[2]}\n') 35 | 36 | # Calculate the dividend based on the score and update the player's balance. 37 | result = self.logic.calculate_payment(player_roll, dealer_roll, bet) 38 | self.player.get_current_balance(result) 39 | print(f'Your current balance: ${self.player.balance}\n') 40 | 41 | # If the player has no money left, end the game. 42 | if self.player.balance <= 0: 43 | print("You're out of money! Game over.") 44 | break 45 | 46 | # Exit the game loop if the player chooses 'n' in ask_continue prompt 47 | if not self.player.ask_continue(): 48 | print("Thanks for playing!") 49 | break 50 | -------------------------------------------------------------------------------- /Games/chin_chiro/src/logic.py: -------------------------------------------------------------------------------- 1 | from player import Player 2 | from dice import Dice 3 | 4 | 5 | class Logic: 6 | """ 7 | Logic class manages the logic of the game. 8 | - Evaluates the role based on the dice combination. 9 | - Checks the win condition for the same role. 10 | - Calculates the dividend based on the score. 11 | """ 12 | def __init__(self, player, dice): 13 | self.player = player 14 | self.dice = dice 15 | 16 | def role_condition(self, dice_roll): 17 | """ 18 | Determines the role of the rolled dice combination. 19 | 20 | Args: 21 | dice_roll (list): A list of the dice roll. 22 | 23 | Return: 24 | int: The score of the role. 25 | str: The result and message describing the role. 26 | """ 27 | a, b, c = dice_roll 28 | if a == b == c: 29 | if a == 1: 30 | result = f'{a} - {b} - {c} Wow Pinzoro! Congratulations!!' 31 | return 5, result 32 | result = f'{a} - {b} - {c}' 33 | return 3, result 34 | elif a != b != c and a + b + c == 15: 35 | result = f'{a} - {b} - {c} It is JIGORO!' 36 | return 2, result 37 | elif a == b != c: 38 | result = f'{a} - {b} - {c}' 39 | return 1, result 40 | elif b == c != a: 41 | result = f'{a} - {b} - {c}' 42 | return 1, result 43 | elif c == a != b: 44 | result = f'{a} - {b} - {c}' 45 | return 1, result 46 | elif a != b != c and a + b + c == 6: 47 | result = f'{a} - {b} - {c} Oh... It is HIFUMI' 48 | return -2, result 49 | else: 50 | result = f'{a} - {b} - {c}' 51 | return -1, result 52 | 53 | def draw_condition(self, player_roll, dealer_roll): 54 | """ 55 | Checks the draw condition. 56 | 57 | Args: 58 | player_roll (list): A list of the player rolls 59 | dealer_roll (list): A list of the dealer rolls 60 | 61 | Returns: 62 | bool: True if both the player and dealer have the same dice roll, otherwise False. 63 | """ 64 | if player_roll == dealer_roll: 65 | return True 66 | return False 67 | 68 | def compare_same_role(self, player_roll, dealer_roll): 69 | """ 70 | Compares the same role to decide the winner. 71 | 72 | Args: 73 | player_roll (list): A list of the player rolls 74 | dealer_roll (list): A list of the dealer rolls 75 | 76 | Returns: 77 | int: The score based on the role. 78 | """ 79 | # If both player and dealer have triplets, the higher wins. 80 | if (player_roll[0] == player_roll[1] == player_roll[2] and 81 | dealer_roll[0] == dealer_roll[1] == dealer_roll[2]): 82 | if player_roll[0] > dealer_roll[0]: 83 | print("You won! You got 3x your bet.") 84 | return 3 85 | elif player_roll[0] < dealer_roll[0]: 86 | print("You lose. You lost -1x your bet.") 87 | return -1 88 | else: 89 | return 0 90 | 91 | # Check if both have pairs to compare the score. 92 | player_pairs = [num for num in player_roll if player_roll.count(num) == 2] 93 | dealer_pairs = [num for num in dealer_roll if dealer_roll.count(num) == 2] 94 | 95 | if player_pairs and dealer_pairs: 96 | # If both have pairs, compare the non-pair numbers. 97 | player_other = [num for num in player_roll if player_roll.count(num) == 1][0] 98 | dealer_other = [num for num in dealer_roll if dealer_roll.count(num) == 1][0] 99 | 100 | # If the non-pair number is higher, wins. 101 | if player_other > dealer_other: 102 | print("You won! You got 1x your bet.") 103 | return 1 104 | elif player_other < dealer_other: 105 | print("You lose. You lost -1x your bet.") 106 | return -1 107 | else: 108 | # If the non-pair numbers are equal, the higher total wins. 109 | player_sum = sum(player_roll) 110 | dealer_sum = sum(dealer_roll) 111 | if player_sum > dealer_sum: 112 | print("You won! You got 1x your bet.") 113 | return 1 114 | else: 115 | print("You lose. You lost -1x your bet.") 116 | return -1 117 | else: 118 | return None # No pair, no comparison 119 | 120 | def calculate_payment(self, player_roll, dealer_roll, bet): 121 | """ 122 | Calculates the dividend based on the score. 123 | 124 | Args: 125 | player_roll (list): A list of the player rolls 126 | dealer_roll (list): A list of the dealer rolls 127 | bet (int): The bet set by the player 128 | 129 | Return: 130 | dividend (int): The dividend (positive or negative) based on the role. 131 | """ 132 | # Determine the score for both player and dealer. 133 | player_score, p_message = self.role_condition(player_roll) 134 | dealer_score, d_message = self.role_condition(dealer_roll) 135 | 136 | # If it is draw, return the bet back. 137 | if self.draw_condition(player_roll, dealer_roll): 138 | print("Draw, your bet is returned.") 139 | dividend = 0 140 | return dividend 141 | 142 | # If the same role, compare the score using compare_same_role 143 | elif player_score == dealer_score == 1 or player_score == dealer_score == 3: 144 | player_score = self.compare_same_role(player_roll, dealer_roll) 145 | dividend = bet * player_score 146 | return dividend 147 | 148 | # Calculate the player's bet multiplied by the score based on the roll. 149 | elif player_score > dealer_score: 150 | print(f'You got {player_score}x your bet!') 151 | dividend = bet * player_score 152 | return dividend 153 | 154 | elif player_score < 0: 155 | print(f"You lose... {player_score}x your bet lost") 156 | dividend = bet * player_score 157 | return dividend 158 | 159 | elif player_score < dealer_score: 160 | print(f"You lose... You lost ${bet}.") 161 | dividend = bet * -1 162 | return dividend 163 | -------------------------------------------------------------------------------- /Games/chin_chiro/src/player.py: -------------------------------------------------------------------------------- 1 | class Player: 2 | """ 3 | Player class manages the player behavior. 4 | - Set an initial balance 5 | - Set a bet amount 6 | - Update player's balance 7 | - Decide whether to continue the game or not 8 | """ 9 | def __init__(self, initial_balance=None): 10 | """ 11 | Initialise the new player with the given initial balance. 12 | 13 | Args: 14 | initial_balance (int): The initial balance for the new player. 15 | """ 16 | if initial_balance is not None: 17 | self.balance = initial_balance 18 | else: 19 | self.balance = self.set_initial_balance() 20 | 21 | @staticmethod 22 | def set_initial_balance(): 23 | """ 24 | Prompts the user to input the initial balance. 25 | The method will ask for input until the user enters a valid balance. 26 | 27 | Returns: 28 | int: The valid initial balance greater than 0. 29 | """ 30 | while True: 31 | initial_balance = input('Your initial balance: $') 32 | if initial_balance.isdigit(): 33 | initial_balance = int(initial_balance) 34 | if initial_balance > 0: 35 | return initial_balance 36 | else: 37 | print('Your balance must be greater than 0.') 38 | else: 39 | print('Enter numbers greater than 0.') 40 | 41 | def set_bet(self): 42 | """ 43 | Prompts the user to input the bet amount. 44 | Validates that the bet amount is greater than 0 and less than or equal to the current balance 45 | 46 | Return: 47 | int: The valid bet amount between 0 and the current balance. 48 | """ 49 | while True: 50 | bet = input('How much would you like to bet? $') 51 | if bet.isdigit(): 52 | bet = int(bet) 53 | if 0 < bet <= self.balance: 54 | return bet 55 | else: 56 | print(f'Set your bet between 0 and {self.balance}') 57 | else: 58 | print('Enter numbers greater than 0.') 59 | 60 | def get_current_balance(self, dividend): 61 | """ 62 | Updates the current balance with the given dividend. 63 | 64 | Args: 65 | dividend (int): The result is calculated by the role condition. 66 | """ 67 | self.balance += dividend 68 | 69 | @staticmethod 70 | def ask_continue(): 71 | """ 72 | Asks the player to continue or exit the game. 73 | 74 | Returns: 75 | bool: True if the player choose 'y' to continue, otherwise False('n'). 76 | """ 77 | while True: 78 | continue_choice = input("Do you want to continue (y/n)? ").lower() 79 | if continue_choice == 'y': 80 | return True 81 | elif continue_choice == 'n': 82 | return False 83 | else: 84 | print("Please enter y or n") 85 | -------------------------------------------------------------------------------- /Games/chin_chiro/tests/__pycache__/test_dice.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/chin_chiro/tests/__pycache__/test_dice.cpython-312.pyc -------------------------------------------------------------------------------- /Games/chin_chiro/tests/__pycache__/test_logic.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/chin_chiro/tests/__pycache__/test_logic.cpython-312.pyc -------------------------------------------------------------------------------- /Games/chin_chiro/tests/__pycache__/test_player.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/chin_chiro/tests/__pycache__/test_player.cpython-312.pyc -------------------------------------------------------------------------------- /Games/chin_chiro/tests/test_dice.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from dice import Dice 3 | 4 | 5 | class TestDice(unittest.TestCase): 6 | def test_roll_dice(self): 7 | """Test that the roll_dice function generates three dice rolls, each between 1 and 6""" 8 | dice = Dice() 9 | roll = dice.roll_dice() 10 | for x in roll: 11 | self.assertGreaterEqual(x, 1) 12 | self.assertLessEqual(x, 6) 13 | self.assertEqual(len(roll), 3) 14 | self.assertTrue(roll[0] <= roll[1] <= roll[2]) 15 | 16 | 17 | if __name__ == "__main__": 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /Games/chin_chiro/tests/test_logic.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from logic import Logic 3 | from player import Player 4 | from dice import Dice 5 | 6 | 7 | class TestLogic(unittest.TestCase): 8 | def setUp(self): 9 | self.logic = Logic(Player(100), Dice()) 10 | 11 | def test_role_condition(self): 12 | """Test that the role_condition function correctly returns the score and message""" 13 | 14 | # Test for Pinzoro (1, 1, 1) 15 | result, message = self.logic.role_condition([1, 1, 1]) 16 | self.assertEqual(result, 5) 17 | self.assertEqual(message, '1 - 1 - 1 Wow Pinzoro! Congratulations!!') 18 | 19 | # Test for Triplet (3, 3, 3) 20 | result, message = self.logic.role_condition([3, 3, 3]) 21 | self.assertEqual(result, 3) 22 | 23 | # Test for Jigoro (4, 5, 6) 24 | result, message = self.logic.role_condition([4, 5, 6]) 25 | self.assertEqual(result, 2) 26 | self.assertEqual(message, '4 - 5 - 6 It is JIGORO!') 27 | 28 | # Test for Normal (2, 2, 3) 29 | result, message = self.logic.role_condition([2, 2, 3]) 30 | self.assertEqual(result, 1) 31 | self.assertEqual(message, '2 - 2 - 3') 32 | 33 | # Test for No Role (2, 5, 6) 34 | result, message = self.logic.role_condition([2, 5, 6]) 35 | self.assertEqual(result, -1) 36 | self.assertEqual(message, '2 - 5 - 6') 37 | 38 | # Test for Hifumi (1, 2, 3) 39 | result, message = self.logic.role_condition([1, 2, 3]) 40 | self.assertEqual(result, -2) 41 | self.assertEqual(message, '1 - 2 - 3 Oh... It is HIFUMI') 42 | 43 | def test_draw_condition(self): 44 | """Test that the draw_condition function correctly identifies a draw 45 | and that the calculate_payment function correctly returns 0 for a draw""" 46 | 47 | # Test for True 48 | player_roll = [2, 4, 6] 49 | dealer_roll = [2, 4, 6] 50 | bet = 50 51 | self.assertEqual(self.logic.draw_condition(player_roll, dealer_roll), True) 52 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 53 | self.assertEqual(dividend, 0) 54 | 55 | # Test for False 56 | player_roll = [2, 4, 6] 57 | dealer_roll = [1, 4, 6] 58 | self.assertEqual(self.logic.draw_condition(player_roll, dealer_roll), False) 59 | 60 | def test_compare_normal_condition(self): 61 | """Test that the compare_same_role function handles Normal correctly 62 | and the calculate_payment function correctly returns dividend""" 63 | player_roll = [2, 6, 6] 64 | dealer_roll = [3, 3, 5] 65 | bet = 50 66 | result = self.logic.compare_same_role(player_roll, dealer_roll) 67 | self.assertEqual(result, -1) 68 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 69 | self.assertEqual(dividend, -50) 70 | 71 | player_roll = [4, 4, 6] 72 | dealer_roll = [2, 2, 6] 73 | result = self.logic.compare_same_role(player_roll, dealer_roll) 74 | self.assertEqual(result, 1) 75 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 76 | self.assertEqual(dividend, 50) 77 | 78 | def test_compare_triplet_condition(self): 79 | """Test that the compare_same_role function handles Triplet correctly 80 | and the calculate_payment function returns correct dividend""" 81 | player_roll = [6, 6, 6] 82 | dealer_roll = [2, 2, 2] 83 | bet = 50 84 | result = self.logic.compare_same_role(player_roll, dealer_roll) 85 | self.assertEqual(result, 3) 86 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 87 | self.assertEqual(dividend, 150) 88 | 89 | def test_calculate_win_payment(self): 90 | """Test that the calculate_payment function correctly calculates the win dividend""" 91 | player_roll = [2, 2, 2] 92 | dealer_roll = [4, 5, 6] 93 | bet = 50 94 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 95 | self.assertEqual(dividend, 150) 96 | 97 | def test_calculate_lose_payment(self): 98 | """Test that the calculate_payment function correctly calculates the loss dividend.""" 99 | player_roll = [4, 5, 6] 100 | dealer_roll = [2, 2, 2] 101 | bet = 50 102 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 103 | self.assertEqual(dividend, -50) 104 | 105 | def test_calculate_lose_payment_negative(self): 106 | """Test that the calculate_payment function correctly calculates the dividend based on the negative score""" 107 | player_roll = [1, 2, 3] 108 | dealer_roll = [2, 3, 4] 109 | bet = 50 110 | dividend = self.logic.calculate_payment(player_roll, dealer_roll, bet) 111 | self.assertEqual(dividend, -100) 112 | 113 | 114 | if __name__ == '__main__': 115 | unittest.main() 116 | -------------------------------------------------------------------------------- /Games/chin_chiro/tests/test_player.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import patch 3 | from player import Player 4 | 5 | 6 | class TestPlayer(unittest.TestCase): 7 | def setUp(self): 8 | self.player = Player(initial_balance=100) 9 | 10 | @patch('builtins.input', side_effect=['-10', 'a', '100']) 11 | def test_set_initial_balance(self, mock_input): 12 | """Test that the set_initial_balance function handles invalid input and sets the valid initial balance""" 13 | self.player.set_initial_balance() 14 | self.assertEqual(mock_input.call_count, 3) 15 | self.assertEqual(self.player.balance, 100) 16 | 17 | @patch('builtins.input', side_effect=['-10', 'a', '200', '50']) 18 | def test_set_bet(self, mock_input): 19 | """Test that the set_bet function handles invalid input and sets the valid bet amount""" 20 | self.player.balance = 100 21 | bet = self.player.set_bet() 22 | self.assertEqual(mock_input.call_count, 4) 23 | self.assertEqual(bet, 50) 24 | 25 | def test_get_current_balance(self): 26 | """Test that the get_current_balance function correctly calculates the current balance""" 27 | 28 | # Test for balance increase 29 | self.player.balance = 100 30 | self.player.get_current_balance(50) 31 | self.assertEqual(self.player.balance, 150) 32 | 33 | # Test for balance decrease 34 | self.player.get_current_balance(-50) 35 | self.assertEqual(self.player.balance, 100) 36 | 37 | @patch('builtins.input', side_effect=['a', 'y']) 38 | def test_ask_continue(self, mock_input): 39 | """Test that the ask_continue function correctly handles valid and invalid input""" 40 | choice = self.player.ask_continue() 41 | self.assertEqual(mock_input.call_count, 2) 42 | self.assertTrue(choice) 43 | 44 | 45 | if __name__ == '__main__': 46 | unittest.main() 47 | -------------------------------------------------------------------------------- /Games/comp_sci_quiz/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # CompSci Quiz 8 | 9 | 1. How well do you think you know about CompSci? 10 | 2. Play this quiz game to find out! 11 | 12 | ## Features 13 | 1. GUI using tkinter. 14 | 2. True or False questions. 15 | 3. Random 10 questions are fetched from Open Trivia DB each time you run it. 16 | 17 | ## How to play 18 | 1. Fork the repo by clicking the fork logo on the top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 20 | 3. Head to the comp_sci_quiz folder 21 | 4. Run the file using python command `python main.py` -------------------------------------------------------------------------------- /Games/comp_sci_quiz/data.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | parameters = { 4 | "amount": 10, 5 | "category": 18, 6 | "type": "boolean", 7 | } 8 | 9 | response = requests.get(url="https://opentdb.com/api.php", params=parameters) 10 | response.raise_for_status() 11 | 12 | data = response.json() 13 | 14 | question_data = data["results"] -------------------------------------------------------------------------------- /Games/comp_sci_quiz/images/false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/comp_sci_quiz/images/false.png -------------------------------------------------------------------------------- /Games/comp_sci_quiz/images/true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/comp_sci_quiz/images/true.png -------------------------------------------------------------------------------- /Games/comp_sci_quiz/main.py: -------------------------------------------------------------------------------- 1 | from question_model import Question 2 | from data import question_data 3 | from quiz_brain import QuizBrain 4 | from ui import QuizInterface 5 | 6 | question_bank = [] 7 | for question in question_data: 8 | question_text = question["question"] 9 | question_answer = question["correct_answer"] 10 | new_question = Question(question_text, question_answer) 11 | question_bank.append(new_question) 12 | 13 | 14 | quiz = QuizBrain(question_bank) 15 | quiz_ui = QuizInterface(quiz) 16 | -------------------------------------------------------------------------------- /Games/comp_sci_quiz/question_model.py: -------------------------------------------------------------------------------- 1 | class Question: 2 | 3 | def __init__(self, q_text, q_answer): 4 | self.text = q_text 5 | self.answer = q_answer 6 | -------------------------------------------------------------------------------- /Games/comp_sci_quiz/quiz_brain.py: -------------------------------------------------------------------------------- 1 | import html 2 | 3 | class QuizBrain: 4 | 5 | def __init__(self, q_list): 6 | self.question_number = 0 7 | self.score = 0 8 | self.question_list = q_list 9 | self.current_question = None 10 | 11 | def still_has_questions(self): 12 | return self.question_number < len(self.question_list) 13 | 14 | def next_question(self): 15 | self.current_question = self.question_list[self.question_number] 16 | self.question_number += 1 17 | q_text = html.unescape(self.current_question.text) 18 | return f"Q.{self.question_number}: {q_text}" 19 | 20 | def check_answer(self, user_answer): 21 | correct_answer = self.current_question.answer 22 | if user_answer.lower() == correct_answer.lower(): 23 | self.score += 1 24 | return True 25 | else: 26 | return False 27 | -------------------------------------------------------------------------------- /Games/comp_sci_quiz/ui.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from quiz_brain import QuizBrain 3 | 4 | THEME_COLOR = "#375362" 5 | 6 | class QuizInterface: 7 | 8 | def __init__(self, quiz_brain: QuizBrain): 9 | self.quiz = quiz_brain 10 | 11 | self.window = Tk() 12 | self.window.title("Comp-Sci Quiz") 13 | self.window.config(padx=20, pady=20, bg=THEME_COLOR) 14 | self.window.resizable(width=False, height=False) 15 | 16 | self.score_label = Label(text="Score: 0", fg="white", bg=THEME_COLOR) 17 | self.score_label.grid(row=0, column=1) 18 | 19 | self.canvas = Canvas(width=300, height=250, bg="white") 20 | self.question_text = self.canvas.create_text( 21 | 150, 22 | 125, 23 | width=280, 24 | text="Some Question Text", 25 | fill=THEME_COLOR, 26 | font=("Arial", 20, "italic") 27 | ) 28 | self.canvas.grid(row=1, column=0, columnspan=2, pady=50) 29 | 30 | true_image = PhotoImage(file="images/true.png") 31 | self.true_button = Button(image=true_image, highlightthickness=0, command=self.true_pressed) 32 | self.true_button.grid(row=2, column=0) 33 | 34 | false_image = PhotoImage(file="images/false.png") 35 | self.false_button = Button(image=false_image, highlightthickness=0, command=self.false_pressed) 36 | self.false_button.grid(row=2, column=1) 37 | 38 | self.get_next_question() 39 | 40 | self.window.mainloop() 41 | 42 | def get_next_question(self): 43 | self.canvas.config(bg="white") 44 | if self.quiz.still_has_questions(): 45 | self.score_label.config(text=f"Score: {self.quiz.score}") 46 | q_text = self.quiz.next_question() 47 | self.canvas.itemconfig(self.question_text, text=q_text) 48 | else: 49 | self.canvas.itemconfig(self.question_text, text="You've reached the end of the quiz.") 50 | self.true_button.config(state="disabled") 51 | self.false_button.config(state="disabled") 52 | 53 | def true_pressed(self): 54 | self.give_feedback(self.quiz.check_answer("True")) 55 | 56 | def false_pressed(self): 57 | is_right = self.quiz.check_answer("False") 58 | self.give_feedback(is_right) 59 | 60 | def give_feedback(self, is_right): 61 | if is_right: 62 | self.canvas.config(bg="green") 63 | else: 64 | self.canvas.config(bg="red") 65 | self.window.after(1000, self.get_next_question) 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Games/etch_a_sketch/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Etch A Sketch 8 | 9 | ## Rules 10 | - W, A, S, D : Move 11 | - C : Clear 12 | - E : Color selection 13 | - SPACE : Toggle pen on/off 14 | 15 | ## How to play 16 | 1. Fork the repo by clicking the fork logo the on top right 17 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 18 | 3. Head to the etch_a_sketch folder 19 | 4. Run the file using python command `python etch_a_sketch.py` 20 | -------------------------------------------------------------------------------- /Games/etch_a_sketch/etch_a_sketch.py: -------------------------------------------------------------------------------- 1 | import turtle 2 | 3 | pointer = turtle.Turtle() 4 | screen = turtle.Screen() 5 | colors = ["red", "blue", "green", "yellow", "orange", "black", "purple"] 6 | 7 | def intro(): 8 | while True: 9 | inp = turtle.textinput(" Etch A Sketch", 10 | """ Welcome!\n 11 | W, A ,S D : Move 12 | Space : Toggle pen 13 | C : Clear 14 | E : Color selection 15 | 16 | Enter 'Start' to start! 17 | """).lower() 18 | if inp == 'start': 19 | break 20 | 21 | def move_forward(): 22 | pointer.fd(10) 23 | 24 | def move_backward(): 25 | pointer.bk(10) 26 | 27 | def tilt_left(): 28 | pointer.lt(10) 29 | 30 | def tilt_right(): 31 | pointer.rt(10) 32 | 33 | def on_off(): 34 | if pointer.isdown(): 35 | pointer.penup() 36 | else: 37 | pointer.pendown() 38 | 39 | def clear(): 40 | turtle.resetscreen() 41 | 42 | def color(): 43 | while True: 44 | color = turtle.textinput(" Color Selection", 45 | "Red, Blue, Green, Yellow, Orange, Black, Purple").lower() 46 | if color in colors: 47 | break 48 | pointer.color(color) 49 | turtle.listen() 50 | 51 | intro() 52 | turtle.onkeypress(move_forward, "w") 53 | turtle.onkeypress(move_backward, "s") 54 | turtle.onkeypress(tilt_left, "a") 55 | turtle.onkeypress(tilt_right, "d") 56 | turtle.onkey(on_off, "space") 57 | turtle.onkey(clear, "c") 58 | turtle.onkey(color, "e") 59 | 60 | turtle.listen() 61 | turtle.mainloop() 62 | -------------------------------------------------------------------------------- /Games/gambler/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Name of your game 8 | ## Rules 9 | 1. Make a bet 10 | 2. Pick your cup 11 | 3. Enjoy! 12 | 13 | ## How to play 14 | 1. Fork the repo by clicking the fork logo on the top right 15 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 16 | 3. Head to the gambler folder 17 | 4. Run the file using python command `python gambler.py` 18 | 19 | -------------------------------------------------------------------------------- /Games/gambler/gambler.py: -------------------------------------------------------------------------------- 1 | import random 2 | import os 3 | from sys import platform 4 | import time 5 | # Clears command line 6 | 7 | def clear(): 8 | if platform == "linux" or platform == "linux2": 9 | # linux 10 | os.system("clear") 11 | elif platform == "darwin": 12 | # OS X 13 | os.system("clear") 14 | elif platform == "win32": 15 | # Windows... 16 | os.system("CLS") 17 | 18 | def main(): 19 | print("Hello!") 20 | time.sleep(0.5) 21 | print("Welcome to The Gambler Game!") 22 | time.sleep(1) 23 | balance = 100 24 | willing_to_quit = False 25 | print(f"--Your starting balance is ${balance}") 26 | while balance > 0 and willing_to_quit == False: 27 | bet = input(f"Make a bet, you have ${balance}, or if you want to quit press q \n") 28 | if bet == "q": 29 | willing_to_quit = True 30 | continue 31 | else: 32 | try: 33 | bet = int(bet) 34 | except: 35 | print("WRONG NUMBER,\n try again using amount affordable for your balance") 36 | continue 37 | if bet <= balance: 38 | guess =-1 39 | while guess > 3 or guess < 1: 40 | guess = int(input("Pick a cup from 1-3,\n")) 41 | if guess > 3 or guess < 1: 42 | print("Invalid entry: Please select cup between 1 and 3") 43 | answer = random.randint(1,3) 44 | print("Checkcking your luck!") 45 | if answer == guess: 46 | print("YES!YES!YES!") 47 | balance+=bet 48 | else: 49 | print('Wrong cup!') 50 | balance-=bet 51 | time.sleep(0.4) 52 | else: 53 | print("WRONG NUMBER,\n try again using amount affordable for your balance") 54 | if balance <= 0: 55 | print("GAME OVER!") 56 | elif balance > 100: 57 | print("GOOD JOB") 58 | elif balance < 100: 59 | print("Next time will be better") 60 | else: 61 | print("Interesting play") 62 | if __name__ == "__main__": 63 | clear() 64 | main() -------------------------------------------------------------------------------- /Games/guess_the_number/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # BlackJack 9 | 10 | ## Rules 11 | 1. Guess the number! 12 | 2. There are 3 difficulty levels: Easy, Hard, and Lucky 13 | 3. Easy mode : 10 chances to guess the number 1 -100 14 | 4. Hard mode : 5 chances to guess the number 1- 100 15 | 5. Lucky mode : 1 chance to guess the number 1 - 50 16 | 17 | ## How to play 18 | 1. Fork the repo by clicking the fork logo the on top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 20 | 3. Head to the guess_the_number folder 21 | 4. Run the file using python command `guess_the_num.py` 22 | -------------------------------------------------------------------------------- /Games/guess_the_number/guess_the_num.py: -------------------------------------------------------------------------------- 1 | import random 2 | import os 3 | from sys import platform 4 | from time import sleep 5 | 6 | # Clears command line 7 | def clear(): 8 | if platform == "linux" or platform == "linux2": 9 | # linux 10 | os.system("clear") 11 | elif platform == "darwin": 12 | # OS X 13 | os.system("clear") 14 | elif platform == "win32": 15 | # Windows... 16 | os.system("CLS") 17 | 18 | MIN = 1 19 | MAX = 100 20 | 21 | def get_guess(): 22 | while True: 23 | player_guess = input("Choose a number: ") 24 | if player_guess.isdigit(): 25 | player_guess = int(player_guess) 26 | if MIN < player_guess < MAX: 27 | break 28 | else: 29 | print("The number has to be 1 to 100") 30 | else: 31 | print(f"{player_guess} is not a number!") 32 | return player_guess 33 | 34 | 35 | def get_randint(): 36 | random_number = random.randint(0,100) 37 | return random_number 38 | 39 | def get_lucky(): 40 | lucky_num = random.randint(1, 10) 41 | return lucky_num 42 | 43 | 44 | def mode(): 45 | while True: 46 | print("Easy: 10 chances | Hard: 5 chances") 47 | print("You're feeling extremely lucky? try `LUCKY`\n") 48 | mode = input("Choose your difficulty level\n'Easy' 'Hard' 'LUCKY' : ") 49 | if isinstance(mode, str): 50 | mode = mode.lower() 51 | if mode == "easy" or mode == "hard" or mode == "lucky": 52 | break 53 | else: 54 | print("You have to choose 'easy' 'hard' 'lucky'!") 55 | else: 56 | print("You hav to choose 'easy' 'hard' 'lucky'!") 57 | return mode 58 | 59 | 60 | def main(): 61 | lives = 0 62 | 63 | while True: 64 | play = input("Press enter to play (`q` to quit)") 65 | clear() 66 | if play == "q": 67 | exit() 68 | 69 | level = mode() 70 | if level == "easy": 71 | lives = 10 72 | elif level == "hard": 73 | lives = 5 74 | else: 75 | lives = 1 76 | ans = get_lucky() 77 | clear() 78 | print("You have ONLY 1 chance to guess the number") 79 | print("The number is between 1 to 50") 80 | print("Let's see how lucky you are") 81 | 82 | guess = get_guess() 83 | if guess == ans: 84 | print(" CONGRATS!") 85 | print("WOW you really are lucky!") 86 | print("possibility was 2%") 87 | else: 88 | print(f"The number was {ans}") 89 | 90 | for i in range(5, 0, -1): 91 | sleep(1) 92 | print(f"Restarting the game in {i} seconds...", end="\r") 93 | clear() 94 | main() 95 | 96 | 97 | ans = get_randint() 98 | 99 | while lives > 0: 100 | guess = get_guess() 101 | lives -= 1 102 | if guess == ans: 103 | print("Congrats! you win the game!") 104 | break 105 | elif guess > ans: 106 | print(f"\nLower than {guess}\n") 107 | print(f"Remaining guess: {lives}") 108 | else: 109 | print(f"\nHigher than {guess}\n") 110 | print(f"Remaining guess: {lives}") 111 | 112 | if lives == 0: 113 | print(f"\nThe number was {ans}!") 114 | 115 | for i in range(5, 0, -1): 116 | sleep(1) 117 | print(f"Restarting the game in {i} seconds...", end="\r") 118 | clear() 119 | main() 120 | 121 | 122 | clear() 123 | print(" Welcome to Geuss The Number!") 124 | print("Rules are simple, I'll choose a number 1 to 100 and you have to guess it right!\n") 125 | main() -------------------------------------------------------------------------------- /Games/hangman/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Hang Man 9 | 10 | ## Rules 11 | 1. Guess the secret word before the stick figure is hung 12 | 2. Player has 6 lives 13 | 14 | ## How to play 15 | 1. Fork the repo by clicking the fork logo the on top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 17 | 3. Head to the hangman folder 18 | 4. Run the file using python command `python hangman.py` 19 | 20 | -------------------------------------------------------------------------------- /Games/hangman/asciiart.py: -------------------------------------------------------------------------------- 1 | stages = [''' 2 | +---+ 3 | | | 4 | O | 5 | /|\ | 6 | / \ | 7 | | 8 | ========= 9 | ''', ''' 10 | +---+ 11 | | | 12 | O | 13 | /|\ | 14 | / | 15 | | 16 | ========= 17 | ''', ''' 18 | +---+ 19 | | | 20 | O | 21 | /|\ | 22 | | 23 | | 24 | ========= 25 | ''', ''' 26 | +---+ 27 | | | 28 | O | 29 | /| | 30 | | 31 | | 32 | =========''', ''' 33 | +---+ 34 | | | 35 | O | 36 | | | 37 | | 38 | | 39 | ========= 40 | ''', ''' 41 | +---+ 42 | | | 43 | O | 44 | | 45 | | 46 | | 47 | ========= 48 | ''', ''' 49 | +---+ 50 | | | 51 | | 52 | | 53 | | 54 | | 55 | ========= 56 | '''] 57 | 58 | logo = ''' 59 | _______ _ _______ _______ _______ _ 60 | |\ /|( ___ )( ( /|( ____ \ ( )( ___ )( ( /| 61 | | ) ( || ( ) || \ ( || ( \/ | () () || ( ) || \ ( | 62 | | (___) || (___) || \ | || | | || || || (___) || \ | | 63 | | ___ || ___ || (\ \) || | ____ | |(_)| || ___ || (\ \) | 64 | | ( ) || ( ) || | \ || | \_ ) | | | || ( ) || | \ | 65 | | ) ( || ) ( || ) \ || (___) | | ) ( || ) ( || ) \ | 66 | |/ \||/ \||/ )_)(_______) |/ \||/ \||/ )_) 67 | 68 | ''' 69 | 70 | 71 | word_list = [ 72 | 'abruptly', 73 | 'absurd', 74 | 'abyss', 75 | 'affix', 76 | 'askew', 77 | 'avenue', 78 | 'awkward', 79 | 'axiom', 80 | 'azure', 81 | 'bagpipes', 82 | 'bandwagon', 83 | 'banjo', 84 | 'bayou', 85 | 'beekeeper', 86 | 'bikini', 87 | 'blitz', 88 | 'blizzard', 89 | 'boggle', 90 | 'bookworm', 91 | 'boxcar', 92 | 'boxful', 93 | 'buckaroo', 94 | 'buffalo', 95 | 'buffoon', 96 | 'buxom', 97 | 'buzzard', 98 | 'buzzing', 99 | 'buzzwords', 100 | 'caliph', 101 | 'cobweb', 102 | 'cockiness', 103 | 'croquet', 104 | 'crypt', 105 | 'curacao', 106 | 'cycle', 107 | 'daiquiri', 108 | 'dirndl', 109 | 'disavow', 110 | 'dizzying', 111 | 'duplex', 112 | 'dwarves', 113 | 'embezzle', 114 | 'equip', 115 | 'espionage', 116 | 'euouae', 117 | 'exodus', 118 | 'faking', 119 | 'fishhook', 120 | 'fixable', 121 | 'fjord', 122 | 'flapjack', 123 | 'flopping', 124 | 'fluffiness', 125 | 'flyby', 126 | 'foxglove', 127 | 'frazzled', 128 | 'frizzled', 129 | 'fuchsia', 130 | 'funny', 131 | 'gabby', 132 | 'galaxy', 133 | 'galvanize', 134 | 'gazebo', 135 | 'giaour', 136 | 'gizmo', 137 | 'glowworm', 138 | 'glyph', 139 | 'gnarly', 140 | 'gnostic', 141 | 'gossip', 142 | 'grogginess', 143 | 'haiku', 144 | 'haphazard', 145 | 'hyphen', 146 | 'iatrogenic', 147 | 'icebox', 148 | 'injury', 149 | 'ivory', 150 | 'ivy', 151 | 'jackpot', 152 | 'jaundice', 153 | 'jawbreaker', 154 | 'jaywalk', 155 | 'jazziest', 156 | 'jazzy', 157 | 'jelly', 158 | 'jigsaw', 159 | 'jinx', 160 | 'jiujitsu', 161 | 'jockey', 162 | 'jogging', 163 | 'joking', 164 | 'jovial', 165 | 'joyful', 166 | 'juicy', 167 | 'jukebox', 168 | 'jumbo', 169 | 'kayak', 170 | 'kazoo', 171 | 'keyhole', 172 | 'khaki', 173 | 'kilobyte', 174 | 'kiosk', 175 | 'kitsch', 176 | 'kiwifruit', 177 | 'klutz', 178 | 'knapsack', 179 | 'larynx', 180 | 'lengths', 181 | 'lucky', 182 | 'luxury', 183 | 'lymph', 184 | 'marquis', 185 | 'matrix', 186 | 'megahertz', 187 | 'microwave', 188 | 'mnemonic', 189 | 'mystify', 190 | 'naphtha', 191 | 'nightclub', 192 | 'nowadays', 193 | 'numbskull', 194 | 'nymph', 195 | 'onyx', 196 | 'ovary', 197 | 'oxidize', 198 | 'oxygen', 199 | 'pajama', 200 | 'peekaboo', 201 | 'phlegm', 202 | 'pixel', 203 | 'pizazz', 204 | 'pneumonia', 205 | 'polka', 206 | 'pshaw', 207 | 'psyche', 208 | 'puppy', 209 | 'puzzling', 210 | 'quartz', 211 | 'queue', 212 | 'quips', 213 | 'quixotic', 214 | 'quiz', 215 | 'quizzes', 216 | 'quorum', 217 | 'razzmatazz', 218 | 'rhubarb', 219 | 'rhythm', 220 | 'rickshaw', 221 | 'schnapps', 222 | 'scratch', 223 | 'shiv', 224 | 'snazzy', 225 | 'sphinx', 226 | 'spritz', 227 | 'squawk', 228 | 'staff', 229 | 'strength', 230 | 'strengths', 231 | 'stretch', 232 | 'stronghold', 233 | 'stymied', 234 | 'subway', 235 | 'swivel', 236 | 'syndrome', 237 | 'thriftless', 238 | 'thumbscrew', 239 | 'topaz', 240 | 'transcript', 241 | 'transgress', 242 | 'transplant', 243 | 'triphthong', 244 | 'twelfth', 245 | 'twelfths', 246 | 'unknown', 247 | 'unworthy', 248 | 'unzip', 249 | 'uptown', 250 | 'vaporize', 251 | 'vixen', 252 | 'vodka', 253 | 'voodoo', 254 | 'vortex', 255 | 'voyeurism', 256 | 'walkway', 257 | 'waltz', 258 | 'wave', 259 | 'wavy', 260 | 'waxy', 261 | 'wellspring', 262 | 'wheezy', 263 | 'whiskey', 264 | 'whizzing', 265 | 'whomever', 266 | 'wimpy', 267 | 'witchcraft', 268 | 'wizard', 269 | 'woozy', 270 | 'wristwatch', 271 | 'wyvern', 272 | 'xylophone', 273 | 'yachtsman', 274 | 'yippee', 275 | 'yoked', 276 | 'youthful', 277 | 'yummy', 278 | 'zephyr', 279 | 'zigzag', 280 | 'zigzagging', 281 | 'zilch', 282 | 'zipper', 283 | 'zodiac', 284 | 'zombie', 285 | ] -------------------------------------------------------------------------------- /Games/hangman/hangman.py: -------------------------------------------------------------------------------- 1 | import random 2 | from asciiart import * 3 | import os 4 | from sys import platform 5 | 6 | # Clears command line 7 | def clear(): 8 | if platform == "linux" or platform == "linux2": 9 | # linux 10 | os.system("clear") 11 | elif platform == "darwin": 12 | # OS X 13 | os.system("clear") 14 | elif platform == "win32": 15 | # Windows... 16 | os.system("CLS") 17 | 18 | word = random.choice(word_list) 19 | tries = 6 20 | blank = [] 21 | word_length = len(word) 22 | 23 | clear() 24 | print(logo) 25 | 26 | for i in word: 27 | blank += "_" 28 | 29 | print(blank) 30 | gameOver = False 31 | while not gameOver: 32 | guess = input("Guess a letter: ").lower() 33 | 34 | if guess in blank: 35 | print(f"You've already guessed {guess}") 36 | 37 | #Check guessed letter 38 | for position in range(word_length): 39 | letter = word[position] 40 | #print(f"Current position: {position}\n Current letter: {letter}\n Guessed letter: {guess}") 41 | if letter == guess: 42 | blank[position] = letter 43 | 44 | #Check if user is wrong. 45 | if guess not in word: 46 | print(f"You guessed {guess}, that's not in the word. You lose a life.") 47 | 48 | tries -= 1 49 | if tries == 0: 50 | gameOver = True 51 | print("You lose.") 52 | 53 | #Join all the elements in the list and turn it into a String. 54 | print(f"{' '.join(blank)}") 55 | 56 | #Check if user has got all letters. 57 | if "_" not in blank: 58 | gameOver = True 59 | print("You win.") 60 | 61 | print(stages[tries]) 62 | -------------------------------------------------------------------------------- /Games/ludo_king/ludo-king.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import sys 3 | import random 4 | 5 | # Initialization Pygame 6 | pygame.init() 7 | 8 | # Set Colors 9 | WHITE = (255, 255, 255) 10 | RED = (255, 0, 0) 11 | GREEN = (0, 255, 0) 12 | BLUE = (0, 0, 255) 13 | YELLOW = (255, 255, 0) 14 | 15 | # Create the window 16 | width, height = 600, 600 17 | screen = pygame.display.set_mode((width, height)) 18 | pygame.display.set_caption("Ludo King") 19 | 20 | # Set positions for the pawns 21 | positions = { 22 | 'red': [(100, 500), (200, 500), (100, 400), (200, 400)], 23 | 'green': [(400, 500), (500, 500), (400, 400), (500, 400)], 24 | 'blue': [(400, 100), (500, 100), (400, 200), (500, 200)], 25 | 'yellow': [(100, 100), (200, 100), (100, 200), (200, 200)] 26 | } 27 | 28 | # Define the dice 29 | dice = { 30 | 'value': 1, 31 | 'rect': pygame.Rect(250, 250, 100, 100) 32 | } 33 | 34 | # Function for dice roll 35 | def roll_dice(): 36 | return random.randint(1, 6) 37 | 38 | # Function for pawns movements 39 | def move_pawns(color, steps): 40 | for i in range(len(positions[color])): 41 | positions[color][i] = ( 42 | positions[color][i][0] + steps * 50, 43 | positions[color][i][1] 44 | ) 45 | 46 | # Basic loop 47 | while True: 48 | for event in pygame.event.get(): 49 | if event.type == pygame.QUIT: 50 | pygame.quit() 51 | sys.exit() 52 | 53 | if event.type == pygame.MOUSEBUTTONDOWN and dice['rect'].collidepoint(event.pos): 54 | dice['value'] = roll_dice() 55 | move_pawns('red', dice['value']) # Move the pawns based on the value of dice 56 | 57 | # Clear the window 58 | screen.fill(WHITE) 59 | 60 | # Drawing the positions of the pawns 61 | for color, pos_list in positions.items(): 62 | for pos in pos_list: 63 | pygame.draw.circle(screen, eval(color.upper()), pos, 20) 64 | 65 | # Daw the dice 66 | pygame.draw.rect(screen, WHITE, dice['rect']) 67 | pygame.draw.rect(screen, RED, dice['rect'], 2) 68 | font = pygame.font.SysFont(None, 36) 69 | text = font.render(str(dice['value']), True, RED) 70 | screen.blit(text, (dice['rect'].x + 40, dice['rect'].y + 40)) 71 | 72 | # Refresh the window 73 | pygame.display.flip() 74 | 75 | -------------------------------------------------------------------------------- /Games/ludo_king/readme.md: -------------------------------------------------------------------------------- 1 | Ludo-King game 2 | 3 | 4 | In this particular file a simple version of the "Ludo King" game is presented. 5 | Any addition or correction can be made for the better functioning. 6 | 7 | ## Rules 8 | 1. Players roll a die and move their pawn by the number of dots that appear. 9 | 2. You can only move a pawn if you roll a six or if you have a pawn in the center circle. 10 | 11 | ## How to play 12 | 1. Fork the repo by clicking the fork logo the on top right 13 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 14 | 3. Head to the 'ludo-king' folder 15 | 4. Run the file using python command `ludo-king.py` 16 | 5. Follow the prompts in the console to play the game. Input the row and column numbers to place your symbol on the grid. 17 | 18 | Have fun playing Ludo-King! 19 | -------------------------------------------------------------------------------- /Games/memory_game/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Memory Game 9 | 10 | ## Game Description 11 | A classic memory card matching game where players test their recall and concentration skills. The objective is to find all matching pairs of cards on the board by flipping them over two at a time. 12 | 13 | ## Rules 14 | 1. The game is played on a 4x4 grid with hidden emoji symbols 15 | 2. Each symbol appears exactly twice on the board 16 | 3. Players take turns revealing two cards per move 17 | 4. If the two revealed cards match, they remain face-up 18 | 5. If the cards do not match, they are turned face-down again 19 | 6. The game continues until all pairs are matched 20 | 7. The goal is to match all pairs with the least number of moves 21 | 22 | ## How to play 23 | 1. Fork the repo by clicking the fork logo the on top right 24 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 25 | 3. Head to the memory_game folder 26 | 4. Run the file using python command `python memory-game.py` 27 | 28 | ## Gameplay Instructions 29 | - Enter row and column numbers to select cards 30 | - Try to remember the locations of previously revealed cards 31 | - Match all pairs to win the game 32 | - Your goal is to complete the game with the fewest moves possible 33 | 34 | ## Future Improvements 35 | - Add difficulty levels 36 | - Implement a scoring system 37 | - Create a graphical user interface (GUI) 38 | - Add multiplayer support 39 | 40 |

41 | 42 | 43 | 44 |

45 | 46 | -------------------------------------------------------------------------------- /Games/memory_game/memory-game.py: -------------------------------------------------------------------------------- 1 | import random 2 | import os 3 | import time 4 | 5 | class MemoryGame: 6 | def __init__(self, size=4): 7 | self.size = size 8 | self.symbols = ['🌟', '🌙', '🌍', '🌈', '🌺', '🍀', '🎵', '🎨'][:size*size//2] * 2 9 | self.board = [[' ' for _ in range(size)] for _ in range(size)] 10 | self.revealed = [[False for _ in range(size)] for _ in range(size)] 11 | self.shuffle_board() 12 | 13 | def shuffle_board(self): 14 | random.shuffle(self.symbols) 15 | for i in range(self.size): 16 | for j in range(self.size): 17 | self.board[i][j] = self.symbols[i * self.size + j] 18 | 19 | def clear_screen(self): 20 | os.system('cls' if os.name == 'nt' else 'clear') 21 | 22 | def display_board(self): 23 | self.clear_screen() 24 | print(" " + " ".join(str(i) for i in range(self.size))) 25 | for i in range(self.size): 26 | row = [self.board[i][j] if self.revealed[i][j] else '▢' for j in range(self.size)] 27 | print(f"{i} {' '.join(row)}") 28 | 29 | def get_move(self): 30 | while True: 31 | try: 32 | row = int(input("Enter row (0-3): ")) 33 | col = int(input("Enter column (0-3): ")) 34 | if 0 <= row < self.size and 0 <= col < self.size and not self.revealed[row][col]: 35 | return row, col 36 | print("Invalid move. Try again.") 37 | except ValueError: 38 | print("Please enter numbers only.") 39 | 40 | def play(self): 41 | pairs_found = 0 42 | moves = 0 43 | 44 | while pairs_found < (self.size * self.size) // 2: 45 | self.display_board() 46 | print(f"\nMoves: {moves} | Pairs found: {pairs_found}") 47 | 48 | # First card 49 | row1, col1 = self.get_move() 50 | self.revealed[row1][col1] = True 51 | self.display_board() 52 | 53 | # Second card 54 | row2, col2 = self.get_move() 55 | self.revealed[row2][col2] = True 56 | self.display_board() 57 | 58 | moves += 1 59 | 60 | # Check if pair matches 61 | if self.board[row1][col1] == self.board[row2][col2]: 62 | pairs_found += 1 63 | print("Match found!") 64 | else: 65 | print("No match...") 66 | self.revealed[row1][col1] = False 67 | self.revealed[row2][col2] = False 68 | 69 | time.sleep(1) 70 | 71 | print(f"\nCongratulations! You won in {moves} moves!") 72 | 73 | if __name__ == "__main__": 74 | game = MemoryGame() 75 | game.play() -------------------------------------------------------------------------------- /Games/minesweeper/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Minesweeper 8 | 9 | ## Rules 10 | 1. Find every mine in the field and place flags on them 11 | 2. Valid input to dig : ROW SPACE COLUMN `1 E` `4 A` `6 H` 12 | 3. Valid input to flag : ROW SPACE COLUMN F `1 E F` `4 A F` `6 H F` 13 | 4. Total of 8 bombs in 8x8 grid 14 | 5. You can change `MINE` `GRID` values for incereased/decreased difficulty 15 | 6. Good Luck! 16 | 17 | ## How to play 18 | 1. Fork the repo by clicking the fork logo the on top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 20 | 3. Head to the minesweeper folder 21 | 4. Run the file using python command `python minesweeper.py` 22 | -------------------------------------------------------------------------------- /Games/pizza_palour/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Pizza Palour 8 | 9 | ## Rules 10 | 1. The game is played by a single player. 11 | 2. The game presents a scenario where one goes to order a pizza 12 | 3. The player is comes to order for a pizza and and is then prompted to choose the options for the pizza 13 | 4. The player then choses the size, topping, flavour etc of his preferred pizza, 14 | 5. After choosing, the player is then informed of his bill, if he pays, his order becomes valid 15 | 6. If not, its Game Over! 16 | 17 | ## How to play 18 | 1. Fork the repo by clicking the fork logo the on top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 20 | 3. Open the 'pizza_palour' folder 21 | 4. Run the file using python command `python main.py` 22 | 5. Follow the prompts in the console to play the game. 23 | 24 | ## How to deply using Streamlit or run on localhost 25 | 1. create a python virtual environment: python -m venev 26 | 2. install required dependencies: pip install -r requirements.txt 27 | 3. run it on local host using following command: streamlit run streamlit_main.py 28 | 29 | ### Enjoy playing Treasure Island! 30 | -------------------------------------------------------------------------------- /Games/pizza_palour/main.py: -------------------------------------------------------------------------------- 1 | # Congratulations! you just got a job at python pizza, 2 | # Your first job is to build an automatic pizza orderin system 3 | # Based on user's order, work out the final bill 4 | 5 | # Pepperoni for small pizza = $2 6 | # Pepperoni for large and medium pizza = $3 7 | # Extra cheese for any size = $1 8 | 9 | # Example input: 10 | # size = L 11 | # add_pepperoni = "Y" 12 | # extra_cheese = "N" 13 | 14 | greetings = ("Welcome to Python Pizza ") 15 | name = (input("What is your name please? ")) 16 | print(greetings + name + "!") 17 | 18 | # Small_pizza = 15 #small_pizza 19 | # Medium_pizza = 20 #medium_pizza 20 | # Large_pizza = 25 #Large_pizz 21 | 22 | 23 | order = (input("What size of pizza would you like to have?\nWe have the following options:\nS for Small Pizza\nM for Medium-sized Pizza\nand L for Large pizza? ")) 24 | print(order) 25 | 26 | if order == "S": 27 | bill = 15 28 | print("Please pay $15 for yor order") 29 | elif order == "M": 30 | bill = 20 31 | print("Please pay $20 for yor order") 32 | elif order == "L": 33 | bill = 25 34 | print("Please pay $25 for your order") 35 | 36 | wants_pepperoni = (input("Do you want pepperoni Y or N ? ")) 37 | if wants_pepperoni == "Y": 38 | size_pepperoni = (input("Which size of pepperoni do you want: Small, Medium or Large? ")) 39 | print(size_pepperoni + "! " + "That's Excellent " + name) 40 | if size_pepperoni == "Small": 41 | bill += 2 42 | print(f"Your total bill is ${bill}") 43 | if size_pepperoni == "Medium": 44 | bill += 3 45 | print(f"Your total bill is ${bill}") 46 | if size_pepperoni == "Large": 47 | bill += 3 48 | print(f"Your total bill is ${bill}") 49 | else: 50 | print(f"Thank you for your order {name}; Your bill remains {bill}.\nPlease pay ${bill} to validate your order!") 51 | 52 | extra_cheese = (input("Do you want extra cheese Y or N?")) 53 | if extra_cheese == "Y": 54 | bill += 1 55 | print(f"Your Total bill is ${bill}") 56 | else: 57 | print(f"Thank you for your order {name},\n Please pay {bill} to validate your order!") -------------------------------------------------------------------------------- /Games/pizza_palour/requirements.txt: -------------------------------------------------------------------------------- 1 | streamlit>=1.27.0 -------------------------------------------------------------------------------- /Games/pizza_palour/streamlit_main.py: -------------------------------------------------------------------------------- 1 | # Congratulations! you just got a job at python pizza, 2 | # Your first job is to build an automatic pizza orderin system 3 | # Based on user's order, work out the final bill 4 | 5 | # Pepperoni for small pizza = $2 6 | # Pepperoni for large and medium pizza = $3 7 | # Extra cheese for any size = $1 8 | 9 | # Example input: 10 | # size = L 11 | # add_pepperoni = "Y" 12 | # extra_cheese = "N" 13 | import streamlit as st 14 | 15 | st.title("Welcome to Python Pizza! 🍕") 16 | st.subheader("Please follow the instructions to place your order! 😃") 17 | st.markdown("---") 18 | name = st.text_input('What is your name please?') 19 | if name: 20 | st.write("Greetings " + str(name)+ "😁") 21 | st.markdown("---") 22 | bill = 0 23 | 24 | # Small_pizza = 15 #small_pizza 25 | # Medium_pizza = 20 #medium_pizza 26 | # Large_pizza = 25 #Large_pizz 27 | 28 | 29 | # order = (input("What size of pizza would you like to have?\nWe have the following options:\nS for Small Pizza\nM for Medium-sized Pizza\nand L for Large pizza? ")) 30 | st.write("What size of pizza would you like to have?") 31 | order = st.radio("We have the following options", ["Small", "Medium", "Large"], captions=["$15", "$20", "$25"], index = None) 32 | if order == 'Small': 33 | bill = 15 34 | if order == 'Medium': 35 | bill = 20 36 | if order == 'Large': 37 | bill = 25 38 | st.write("Current Bill without any toppings: ", bill) 39 | st.markdown("---") 40 | if order: 41 | wants_pepperoni = st.radio("Do you want Pepperoni in your pizza", ["Yes", "No"], index= None) 42 | if wants_pepperoni == "Yes": 43 | size_pepperoni = st.radio("Which size of pepperoni do you want:", ["Small", "Medium", "Large"], captions=["$2", "$3", "$3"], index= None) 44 | if size_pepperoni == "Small": 45 | bill+=2 46 | if size_pepperoni == "Medium": 47 | bill+=3 48 | if size_pepperoni == "Large": 49 | bill+=3 50 | extra_cheese = st.radio("Do you want Extra Cheese in your pizza", ["Yes", "No"], index= None) 51 | if extra_cheese == "Yes": 52 | bill+=1 53 | st.markdown("---") 54 | st.write("Your total bill is $", bill) 55 | st.write("Thank you for your order "+str(name)+" 😁Please pay $"+str(bill)+" to validate your order!") 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Games/pong/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Pong 8 | 9 | ## Rules 10 | 1. 2 player game 11 | 2. Left side of the player can move the paddle using `w` ans `s` 12 | 3. Right side of the player can move the paddle using `Up arrow` and `Down arrow` 13 | 4. The speed of the ball is random each time it bounces off the paddle 14 | 15 | ## How to play 16 | 1. Fork the repo by clicking the fork logo the on top right 17 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 18 | 3. Head to the pong folder 19 | 4. Run the file using python command `python main.py` -------------------------------------------------------------------------------- /Games/pong/ball.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | from playsound import playsound 3 | 4 | # Create a ball 5 | class Ball(Turtle): 6 | def __init__(self): 7 | super().__init__() 8 | 9 | self.pu() 10 | self.shape("square") 11 | self.color("white") 12 | self.speed(20) 13 | self.x_position = 10 14 | self.y_position = 10 15 | 16 | # Move ball 17 | def move(self): 18 | new_x = self.xcor() + self.x_position 19 | new_y = self.ycor() + self.y_position 20 | self.setpos(new_x, new_y) 21 | 22 | # Bounce when hit upper and lower walls / flip Y-axis 23 | def bounce_wall(self): 24 | self.y_position *= -1 25 | playsound('/bounce.wav') 26 | 27 | # Bounce when hit either paddles / flip X-axies 28 | def bounce_paddle(self): 29 | self.x_position *= -1 30 | playsound('/bounce.wav') 31 | # Resets ball position 32 | def reset(self): 33 | self.setpos(0, 0) 34 | -------------------------------------------------------------------------------- /Games/pong/bounce.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/pong/bounce.wav -------------------------------------------------------------------------------- /Games/pong/main.py: -------------------------------------------------------------------------------- 1 | from turtle import Screen 2 | from paddle import Paddle 3 | from ball import Ball 4 | from time import sleep 5 | from score import score 6 | from random import choice 7 | 8 | # Global val 9 | SPEEDS = [.08, .07, .06, .05, .04, .03, .02, .01] 10 | 11 | screen = Screen() 12 | screen.setup(width=800, height=600) 13 | screen.bgcolor("black") 14 | screen.title("Pong") 15 | screen.tracer(0) 16 | screen.listen() 17 | 18 | # Paddle X-axis position 19 | l_paddle = Paddle(-350) 20 | r_paddle = Paddle(350) 21 | 22 | ball = Ball() 23 | 24 | scoreboard = score() 25 | 26 | screen.onkeypress(r_paddle.up, "Up") 27 | screen.onkeypress(r_paddle.down, "Down") 28 | screen.onkeypress(l_paddle.up, "w") 29 | screen.onkeypress(l_paddle.down, "s") 30 | 31 | 32 | # Main game loop 33 | game_on = True 34 | speed = 0.07 35 | while game_on: 36 | # time.sleep() = speed of the ball / lower = faster 37 | sleep(speed) 38 | ball.move() 39 | screen.update() 40 | 41 | if ball.ycor() > 280 or ball.ycor() < -270: 42 | ball.bounce_wall() 43 | 44 | # When ball hits the either paddle/ flip the X-axis 45 | # Random speed 46 | if ball.distance(r_paddle) < 50 and ball.xcor() > 320 or ball.distance(l_paddle) < 50 and ball.xcor() < -320: 47 | ball.bounce_paddle() 48 | speed = choice(SPEEDS) 49 | 50 | # Left paddle scores 51 | if ball.xcor() > 360: 52 | scoreboard.left_point() 53 | ball.reset() 54 | ball.bounce_paddle() 55 | speed = 0.07 56 | 57 | # Right paddle scores 58 | if ball.xcor() < -360: 59 | scoreboard.right_point() 60 | ball.reset() 61 | ball.bounce_paddle() 62 | speed = 0.07 63 | 64 | 65 | 66 | screen.exitonclick() -------------------------------------------------------------------------------- /Games/pong/paddle.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | 3 | class Paddle(Turtle): 4 | def __init__(self, position): 5 | super().__init__() 6 | 7 | self.shape("square") 8 | self.color("white") 9 | self.pu() 10 | self.speed(20) 11 | self.shapesize(stretch_wid=5, stretch_len=1) 12 | self.setpos(position, 0) 13 | 14 | # Move paddle up 15 | def up(self): 16 | new_y = self.ycor() + 20 17 | self.sety(new_y) 18 | 19 | # Move paddle down 20 | def down(self): 21 | new_y = self.ycor() - 20 22 | self.sety(new_y) -------------------------------------------------------------------------------- /Games/pong/score.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | 3 | class score(Turtle): 4 | def __init__(self): 5 | super().__init__() 6 | 7 | self.color("white") 8 | self.pu() 9 | self.hideturtle() 10 | self.left_score = 0 11 | self.right_score = 0 12 | self.update() 13 | 14 | # Updates scoreboard 15 | def update(self): 16 | self.clear() 17 | self.setpos(-150, 200) 18 | self.write(f"Score: {self.left_score}", align="center", font=('Arial', 18, 'normal')) 19 | 20 | self.setpos(150, 200) 21 | self.write(f"Score: {self.right_score}", align="center", font=('Arial', 18, 'normal')) 22 | 23 | # Add score to left scoreboard 24 | def left_point(self): 25 | self.left_score += 1 26 | self.update() 27 | 28 | # Add score to right scoreboard 29 | def right_point(self): 30 | self.right_score += 1 31 | self.update() -------------------------------------------------------------------------------- /Games/road_crossing/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Road crossing 8 | 9 | ## Rules 10 | 1. `Up arrow` to move up and `Down arrow` to move down 11 | 2. The goal is to reach the finish line without getiing hit by a car 12 | 3. The speed of cars will increase everytime you level up 13 | 14 | ## How to play 15 | 1. Fork the repo by clicking the fork logo the on top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 17 | 3. Head to the road_crossing folder 18 | 4. Run the file using python command `python main.py` -------------------------------------------------------------------------------- /Games/road_crossing/animal.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | 3 | # Global val 4 | MOVE_DISTANCE = 10 5 | 6 | class Animal(Turtle): 7 | def __init__(self): 8 | super().__init__() 9 | 10 | self.pu() 11 | self.shape("turtle") 12 | self.color("green") 13 | self.setheading(90) 14 | self.sety(-280) 15 | 16 | 17 | def move_up(self): 18 | new_y = self.ycor() + MOVE_DISTANCE 19 | self.sety(new_y) 20 | 21 | 22 | def move_down(self): 23 | new_y = self.ycor() - MOVE_DISTANCE 24 | self.sety(new_y) 25 | 26 | 27 | def reset_animal(self): 28 | self.sety(-280) -------------------------------------------------------------------------------- /Games/road_crossing/cars.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | from random import randint, choice 3 | 4 | # Global val 5 | COLORS = ["red", "orange", "yellow", "green", "blue", "purple"] 6 | INCREASE_SPEED = 10 7 | STARTING_SPEED = 5 8 | 9 | class Cars: 10 | def __init__(self): 11 | self.all_cars = [] 12 | self.speed = STARTING_SPEED 13 | self.create_car() 14 | 15 | # Create cars / decreased # of cars with randint 16 | def create_car(self): 17 | chance = randint(1,5) 18 | if chance == 1: 19 | y_pos = randint(-250, 250) 20 | color = choice(COLORS) 21 | 22 | new_car = Turtle("square") 23 | new_car.pu() 24 | new_car.color(color) 25 | new_car.turtlesize(stretch_len=2, stretch_wid=1) 26 | new_car.setpos(300, y_pos) 27 | 28 | self.all_cars.append(new_car) 29 | 30 | 31 | # Move cars 32 | def move_cars(self): 33 | for car in self.all_cars: 34 | car.bk(self.speed) 35 | 36 | 37 | # Increase the speed of cars 38 | def level_up(self): 39 | for car in self.all_cars: 40 | car.setpos(1000 ,1000) 41 | self.all_cars = [] 42 | self.speed += INCREASE_SPEED 43 | self.create_car() 44 | self.move_cars() -------------------------------------------------------------------------------- /Games/road_crossing/level.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | 3 | class Level(Turtle): 4 | def __init__(self): 5 | super().__init__() 6 | self.lvl = 1 7 | self.create_level() 8 | 9 | 10 | # Create current level text 11 | def create_level(self): 12 | self.pu() 13 | self.hideturtle() 14 | self.setpos(-250, 260) 15 | self.write(f"Current level: {self.lvl}", font=("Courier", 18, "normal")) 16 | 17 | 18 | # Updates current level 19 | def level_up(self): 20 | self.reset() 21 | self.lvl += 1 22 | self.create_level() 23 | 24 | 25 | # Game over text 26 | def game_over(self): 27 | self.setpos(0, 0) 28 | self.write("GAME OVER",align="center", font=("Courier", 18, "normal")) 29 | -------------------------------------------------------------------------------- /Games/road_crossing/main.py: -------------------------------------------------------------------------------- 1 | from turtle import Screen 2 | from animal import Animal 3 | from cars import Cars 4 | from level import Level 5 | from time import sleep 6 | 7 | # turtle screen 8 | screen = Screen() 9 | screen.setup(width=600, height=600) 10 | screen.title("Road Crossing") 11 | screen.tracer(0) 12 | screen.listen() 13 | 14 | animal = Animal() 15 | car = Cars() 16 | display = Level() 17 | 18 | screen.onkeypress(animal.move_up, "Up") 19 | screen.onkeypress(animal.move_down, "Down") 20 | 21 | 22 | # Main loop 23 | game_on = True 24 | while game_on: 25 | sleep(.05) 26 | screen.update() 27 | car.create_car() 28 | car.move_cars() 29 | 30 | # Game over when hit by the car 31 | for each_car in car.all_cars: 32 | if each_car.distance(animal) < 25: 33 | display.game_over() 34 | game_on = False 35 | 36 | # Level up when the player reaches certain y_cor 37 | if animal.ycor() > 280: 38 | animal.reset_animal() 39 | display.level_up() 40 | car.level_up() 41 | 42 | 43 | screen.exitonclick() -------------------------------------------------------------------------------- /Games/rock_paper_scissors/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Rock Paper Scissor 9 | 10 | ## Rules 11 | 1. Rock beats Scissor, Paper beats Rock, Scissor beats Paper 12 | 2. Try to win as many rounds as possible. 13 | 14 | ## How to play 15 | 1. Fork the repo by clicking the fork logo the on top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 17 | 3. Head rock_paper_scissor folder 18 | 4. Run the file using python command `rock_paper_scissor.py` 19 | 20 | -------------------------------------------------------------------------------- /Games/rock_paper_scissors/rock_paper_scissors.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | from time import sleep 5 | 6 | choices = ['rock', 'paper', 'scissors'] 7 | 8 | player_score = 0 9 | cpu_score = 0 10 | round_counter = 0 11 | 12 | clear = lambda: os.system('cls') 13 | 14 | def clear(): 15 | if sys.platform in ["linux", "linux2", "darwin"]: 16 | # linux or OS X 17 | os.system("clear") 18 | elif sys.platform == "win32": 19 | # Windows 20 | os.system("cls") 21 | 22 | 23 | clear() 24 | print("Welcome to Rock Paper Scissors!") 25 | 26 | while True: 27 | cpu_choice = random.choice(choices) 28 | 29 | player_choice = input('Rock, Paper, or Scissors?\n').lower() 30 | 31 | if player_choice not in choices: 32 | print("Invalid choice. Please pick from 'rock', 'paper', or 'scissors'.\n") 33 | continue 34 | 35 | print('\n') 36 | for item in choices: 37 | print(f'{item.title()}...') 38 | sleep(0.5) 39 | print('Shoot!') 40 | 41 | print(f'\nPlayer: {player_choice}\nCPU: {cpu_choice}\n') 42 | 43 | if player_choice == cpu_choice: 44 | print("It's a tie!\n") 45 | elif (choices.index(player_choice) - choices.index(cpu_choice)) % 3 == 1: 46 | print('You win!\n') 47 | player_score += 1 48 | else: 49 | print('You lose!\n') 50 | cpu_score += 1 51 | 52 | round_counter += 1 53 | 54 | print(f'Player Score: {player_score}\nCPU Score: {cpu_score}\nRounds: {round_counter}\n') 55 | 56 | again = input('Play again? (y/n)\n').lower() 57 | 58 | clear() 59 | 60 | if again != 'y': 61 | print('\nThanks for playing!') 62 | sleep(2.5) 63 | break 64 | -------------------------------------------------------------------------------- /Games/slot_machine/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Slot machine 9 | 10 | ## Rules 11 | 1. ⭐ : X10, 🟢 : X7, 🟨 : X5, 🔷 : X3, 🔺 : X2 12 | 2. Total of 60 symbols in the pool, ⭐ : 8, 🟢 : 10, 🟨 : 13, 🔷 : 14, 🔺 : 15 13 | 3. I've tried it countless times yet never got ⭐⭐⭐ 🥲 14 | 4. But I think that's how real slot machines work 😉 15 | 5. Good Luck! 16 | 17 | ## How to play 18 | 1. Fork the repo by clicking the fork logo the on top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 20 | 3. Head to the slot_machine folder 21 | 4. Run the file using python command `python slot_machine` 22 | 23 | -------------------------------------------------------------------------------- /Games/slot_machine/slot_machine.py: -------------------------------------------------------------------------------- 1 | import random 2 | from time import sleep 3 | import os 4 | from sys import platform 5 | 6 | # Clears command line 7 | def clear(): 8 | if platform == "linux" or platform == "linux2": 9 | # linux 10 | os.system("clear") 11 | elif platform == "darwin": 12 | # OS X 13 | os.system("clear") 14 | elif platform == "win32": 15 | # Windows... 16 | os.system("CLS") 17 | 18 | # Amount of symbols in the pool 19 | number_of_symbols = { 20 | "⭐": 8, 21 | "🟢": 10, 22 | "🟨": 13, 23 | "🔷": 14, 24 | "🔺": 15 25 | } 26 | 27 | # Values of the symbols 28 | value_of_symbols = { 29 | "⭐": 10, 30 | "🟢": 7, 31 | "🟨": 5, 32 | "🔷": 3, 33 | "🔺": 2 34 | } 35 | 36 | 37 | # Gets player's deposit 38 | def deposit(): 39 | while True: 40 | balance = input("Please enter the amount you want to deposit: $") 41 | if balance.isdigit(): 42 | balance = int(balance) 43 | if balance > 0: 44 | break 45 | else: 46 | print("\nYou must deposit more than $0") 47 | else: 48 | print(f"\n{balance} is not a number!") 49 | return balance 50 | 51 | 52 | # Get player's betting 53 | def get_bet(): 54 | while True: 55 | bet = input("\nPlease enter desire betting amount: $") 56 | if bet.isdigit(): 57 | bet = int(bet) 58 | if bet > 0: 59 | break 60 | else: 61 | print("\nYou must bet more than $0") 62 | else: 63 | print(f"\n{bet} is not a number!") 64 | return bet 65 | 66 | 67 | # Chooses 3 random symbols from the pool 68 | def get_spin(symbols): 69 | all_symbols = [] 70 | 71 | for symbol, number_of_symbols in symbols.items(): 72 | for _ in range(number_of_symbols): 73 | all_symbols.append(symbol) 74 | 75 | row = [] 76 | current_symbol = all_symbols[:] 77 | for _ in range(1, 4): 78 | value = random.choice(current_symbol) 79 | current_symbol.remove(value) 80 | row.append(value) 81 | return row 82 | 83 | 84 | # spinning effect display 85 | def spin_display(symbols): 86 | all_symbols = [] 87 | for symbol, number_of_symbols in symbols.items(): 88 | for _ in range(number_of_symbols): 89 | all_symbols.append(symbol) 90 | display = [] 91 | for _ in range(0,30): 92 | sleep(0.1) 93 | display1 = random.choice(all_symbols) 94 | print(display1, end=" | ") 95 | display2 = random.choice(all_symbols) 96 | print(display2, end=" | ") 97 | display3 = random.choice(all_symbols) 98 | print(display3, end="\r") 99 | 100 | 101 | # main function 102 | def main(): 103 | depo = deposit() 104 | 105 | while True: 106 | print(f"\nYour current balance is {depo}\n\n") 107 | ans = input("Press enter to spin ('q' to quit)") 108 | if ans == "q": 109 | exit() 110 | 111 | while True: 112 | bet = get_bet() 113 | if bet <= depo: 114 | break 115 | else: 116 | print(f"\nYour current balance is {depo}\nYou cannot bet more than your balance!") 117 | clear() 118 | depo -= bet 119 | 120 | print("\nGOOD LUCK!") 121 | 122 | spin_display(number_of_symbols) 123 | 124 | row = get_spin(number_of_symbols) 125 | 126 | print(f"{row[0]} | {row[1]} | {row[2]}\n", end="\r") 127 | 128 | if row[0] == row[1] and row[1] == row[2]: 129 | value = value_of_symbols.get(row[0]) 130 | depo += value * bet 131 | 132 | if depo <= 0: 133 | print("\nYou've lost all of your money!") 134 | ans = input("\nPress enter to deposit more or 'q' to quit") 135 | if ans == "q": 136 | print("\nThank you for playing!") 137 | exit() 138 | else: 139 | main() 140 | 141 | clear() 142 | print("Welcome to THE Slot machine!") 143 | print(''' 144 | Winning prizes 145 | ⭐ : X10 146 | 🟢 : X7 147 | 🟨 : X5 148 | 🔷 : X3 149 | 🔺 : X2 150 | ''') 151 | main() -------------------------------------------------------------------------------- /Games/snake_game/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Snake Game 8 | 9 | ## Rules 10 | 1. The snake starts at the center of the screen and moves in any direction using the 'w', 's', 'a', 'd' keys to move up, down, left, or right respectively. 11 | 2. A food item appears randomly on the screen. 12 | 3. The snake grows in length and the score increases each time the snake eats the food item. 13 | 4. The game ends when the snake hits the boundary or collides with its own body. 14 | 5. The game can be paused and unpaused by pressing the 'p' key. 15 | 16 | ## Features 17 | 18 | ### Pause/Unpause 19 | The game can be paused and unpaused using the 'p' key. This lets you take a break without having to stop the game entirely. 20 | 21 | ### Sound Effects 22 | The game includes sound effects to enhance the playing experience. When the snake eats a food item, an eating sound effect (eat.wav) plays. When the snake dies, a dying sound effect (die.wav) plays. 23 | 24 | ### Difficulty Levels 25 | The game offers two difficulty levels: Easy and Hard. You can choose the difficulty level by clicking on the respective buttons on the screen. The difficulty level affects the speed of the snake, making the game more challenging on the Hard level. 26 | 27 | 28 | ## How to play 29 | 1. Fork the repo by clicking the fork logo the on top right 30 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 31 | 3. Head to the snake_game folder 32 | 4. Ensure that you have the required sound files (eat.wav and die.wav) in the `snake_game` directory. 33 | 5. Run the game using python command `python game.py` 34 | 35 | -------------------------------------------------------------------------------- /Games/snake_game/constants.py: -------------------------------------------------------------------------------- 1 | # Screen properties 2 | SCREEN_WIDTH = 600 3 | SCREEN_HEIGHT = 600 4 | SCREEN_COLOR = "blue" 5 | SCORE_FONT = ("Courier", 24, "normal") 6 | 7 | # Initial properties 8 | INITIAL_DELAY = 0.1 9 | HARD_DELAY = 0.05 10 | DELAY_DECREMENT = 0.001 11 | SCORE_INCREMENT = 10 12 | SNAKE_HEAD_INITIAL_POSITION = (0, 0) 13 | FOOD_INITIAL_POSITION = (0, 100) 14 | 15 | # Colors 16 | SNAKE_HEAD_COLOR = "yellow" 17 | FOOD_COLOR = "red" 18 | 19 | # Keys for directions 20 | DIRECTION_KEYS = {'w': 'up', 's': 'down', 'a': 'left', 'd': 'right'} 21 | 22 | # Opposite directions 23 | OPPOSITE_DIRECTIONS = {'up': 'down', 'down': 'up', 'left': 'right', 'right': 'left'} 24 | 25 | # Size of the turtle 26 | TURTLE_SIZE = 20 27 | 28 | # Boundary limit, considering the size of the turtle 29 | BOUNDARY_LIMIT = SCREEN_WIDTH / 2 30 | 31 | -------------------------------------------------------------------------------- /Games/snake_game/die.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/snake_game/die.wav -------------------------------------------------------------------------------- /Games/snake_game/eat.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/snake_game/eat.wav -------------------------------------------------------------------------------- /Games/state_guessing/50_states.csv: -------------------------------------------------------------------------------- 1 | state,x,y 2 | Alabama,139,-77 3 | Alaska,-204,-170 4 | Arizona,-203,-40 5 | Arkansas,57,-53 6 | California,-297,13 7 | Colorado,-112,20 8 | Connecticut,297,96 9 | Delaware,275,42 10 | Florida,220,-145 11 | Georgia,182,-75 12 | Hawaii,-317,-143 13 | Idaho,-216,122 14 | Illinois,95,37 15 | Indiana,133,39 16 | Iowa,38,65 17 | Kansas,-17,5 18 | Kentucky,149,1 19 | Louisiana,59,-114 20 | Maine,319,164 21 | Maryland,288,27 22 | Massachusetts,312,112 23 | Michigan,148,101 24 | Minnesota,23,135 25 | Mississippi,94,-78 26 | Missouri,49,6 27 | Montana,-141,150 28 | Nebraska,-61,66 29 | Nevada,-257,56 30 | New Hampshire,302,127 31 | New Jersey,282,65 32 | New Mexico,-128,-43 33 | New York,236,104 34 | North Carolina,239,-22 35 | North Dakota,-44,158 36 | Ohio,176,52 37 | Oklahoma,-8,-41 38 | Oregon,-278,138 39 | Pennsylvania,238,72 40 | Rhode Island,318,94 41 | South Carolina,218,-51 42 | South Dakota,-44,109 43 | Tennessee,131,-34 44 | Texas,-38,-106 45 | Utah,-189,34 46 | Vermont,282,154 47 | Virginia,234,12 48 | Washington,-257,193 49 | West Virginia,200,20 50 | Wisconsin,83,113 51 | Wyoming,-134,90 -------------------------------------------------------------------------------- /Games/state_guessing/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Name of your game 8 | 9 | ## Rules 10 | 1. Do you know all 50 states of US? Play this game and find out! 11 | 2. Guess all 50 states of US 12 | 13 | ## How to play 14 | 1. Fork the repo by clicking the fork logo the on top right 15 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 16 | 3. Head to the state_guessing folder 17 | 4. Run the file using python command `python main.py` 18 | -------------------------------------------------------------------------------- /Games/state_guessing/blank_states_img.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Games/state_guessing/blank_states_img.gif -------------------------------------------------------------------------------- /Games/state_guessing/display.py: -------------------------------------------------------------------------------- 1 | from turtle import Turtle 2 | import pandas 3 | 4 | # Read .csv data using pandas 5 | data = pandas.read_csv("./50_states.csv", index_col=False) 6 | 7 | 8 | class Display(Turtle): 9 | def __init__(self): 10 | super().__init__() 11 | self.pu() 12 | self.hideturtle() 13 | self.guessed = [] 14 | 15 | 16 | # Displays states im the map 17 | def show(self, state): 18 | cor = data[data["state"] == state] 19 | 20 | self.setpos(int(cor.x), int(cor.y)) 21 | self.write(f"{state}", font=("Arial", 8, "normal")) 22 | self.guessed.append(state) 23 | 24 | 25 | -------------------------------------------------------------------------------- /Games/state_guessing/main.py: -------------------------------------------------------------------------------- 1 | import turtle 2 | import pandas 3 | from display import Display 4 | 5 | # Turtle window 6 | screen = turtle.Screen() 7 | screen.bgpic("./blank_states_img.gif") 8 | screen.setup(725, 491) 9 | screen.title("Guess The States") 10 | 11 | # Read .csv data using pandas and put all states in a set 12 | data = pandas.read_csv("./50_states.csv") 13 | states = set(data["state"]) 14 | # Displays states in the map 15 | display = Display() 16 | 17 | # Users guessed states 18 | # TODO: Using guessed list, work on the HINT 19 | guessed = [] 20 | while len(guessed) < 50: 21 | user_ans = screen.textinput(title=f"{len(guessed)}/50 States", prompt="Enter the state").title() 22 | 23 | if user_ans in states: 24 | guessed.append(user_ans) 25 | display.show(user_ans) 26 | 27 | turtle.mainloop() -------------------------------------------------------------------------------- /Games/tic_tac_toe/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # Tic-Tac-Toe game 9 | 10 | ## Rules 11 | 1. The game is played on a 3x3 grid. 12 | 2. Two players take turns marking a square with their respective symbols (X or O). 13 | 3. The first player to get three of their symbols in a row (horizontally, vertically, or diagonally) wins the game. 14 | 4. If all squares are filled and no player has won, the game ends in a draw. 15 | 16 | ## How to play 17 | 1. Fork the repo by clicking the fork logo the on top right 18 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 19 | 3. Head to the 'tic_tac_toe' folder 20 | 4. Run the file using python command `python tic_tac_toe.py` 21 | 5. Follow the prompts in the console to play the game. Input the row and column numbers to place your symbol on the grid. 22 | 23 | Have fun playing Tic-Tac-Toe! 24 | -------------------------------------------------------------------------------- /Games/tic_tac_toe/tic_tac_toe.py: -------------------------------------------------------------------------------- 1 | # Tic-Tac-Toe 2 | 3 | # Create the board 4 | board = [' ' for _ in range(9)] 5 | 6 | # Function to display the board 7 | def display_board(): 8 | print('-------------') 9 | for i in range(0, 9, 3): 10 | print('|', board[i], '|', board[i+1], '|', board[i+2], '|') 11 | print('-------------') 12 | 13 | # Function to make a move 14 | def make_move(player, position): 15 | board[position] = player 16 | 17 | # Function to check for a win 18 | def check_win(player): 19 | # Check rows 20 | for i in range(0, 9, 3): 21 | if all(board[i+j] == player for j in range(3)): 22 | return True 23 | 24 | # Check columns 25 | for i in range(3): 26 | if all(board[i+j] == player for j in range(0, 7, 3)): 27 | return True 28 | 29 | # Check diagonals 30 | if all(board[i] == player for i in range(0, 9, 4)) or all(board[i] == player for i in range(2, 7, 2)): 31 | return True 32 | 33 | return False 34 | 35 | # Function to check for a draw 36 | def check_draw(): 37 | return ' ' not in board 38 | 39 | # Function to play the game 40 | def play_game(): 41 | current_player = 'X' 42 | 43 | while True: 44 | display_board() 45 | 46 | # Get player's move 47 | move = input(f"Player {current_player}, make your move (0-8): ") 48 | move = int(move) 49 | 50 | # Make the move 51 | if 0 <= move <= 8 and board[move] == ' ': 52 | make_move(current_player, move) 53 | else: 54 | print("Invalid move. Try again.") 55 | continue 56 | 57 | # Check for a win 58 | if check_win(current_player): 59 | display_board() 60 | print(f"Player {current_player} wins!") 61 | break 62 | 63 | # Check for a draw 64 | if check_draw(): 65 | display_board() 66 | print("It's a draw!") 67 | break 68 | 69 | # Switch to the other player 70 | current_player = 'O' if current_player == 'X' else 'X' 71 | 72 | # Start the game 73 | play_game() 74 | -------------------------------------------------------------------------------- /Games/treasure_Island/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Treasure Island game 8 | 9 | ## Rules 10 | 1. The game is played by a single player. 11 | 2. The game presents a scenario and gives the player options to choose from 12 | 3. The player navigates the scenaios in the game by selecting their preferred answer to the problem faced in the scenario 13 | 4. If the player chooses the right answer(s), a new scenario is presented with new options, 14 | 5. If the player is successful in all his choices, he successfully finds the treasure at the end of the game 15 | 6. If not, its Game Over! 16 | 17 | ## How to play 18 | 1. Fork the repo by clicking the fork logo the on top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 20 | 3. Open the 'treasure_Island' folder 21 | 4. Run the file using python command `python main.py` 22 | 5. Follow the prompts in the console to play the game. Input the row and column numbers to place your symbol on the grid. 23 | 24 | ### Enjoy playing Treasure Island! 25 | -------------------------------------------------------------------------------- /Games/treasure_Island/main.py: -------------------------------------------------------------------------------- 1 | print(''' 2 | ******************************************************************************* 3 | | | | | 4 | _________|________________.=""_;=.______________|_____________________|_______ 5 | | | ,-"_,="" `"=.| | 6 | |___________________|__"=._o`"-._ `"=.______________|___________________ 7 | | `"=._o`"=._ _`"=._ | 8 | _________|_____________________:=._o "=._."_.-="'"=.__________________|_______ 9 | | | __.--" , ; `"=._o." ,-"""-._ ". | 10 | |___________________|_._" ,. .` ` `` , `"-._"-._ ". '__|___________________ 11 | | |o`"=._` , "` `; .". , "-._"-._; ; | 12 | _________|___________| ;`-.o`"=._; ." ` '`."\` . "-._ /_______________|_______ 13 | | | |o; `"-.o`"=._`` '` " ,__.--o; | 14 | |___________________|_| ; (#) `-.o `"=.`_.--"_o.-; ;___|___________________ 15 | ____/______/______/___|o;._ " `".o|o_.--" ;o;____/______/______/____ 16 | /______/______/______/_"=._o--._ ; | ; ; ;/______/______/______/_ 17 | ____/______/______/______/__"=._o--._ ;o|o; _._;o;____/______/______/____ 18 | /______/______/______/______/____"=._o._; | ;_.--"o.--"_/______/______/______/_ 19 | ____/______/______/______/______/_____"=.o|o_.--""___/______/______/______/____ 20 | /______/______/______/______/______/______/______/______/______/______/_____ / 21 | ******************************************************************************* 22 | ''') 23 | print("Welcome to Treasure Island.") 24 | print("Your mission is to find the treasure.") 25 | 26 | #Write your code below this line 👇 27 | 28 | choice1 = input('You\'re at a cross road. Where do you want to go? Type "left" or "right" \n').lower() 29 | if choice1 == "left": 30 | choice2 = input('You\'ve come to a lake. There is an island in the middle of the lake. Type "wait" to wait for a boat. Type "swim" to swim across. \n').lower() 31 | if choice2 == "wait": 32 | choice3 = input("You arrive at the island unharmed. There is a house with 3 doors. One red, one yellow and one blue. Which colour do you choose? \n").lower() 33 | if choice3 == "red": 34 | print("It's a room full of fire. Game Over.") 35 | elif choice3 == "yellow": 36 | print("You found the treasure! You Win!") 37 | elif choice3 == "blue": 38 | print("You enter a room of beasts. Game Over.") 39 | else: 40 | print("You chose a door that doesn't exist. Game Over.") 41 | else: 42 | print("You get attacked by an angry trout. Game Over.") 43 | else: 44 | print("You fell into a hole. Game Over.") -------------------------------------------------------------------------------- /Games/turtle_racing_bet/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Turtle racing bet 8 | 9 | ## Rules 10 | 1. Choose your turtle 11 | 2. Place a bet 12 | 3. Enjoy the race! 13 | 14 | ## How to play 15 | 1. Fork the repo by clicking the fork logo the on top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 17 | 3. Head to the turtle_racing_bet folder 18 | 4. Run the file using python command `python turtle_racing_bet.py` -------------------------------------------------------------------------------- /Games/turtle_racing_bet/turtle_racing_bet.py: -------------------------------------------------------------------------------- 1 | import turtle 2 | import random 3 | from time import sleep 4 | import os 5 | from sys import platform 6 | 7 | # Clears command line 8 | def clear(): 9 | if platform == "linux" or platform == "linux2": 10 | # linux 11 | os.system("clear") 12 | elif platform == "darwin": 13 | # OS X 14 | os.system("clear") 15 | elif platform == "win32": 16 | # Windows... 17 | os.system("CLS") 18 | 19 | 20 | TURTLES = ["red", "orange", "yellow", "green", "blue", "purple", "black"] 21 | 22 | 23 | # Intro 24 | def intro(): 25 | clear() 26 | print("Welcome to Turtle raing bet!") 27 | print("""\nRules are simple 28 | Enter a color of the turtle 29 | Place the amount you want to bet 30 | Watch your turtle win! or lose 31 | """) 32 | inp = input("Press enter to start, 'q' to quit") 33 | if inp == 'q': 34 | exit() 35 | 36 | 37 | # Get user's betting choice 38 | def get_turtle(): 39 | while True: 40 | inp = input(""" 41 | Choose a trutle you want to bet: 42 | 43 | Red Orange Yellow Green Blue Purple Black\n""").lower() 44 | if inp in TURTLES: 45 | break 46 | else: 47 | print("Please enter from the choice") 48 | return inp 49 | 50 | 51 | # Get user's bet 52 | def get_bet(): 53 | while True: 54 | inp = input("Enter a amount you want to bet\n$") 55 | if inp.isdigit(): 56 | inp = int(inp) 57 | if inp > 0: 58 | break 59 | else: 60 | print("You have to bet more than $0") 61 | else: 62 | print(f"{inp} is not a number!") 63 | return inp 64 | 65 | 66 | # Count down before the game starts 67 | def count_down(): 68 | for i in range(5,0, -1): 69 | print(f"Race starts in ...{i}", end="\r") 70 | sleep(.7) 71 | 72 | 73 | # Turtle racing main, returns the winner color 74 | def main(): 75 | screen = turtle.Screen() 76 | screen.setup(width=600, height=600) 77 | screen.bgcolor("gray") 78 | 79 | all_turtles = [] 80 | position = -270 81 | 82 | for each_turtle in TURTLES: 83 | new_turtle = turtle.Turtle() 84 | new_turtle.shape("turtle") 85 | new_turtle.color(each_turtle) 86 | new_turtle.pu() 87 | new_turtle.goto(-270, position) 88 | position += 90 89 | all_turtles.append(new_turtle) 90 | 91 | while True: 92 | for t in all_turtles: 93 | if t.xcor() > 260: 94 | winner = t.pencolor() 95 | screen.bye() 96 | return winner 97 | 98 | speed = random.randint(0, 10) 99 | t.fd(speed) 100 | 101 | 102 | # Count down before the winner reveal 103 | def print_winner(): 104 | dots = ".", "..", "..." 105 | for dot in dots: 106 | print(f"The winner is {dot}", end="\r") 107 | sleep(1) 108 | 109 | 110 | # Play game, display if the user guessed it right 111 | def start(): 112 | user_guess = get_turtle() 113 | user_bet = get_bet() 114 | count_down() 115 | clear() 116 | print("GOOD LUCK!") 117 | winner = main() 118 | clear() 119 | print_winner() 120 | 121 | print(f"The winner is {winner.upper()}!!!") 122 | if winner == user_guess: 123 | print(f"\nCONGRATS!! You Won ${user_bet * 3}!") 124 | else: 125 | print(f"\nYou lost ${user_bet} 😓") 126 | print("\nBetter luck next time!") 127 | exit() 128 | 129 | intro() 130 | clear() 131 | start() 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sean Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Python Tools and Games

2 |

3 | 4 | 5 | 6 |
7 | 8 | Help wanted 9 | Help wanted 10 | Help wanted 11 | 12 |
13 | 14 | 15 |

16 | 17 | 18 | 19 |

20 | 21 | 22 |
23 | 24 | ![GitHub contributors](https://img.shields.io/github/contributors/AseanK/python-tools-and-games?style=flat&color=blueviolet) 25 | ![GitHub PR closed](https://img.shields.io/github/issues-pr-closed-raw/AseanK/python-tools-and-games?style=flate&color=fb07c8) 26 | ![GitHub issues](https://img.shields.io/github/issues-raw/AseanK/python-tools-and-games?style=flate&color=aqua) 27 | ![GitHub last commit](https://img.shields.io/github/last-commit/AseanK/python-tools-and-games?style=flat&color=blueviolet) 28 | ![GitHub Maintained](https://img.shields.io/badge/maintained-yes-fb07c8.svg?style=flat) 29 | ![Github Repo Size](https://img.shields.io/github/repo-size/AseanK/python-tools-and-games?style=flat&color=aqua) 30 | [![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT) 31 |
32 | 33 | 34 | ## Table of Contents 35 | 36 | [Getting Started](#getting-started) 37 | 38 | [Contributing](#contributing) 39 | 40 |
41 | Games 42 | 43 | - [Auction](/Games/auction) 44 | - [BlackJack](/Games/black_jack) 45 | - [Slot Machine](/Games/slot_machine) 46 | - [Board filling game](/Games/board_filling_game) 47 | - [US states guessing](/Games/state_guessing) 48 | - [Minesweeper](/Games/minesweeper) 49 | - [Hang Man](/Games/hangman) 50 | - [Rock Paper Scissors](/Games/rock_paper_scissors) 51 | - [Guess the number](/Games/guess_the_number) 52 | - [Tic-Tac-Toe](/Games/tic_tac_toe) 53 | - [Road crossing](/Games/road_crossing) 54 | - [Pong](/Games/pong) 55 | - [Turtle racing bet](/Games/turtle_racing_bet) 56 | - [Snake game](/Games/snake_game) 57 | - [Etch A Sketch](/Games/etch_a_sketch) 58 | - [CompSci Quiz](/Games/comp_sci_quiz) 59 | - [Treasure Island](Games/treasure_Island) 60 | - [Pizza Palour](Games/pizza_palour) 61 | - [Checkers](Games/checkers) 62 | - [General Quiz Game]() 63 | - [Ludo King](Games/ludo_king) 64 | - [Chin Chiro](Games/chin_chiro) 65 | 66 |
67 | 68 |
69 | Tools 70 | 71 | - [Encoding](/Tools/encoding) 72 | - [Calculator](/Tools/calculator) 73 | - [NATO Alphabet Translator](/Tools/NATO_alphabet_translator) 74 | - [Distance Conversion Calculator](/Tools/distance_calculator) 75 | - [Pomodoro Timer](/Tools/pomodoro_timer) 76 | - [Kanye Says...](/Tools/kanye_says) 77 | - [Cookie Macro](/Tools/cookie_macro) 78 | - [QRcode Generator](/Tools/qrcode_gen) 79 | - [Tip Calculator](/Tools/tip_calculator) 80 | - [Auto WiFi Check](/Tools/AutoWiFiCheck) 81 | - [PDF Merge](Tools/merge_pdf) 82 | - [Text Summarizer](Tools/text_summarizer) 83 | - [Image Resizer](Tools/Image_resizer) 84 | - [Remove Duplicates](Tools/remove_duplicates) 85 | - [Password Strength Checker](Tools/Password_strength_checker) 86 | - [Bluetooth Scanner](Tools/bluetooth_scanner) 87 | - [Custom Password Generator](Tools/custom_password_generator) 88 | 89 |
90 | 91 |

92 | 93 | ## 👀About The Project 94 | 95 | 🎮 Welcome to the **Awesome Open Source** Python Games and Tools repository! 🛠️ 96 | 97 | This curated collection of open source games and tools is specifically designed to empower beginners in their journey to learn and explore Python programming. 🌟 We strongly encourage contributions from the community to enrich this repository with new games, tools, and improvements. 98 |

99 | 100 | ## 🍄Getting Started 101 | 102 | To get started, you'll need to have Python installed on your machine. You can download Python from the official website: [python.org](https://www.python.org/). 103 | 104 | Once Python is installed, you can take the following steps: 105 | 106 | ### Step 1 107 | 108 | - Clone the repository using either of the following commands: 109 | 110 | ```bash 111 | git clone git@github.com:AseanK/python-tools-and-games.git 112 | ``` 113 | 114 | or 115 | 116 | ```bash 117 | git clone https://github.com/AseanK/python-tools-and-games.git 118 | ``` 119 | 120 | ### Step 2 121 | 122 | - Now you can explore the games and tools provided in the repository. 123 | - After cloning the repository, navigate to the project directory: 124 | 125 | ```bash 126 | cd "" 127 | ``` 128 | 129 | ### Step 3 130 | 131 | - Run the file using python command 132 | 133 | ```bash 134 | python ".py" 135 | ``` 136 | 137 |
138 | 139 | ## ✨Contributing 140 | 141 | Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. 142 | We welcome contributions from everyone! If you have an idea for a new game or tool, or if you want to improve the existing ones, please follow these steps: 143 | 144 | ### Step 1 145 | 146 | - Fork the repository: 147 | 148 | 149 | ### Step 2 150 | 151 | - Clone the repository: 152 | 153 | ```bash 154 | git clone git@github.com:AseanK/beginner-python-tools-and-games.git 155 | ``` 156 | 157 | or 158 | 159 | ```bash 160 | git clone https://github.com/AseanK/python-tools-and-games.git 161 | ``` 162 | 163 | ### Step 3 164 | 165 | - Create a new branch for your feature or improvement: 166 | 167 | ```bash 168 | git checkout -b 169 | ``` 170 | 171 | ### Step 4 172 | 173 | - Make your changes and commit them with descriptive messages: 174 | 175 | ```bash 176 | git commit -m '' 177 | ``` 178 | 179 | ### Step 5 180 | 181 | - Push your changes to your forked repository: 182 | 183 | ```bash 184 | git push origin 185 | ``` 186 | 187 | ### Step 6 188 | 189 | - Submit a pull request to the main repository. 190 |
191 | 192 | Please create a simple README.md file using provided template! 193 | 194 | If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". 195 | Don't forget to give the project a star! Thanks again! 196 | 197 | ## :raised_hands: Contributors 198 | 199 | 200 | 201 | 202 | 203 |
204 |

🙏 Thank you! 🙏

205 | -------------------------------------------------------------------------------- /Tools/.gitignore: -------------------------------------------------------------------------------- 1 | */__pycache__ 2 | -------------------------------------------------------------------------------- /Tools/AutoWiFiCheck/README.md: -------------------------------------------------------------------------------- 1 |

WiFi Connection Checker and Restarter

2 | 3 |

Overview

4 |

This Python script is designed to check the status of your WiFi connection on a Windows system. If the WiFi network is inactive and not able to receive ping packets, the script will automatically turn off the WiFi, turn it on again, and check whether the connection is live again or not. The script utilizes the schedule package for task scheduling, netsh commands for controlling the WiFi interface, and the netifaces package to retrieve meaningful network interface names.

5 | 6 |

Prerequisites

7 |
    8 |
  • This script is specifically designed for Windows systems.
  • 9 |
  • The script requires administrative privileges to perform actions like turning off and on the WiFi interface.
  • 10 |
11 | 12 |

Dependencies

13 |

Install the schedule and netifaces packages using the following commands:

14 |
15 | pip install schedule
16 | pip install netifaces
17 | 
18 | 19 |

Usage

20 |
    21 |
  1. Run the script with administrative privileges to ensure it can control the WiFi interface.
  2. 22 |
    python wifi_checker.py
    23 |
  3. The script will schedule a periodic check of the WiFi connection status.
  4. 24 |
  5. If the WiFi connection is inactive (unable to receive ping packets), the script will automatically turn off and on the WiFi interface.
  6. 25 |
  7. The script will log the status of the WiFi connection in the console.
  8. 26 |
27 | 28 |

Important Notes

29 |
    30 |
  • Ensure that the script is run with administrative privileges to avoid permission issues.
  • 31 |
  • The script uses the netsh command to control the WiFi interface. If there are any issues with the execution of netsh, the script may not work as expected.
  • 32 |
33 | 34 |

References

35 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Tools/AutoWiFiCheck/wifi_checker.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | import subprocess 3 | import sys 4 | import time 5 | from datetime import datetime 6 | import schedule as sc 7 | 8 | 9 | def enable(): 10 | subprocess.call("netsh interface set interface Wi-Fi enabled") 11 | print("Turning On the laptop WiFi") 12 | 13 | def disable(): 14 | subprocess.call("netsh interface set interface Wi-Fi disabled") 15 | print("Turning Off the laptop WiFi") 16 | 17 | 18 | 19 | def job(): 20 | if subprocess.call("netsh interface set interface Wi-Fi enabled") == 0: 21 | print("WiFi is enabled and connected to internet") 22 | hostname = "www.google.com" 23 | response = subprocess.call("ping -n 1 " + hostname) 24 | if response == 1: 25 | print("Your Connection is not working") 26 | disable() 27 | time.sleep(1) 28 | enable() 29 | 30 | def is_admin(): 31 | try: 32 | return ctypes.windll.shell32.IsUserAnAdmin() 33 | except: 34 | return False 35 | 36 | if is_admin(): 37 | # job() 38 | sc.every(50).seconds.do(job) 39 | else: 40 | ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1) 41 | 42 | 43 | while True: 44 | sc.run_pending() 45 | time.sleep(1) -------------------------------------------------------------------------------- /Tools/Image encoding and decoding/README.md: -------------------------------------------------------------------------------- 1 | # Image Encoder and Decoder 2 | 3 | A Python program that enables users to encode images into Base64 text for easy sharing across text-based platforms and decode the text back into the original image files. This tool is designed to simplify image sharing and recovery without relying on binary file transfers. 4 | 5 | --- 6 | 7 | ## Features 8 | 9 | - **Image Encoding**: Converts images into Base64-encoded text files, making them suitable for embedding in text documents or sharing via chat and email. 10 | - **Text-to-Image Decoding**: Restores the original image from Base64-encoded text files. 11 | - **File Navigation**: Allows users to navigate directories and manage file selection via a command-line interface. 12 | - **Automated File Naming**: Automatically saves encoded and decoded files with descriptive names to prevent overwriting and enhance organization. 13 | 14 | --- 15 | 16 | ## Requirements 17 | 18 | - **Python 3.6+** 19 | 20 | This program uses only built-in Python modules (`os` and `base64`), so no additional dependencies are needed. 21 | 22 | --- 23 | 24 | ## How It Works 25 | 26 | ### Encoding Process 27 | 1. Reads the image file in binary mode. 28 | 2. Converts the binary data into a Base64-encoded string. 29 | 3. Saves the string into a text file with a user-friendly name. 30 | 31 | ### Decoding Process 32 | 1. Reads the Base64 string from a text file. 33 | 2. Decodes the string back into binary image data. 34 | 3. Writes the binary data into an image file. 35 | 36 | --- 37 | 38 | ## Customization 39 | 40 | - **File Naming**: Modify the naming conventions for encoded or decoded files in the `encode_image` and `decode_image` functions. 41 | - **Batch Processing**: Extend the program to handle multiple files simultaneously for encoding or decoding. 42 | - **Character Limit Handling**: Add functionality to split encoded text into chunks for platforms with character limits. 43 | 44 | --- 45 | 46 | ## Troubleshooting 47 | 48 | ### Common Issues 49 | - **File Not Found**: Ensure the file exists in the current directory and the name is entered correctly. 50 | - **Decoding Errors**: Ensure the Base64 text is unaltered before decoding. 51 | - **Invalid Directories**: Verify that directory names exist when navigating. 52 | 53 | ### Tips 54 | - Use complete file names, including extensions, when selecting files. 55 | - Avoid manually modifying encoded text files to prevent decoding errors. 56 | 57 | --- 58 | 59 | ## Notes 60 | 61 | ### Use Cases 62 | - **Portable Image Sharing**: Share images via text-based platforms like emails, chat, or forums without relying on attachments. 63 | - **Embedding Visuals in Code**: Include images as Base64 text in configuration files or scripts for portability. 64 | - **Cross-Platform Support**: The program works on all operating systems that support Python 3.6 or later. 65 | 66 | ### Known Limitations 67 | - Base64-encoded text files are larger than the original images due to encoding overhead. 68 | - Processing very large images may require significant memory. 69 | 70 | --- 71 | 72 | ## License 73 | 74 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 75 | 76 | --- 77 | 78 | ## Acknowledgments 79 | 80 | - Thanks to the Python community for documentation and resources. 81 | - This project was inspired by the need for seamless image sharing and recovery in text-based environments. 82 | -------------------------------------------------------------------------------- /Tools/Image encoding and decoding/image_encoding_and_decoding.py: -------------------------------------------------------------------------------- 1 | import os 2 | import base64 3 | 4 | 5 | def encode_image(file_path): 6 | try: 7 | with open(file_path, "rb") as image_file: 8 | encoded_string = base64.b64encode(image_file.read()).decode("utf-8") 9 | output_file = f"{os.path.splitext(os.path.basename(file_path))[0]}_encode.txt" 10 | with open(output_file, "w", encoding="utf-8") as text_file: 11 | text_file.write(encoded_string) 12 | print(f"\n✅ Image encoding successful! Result saved in '{output_file}'.") 13 | except Exception as e: 14 | print(f"⚠️ Error during encoding: {e}") 15 | 16 | 17 | def decode_image(encoded_string, output_path): 18 | try: 19 | image_data = base64.b64decode(encoded_string) 20 | with open(output_path, "wb") as image_file: 21 | image_file.write(image_data) 22 | print(f"\n✅ Image decoding successful! Result saved in '{output_path}'.") 23 | except Exception as e: 24 | print(f"⚠️ Error during decoding: {e}") 25 | 26 | 27 | def list_files(current_dir): 28 | print(f"\n📂 Current directory: {current_dir}") 29 | print("=" * 40) 30 | for item in os.listdir(current_dir): 31 | item_path = os.path.join(current_dir, item) 32 | if os.path.isdir(item_path): 33 | print(f"[DIR] {item}") 34 | else: 35 | print(f" {item}") 36 | print("=" * 40) 37 | 38 | 39 | def change_directory(current_dir): 40 | target_dir = input("Enter the directory to move to ('..' for parent directory): ").strip() 41 | if target_dir == "..": 42 | return os.path.dirname(current_dir) 43 | else: 44 | new_dir = os.path.join(current_dir, target_dir) 45 | if os.path.isdir(new_dir): 46 | return new_dir 47 | else: 48 | print("⚠️ Directory does not exist.") 49 | return current_dir 50 | 51 | 52 | def main(): 53 | current_dir = os.getcwd() 54 | while True: 55 | list_files(current_dir) 56 | print("\n🛠️ Select an action") 57 | print("[1] Encode an image") 58 | print("[2] Decode an image from encoded text") 59 | print("[3] Change directory") 60 | print("[4] Exit") 61 | choice = input("Select (1/2/3/4): ").strip() 62 | 63 | if choice == "1": 64 | file_name = input("🔎 Enter the name of the image file to encode: ").strip() 65 | file_path = os.path.join(current_dir, file_name) 66 | if os.path.exists(file_path): 67 | encode_image(file_path) 68 | else: 69 | print("⚠️ File does not exist.") 70 | 71 | elif choice == "2": 72 | encoded_file = input("🔎 Enter the name of the encoded text file: ").strip() 73 | encoded_path = os.path.join(current_dir, encoded_file) 74 | if os.path.exists(encoded_path): 75 | with open(encoded_path, "r", encoding="utf-8") as text_file: 76 | encoded_string = text_file.read() 77 | output_name = input("💾 Enter the name of the output image file (e.g., output.png): ").strip() 78 | output_path = os.path.join(current_dir, output_name) 79 | decode_image(encoded_string, output_path) 80 | else: 81 | print("⚠️ Text file does not exist.") 82 | 83 | elif choice == "3": 84 | current_dir = change_directory(current_dir) 85 | 86 | elif choice == "4": 87 | print("\nExiting the program. 👋") 88 | break 89 | 90 | else: 91 | print("⚠️ Invalid input. Please try again.") 92 | 93 | 94 | if __name__ == "__main__": 95 | main() 96 | -------------------------------------------------------------------------------- /Tools/Image_resizer/image_resize.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import os 3 | 4 | def reduce_image_size(image_path, quality=85): 5 | fileName, ext = os.path.splitext(image_path) 6 | ext = ext.lower() 7 | 8 | img = Image.open(image_path) 9 | output_path = f"{fileName}_resize{ext}" 10 | 11 | if ext in ['.jpg', '.jpeg']: 12 | img.save(output_path, "JPEG", quality=quality) 13 | elif ext == '.png': 14 | img = img.convert("P", palette=Image.ADAPTIVE, colors=256) 15 | img.save(output_path, "PNG", optimize=True) 16 | elif ext == '.webp': 17 | if getattr(img, "is_animated", False): # Is file Animate? 18 | frames = [] 19 | for frame in range(img.n_frames): 20 | img.seek(frame) 21 | frames.append(img.copy()) 22 | frames[0].save( 23 | output_path, 24 | format="WEBP", 25 | save_all=True, 26 | append_images=frames[1:], 27 | quality=quality, 28 | duration=img.info.get("duration", 100), 29 | loop=img.info.get("loop", 0) 30 | ) 31 | else: 32 | img.save(output_path, "WEBP", quality=quality) 33 | else: 34 | print("We can't resize this extension.") 35 | return 36 | 37 | print(f"{output_path} resize complete!") 38 | 39 | image_path = input("Input image path: ") 40 | reduce_image_size(image_path, quality=70) 41 | -------------------------------------------------------------------------------- /Tools/NATO_alphabet_translator/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # NATO Alphabet Translator 8 | 9 | ## Features 10 | 1. This program converts the normal alphabet into the NATO phonetic alphabet which is commonly used by militaries and other organisations that communicate via radio 11 | 2. Enter a word and it'll do the rest for you! 12 | 13 | ## How to install and run 14 | 1. Fork the repo by clicking the fork logo on the top right 15 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 16 | 3. Head to the NATO_alphabet_translator folder 17 | 4. Run the file using python command `python translator.py` 18 | 19 | ## Slight adjustments for readability 20 | 1) Added single check statement that will check if letter is entered 21 | 2) Removed redundant while loop (outer) because there is no way to break out of program once you start it 22 | 3) Removed redundant quit statement in Intro() function 23 | 4) Moved intro() inside single function as its all prints statements -------------------------------------------------------------------------------- /Tools/NATO_alphabet_translator/nato_phonetic_alphabet.csv: -------------------------------------------------------------------------------- 1 | letter,code 2 | A,Alfa 3 | B,Bravo 4 | C,Charlie 5 | D,Delta 6 | E,Echo 7 | F,Foxtrot 8 | G,Golf 9 | H,Hotel 10 | I,India 11 | J,Juliet 12 | K,Kilo 13 | L,Lima 14 | M,Mike 15 | N,November 16 | O,Oscar 17 | P,Papa 18 | Q,Quebec 19 | R,Romeo 20 | S,Sierra 21 | T,Tango 22 | U,Uniform 23 | V,Victor 24 | W,Whiskey 25 | X,X-ray 26 | Y,Yankee 27 | Z,Zulu -------------------------------------------------------------------------------- /Tools/NATO_alphabet_translator/translator.py: -------------------------------------------------------------------------------- 1 | import pandas 2 | import os 3 | from sys import platform 4 | 5 | # Clears command line 6 | def clear(): 7 | if platform == "linux" or platform == "linux2": 8 | # linux 9 | os.system("clear") 10 | elif platform == "darwin": 11 | # OS X 12 | os.system("clear") 13 | elif platform == "win32": 14 | # Windows... 15 | os.system("CLS") 16 | 17 | print("Welcome to NATO phonetic alphabet translator!\n") 18 | print("A spelling alphabet is a set of words used to stand for the letters of an alphabet in oral communication") 19 | print("It is used to spell out words when speaking to someone not able to see the speaker,\nor when the audio channel is not clear") 20 | print("Enter a word and this program will translate it for you!\n") 21 | 22 | 23 | nato = pandas.read_csv("./nato_phonetic_alphabet.csv") 24 | 25 | nato_dict = {row.letter:row.code for (index, row) in nato.iterrows()} 26 | 27 | clear() 28 | 29 | # Input validation 30 | while True: 31 | inp = input("Enter a word: ").upper() 32 | if not inp.isalpha(): 33 | print("Only letters are allowed, no symbols, or empty space or numbers...") 34 | elif inp == "QUIT": 35 | break 36 | 37 | ans = [nato_dict[letter] for letter in inp if letter != " "] 38 | print([nato_dict[letter] for letter in inp if letter != " "]) 39 | 40 | # Added single check statement that will check if letter is entered 41 | # Removed redundant while loop (outer) because there is no way to break out of program once you start it 42 | # Removed redundant quit statement in Intro() function 43 | # Moved intro() inside single function as its all prints statements -------------------------------------------------------------------------------- /Tools/Password_strength_checker/main.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter import messagebox 3 | import re 4 | import nltk 5 | from nltk.corpus import words 6 | 7 | nltk.download('words') 8 | 9 | def check_dictionary(word): 10 | word_list = set(words.words()) 11 | if word.lower() in word_list: 12 | return True 13 | return False 14 | 15 | def check_complexity(password): 16 | if len(password) < 10: 17 | return False 18 | if not re.search(r'[A-Z]', password): 19 | return False 20 | if not re.search(r'[a-z]', password): 21 | return False 22 | if not re.search(r'[0-9]', password): 23 | return False 24 | if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password): 25 | return False 26 | if re.search(r'(.)\1\1', password): 27 | return False 28 | return True 29 | 30 | def check_password_strength(password): 31 | feedback = [] 32 | if len(password) < 8: 33 | feedback.append("Password is too short. Please enter at least 8 characters.") 34 | if check_dictionary(password): 35 | feedback.append("Password contains a dictionary word. Use a more complex password.") 36 | if not check_complexity(password): 37 | feedback.append("Include uppercase and lowercase letters, numbers, and special characters, and avoid consecutive identical characters.") 38 | 39 | if feedback: 40 | return "\n".join(feedback) 41 | return "Strong password!" 42 | 43 | def on_check_button_click(): 44 | password = entry_password.get() 45 | result = check_password_strength(password) 46 | if result == "Strong password!": 47 | messagebox.showinfo("Strength Check Result", result) 48 | else: 49 | messagebox.showwarning("Strength Check Result", result) 50 | 51 | root = tk.Tk() 52 | root.title("Password Strength Checker") 53 | root.geometry("400x300") 54 | 55 | label_password = tk.Label(root, text="Enter Password : ") 56 | label_password.pack(pady=10) 57 | 58 | entry_password = tk.Entry(root, show="*", width=30) 59 | entry_password.pack(pady=5) 60 | 61 | check_button = tk.Button(root, text="Check Password Strength", command=on_check_button_click) 62 | check_button.pack(pady=20) 63 | 64 | root.mainloop() -------------------------------------------------------------------------------- /Tools/README_template.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Name of your tool 8 | 9 | ## Features 10 | 1. 11 | 2. 12 | 3. 13 | 14 | ## How to install and run 15 | 1. Fork the repo by clicking the fork logo on the top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 17 | 3. Head to the folder 18 | 4. Run the file using python command `python ` 19 | 20 | 21 | -------------------------------------------------------------------------------- /Tools/bluetooth_scanner/README.md: -------------------------------------------------------------------------------- 1 | # Bluetooth Scanner using PyQt5 2 | 3 | A Python application that scans for nearby Bluetooth devices using PyQt5's QtBluetooth module. It lists both discovered and connected Bluetooth devices, providing a simple interface to manage Bluetooth peripherals directly from the application. 4 | 5 | ## Features 6 | 7 | - **Device Scanning**: Searches for nearby Bluetooth devices. 8 | - **Device Filtering**: Ignores devices without names or with default naming patterns. 9 | - **Connected Devices**: Identifies and lists devices that are already paired or connected. 10 | - **Cross-Platform**: Works on any operating system supported by PyQt5 and QtBluetooth. 11 | 12 | ## Requirements 13 | 14 | - **Python 3.5+** 15 | - **PyQt5** 16 | - Ensure that PyQt5 is installed with Bluetooth support. 17 | - **QtBluetooth Module** 18 | - Some operating systems might require additional packages for Bluetooth functionality. 19 | 20 | ## Usage 21 | 22 | ### Run the Application 23 | 24 | ```bash 25 | python bluetooth_scanner.py 26 | ``` 27 | 28 | ### Understanding the Output 29 | 30 | - **Discovered Devices**: The application will print out all Bluetooth devices found during the scan. 31 | - **Connected Devices**: It will list devices that are currently paired or connected to your system. 32 | 33 | ## How It Works 34 | 35 | ### Initialization: 36 | 37 | - Creates an instance of `QBluetoothDeviceDiscoveryAgent` to manage the scanning process. 38 | - Connects signals to handle device discovery and completion of the scan. 39 | 40 | ### Device Discovery: 41 | 42 | - The `device_discovered` method is called whenever a new device is found. 43 | - Filters out devices without a name or with default naming patterns like "Bluetooth XX:XX:XX:XX:XX". 44 | - Stores valid devices in a list and checks their pairing status. 45 | 46 | ### Completion: 47 | 48 | - Once scanning is finished, `scan_finished` is called. 49 | - Prints out lists of all discovered devices and connected devices. 50 | - Exits the application gracefully. 51 | 52 | ## Customization 53 | 54 | ### Filtering Devices: 55 | 56 | - Modify the regular expression in the `device_discovered` method to change how devices are filtered. 57 | - Currently, it filters out devices matching the pattern: `Bluetooth XX:XX:XX:XX:XX:XX`. 58 | 59 | ### Extending Functionality: 60 | 61 | - Implement additional features like initiating pairing, connecting to devices, or handling data transfer. 62 | - Utilize other classes from the QtBluetooth module as needed. 63 | 64 | ## Troubleshooting 65 | 66 | ### No Devices Found: 67 | 68 | - Ensure that your Bluetooth adapter is enabled and working properly. 69 | - Check that the devices you're trying to discover are discoverable. 70 | 71 | ### Import Errors: 72 | 73 | - Verify that PyQt5 is installed correctly with Bluetooth support. 74 | - Some Linux distributions require additional Qt Bluetooth packages. 75 | 76 | ### Permission Issues: 77 | 78 | - On Linux, you might need to run the application with `sudo` to access Bluetooth hardware. 79 | - Alternatively, add your user to the `bluetooth` group: 80 | 81 | ```bash 82 | sudo usermod -a -G bluetooth $(whoami) 83 | ``` 84 | 85 | ## Notes 86 | 87 | ### Cross-Platform Compatibility: 88 | 89 | - While PyQt5 aims to be cross-platform, Bluetooth support might vary depending on the operating system and hardware drivers. 90 | - Testing has been primarily conducted on Windows 10 and Ubuntu 20.04. 91 | 92 | ### PyQt5 Version: 93 | 94 | - This application requires PyQt5 version that includes the QtBluetooth module. 95 | - You can check your PyQt5 version using: 96 | 97 | ```python 98 | import PyQt5 99 | print(PyQt5.QT_VERSION_STR) 100 | ``` 101 | 102 | ## License 103 | 104 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 105 | 106 | ## Acknowledgments 107 | 108 | - Thanks to the PyQt5 and Qt communities for providing extensive documentation and support. 109 | - Inspired by the need for simple Bluetooth management in Python applications. 110 | -------------------------------------------------------------------------------- /Tools/bluetooth_scanner/bluetooth_scanner.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtBluetooth import ( 2 | QBluetoothDeviceDiscoveryAgent, 3 | QBluetoothLocalDevice, 4 | QBluetoothAddress, 5 | QBluetoothDeviceInfo 6 | ) 7 | from PyQt5.QtCore import QCoreApplication, QObject, pyqtSlot 8 | import sys 9 | import re 10 | 11 | 12 | class BluetoothScanner(QObject): 13 | def __init__(self): 14 | super().__init__() 15 | self.devices = [] 16 | self.connected_devices = [] 17 | self.agent = QBluetoothDeviceDiscoveryAgent() 18 | self.agent.deviceDiscovered.connect(self.device_discovered) 19 | self.agent.finished.connect(self.scan_finished) 20 | 21 | # Local Bluetooth adapter 22 | self.local_device = QBluetoothLocalDevice() 23 | 24 | # Start scanning 25 | self.agent.start() 26 | 27 | @pyqtSlot("QBluetoothDeviceInfo") 28 | def device_discovered(self, device): 29 | name = device.name() 30 | address = device.address().toString() 31 | 32 | # Skip devices with no name or names matching 'Bluetooth XX:XX:XX:XX:XX:XX' pattern 33 | if not name: 34 | return 35 | 36 | pattern = r'^Bluetooth ([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$' 37 | if re.match(pattern, name): 38 | return 39 | 40 | # Save device info 41 | device_info = { 42 | "name": name, 43 | "address": address, 44 | "device_info": device, # QBluetoothDeviceInfo object 45 | } 46 | self.devices.append(device_info) 47 | print(f"Discovered device: {name} ({address})") 48 | 49 | # Check pairing status 50 | pairing_status = self.local_device.pairingStatus(device.address()) 51 | if pairing_status != QBluetoothLocalDevice.Unpaired: 52 | self.connected_devices.append(device_info) 53 | 54 | @pyqtSlot() 55 | def scan_finished(self): 56 | print("\nScan completed!\n") 57 | print("=== Discovered Bluetooth Devices ===") 58 | for idx, device in enumerate(self.devices, 1): 59 | print(f"{idx}. {device['name']} ({device['address']})") 60 | 61 | print("\n=== Connected Bluetooth Devices ===") 62 | if self.connected_devices: 63 | for idx, device in enumerate(self.connected_devices, 1): 64 | print(f"{idx}. {device['name']} ({device['address']})") 65 | else: 66 | print("No connected Bluetooth devices found.") 67 | 68 | # Exit the application 69 | QCoreApplication.quit() 70 | 71 | 72 | if __name__ == "__main__": 73 | app = QCoreApplication(sys.argv) 74 | scanner = BluetoothScanner() 75 | sys.exit(app.exec_()) 76 | -------------------------------------------------------------------------------- /Tools/calculator/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Calculator 8 | 9 | ## Restrictions 10 | 11 | - Equations are strictly evaluated left to right (so don't be surprised when it can't accurately compute more complex equations) 12 | - Equations must be entered WITHOUT spaces. For example: 13 | - `Correct`: 14 | >\>\>\> 4+3/99+4 15 | - `Incorrect`: 16 | >\>\>\> 5 + 4 + 99 - 33 * 4 17 | - Parenthesis are not yet included (this requires _a lot_ of more work to validate. I encourage anyone to try though. You'll have to use a more advanced algorithm). 18 | 19 | ## How to install and run 20 | 21 | 1. Fork the repo by clicking the fork logo on top right 22 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 23 | 3. Head to the calculator folder 24 | 4. Run the file using python command `python calc.py` -------------------------------------------------------------------------------- /Tools/calculator/calc.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple 2 | 3 | SUPPRORTED_OPS = ["+", "-", "*", "/"] 4 | 5 | def begins_with_negative(equation:str) -> bool: 6 | """Checks if an equation begins with a negative (edge case for having string-initial negative #'s)""" 7 | return equation[0] == "-" 8 | 9 | def is_operator(char:str) -> bool: 10 | """Checks of a given string character is an operator (aka, not a digit)""" 11 | return not char.isdigit() 12 | 13 | def has_correct_equation_sides(equation:str) -> bool: 14 | """Checks if an equation has operators at the beginning or end of it, which is illicit (except for negative #'s at the beginning)""" 15 | try: 16 | beginning = equation[0] 17 | end = equation[-1] 18 | except IndexError: 19 | return False 20 | 21 | if beginning in SUPPRORTED_OPS or end in SUPPRORTED_OPS: 22 | if not begins_with_negative(equation): 23 | return False 24 | return True 25 | 26 | def has_correct_neighbors(equation:str, operator_indices:List[int]) -> bool: 27 | """Each operator should have at least one digit on either side. """ 28 | 29 | for operator_idx in operator_indices: 30 | left_neighbor = equation[operator_idx-1] 31 | right_neighbor = equation[operator_idx+1] 32 | #print(f"{left_neighbor = } AT {operator_idx-1}") 33 | #print(f"{right_neighbor = } AT {operator_idx+1}") 34 | 35 | if not left_neighbor.isdigit() or not right_neighbor.isdigit(): 36 | return False 37 | 38 | return True 39 | 40 | def contains_operators(equation:str) -> bool: 41 | """Check if there are any operators in the equation""" 42 | for char in equation: 43 | if is_operator(char) and char in SUPPRORTED_OPS: 44 | return True 45 | return False 46 | 47 | def valid_equation_format(equation:str, equation_ops:List[int]) -> bool: 48 | """Applies all input validation functions to the user's equation""" 49 | 50 | if not has_correct_equation_sides(equation): 51 | print("Equation has trailing operators") 52 | return False 53 | 54 | if not has_correct_neighbors(equation, equation_ops): 55 | print("Equation has incorrect neighbors") 56 | return False 57 | 58 | if not contains_operators(equation): 59 | print("Equation does not contain operators") 60 | return False 61 | 62 | return True 63 | 64 | 65 | def calculate(op:str, i:int, j:int) -> int: 66 | """Given an operator and two numbers, performs that operation on the nums""" 67 | result = i+j if op == "+" else \ 68 | i-j if op == "-" else \ 69 | i*j if op == "*" else \ 70 | i/j if op == "/" else None 71 | return result 72 | 73 | 74 | def get_initial_op_left_num(equation:str, op_index:int) -> int: 75 | """Retrieves the numbers on an operators left side. This func is only called for the first operator in an equation""" 76 | digits = [] 77 | 78 | for char in equation[op_index-1::-1]: 79 | if not is_operator(char): 80 | digits.append(char) 81 | else: 82 | break 83 | 84 | num = int("".join(digits)) 85 | return -(num) if begins_with_negative(equation) else num 86 | 87 | def get_op_right_num(equation:str, op_index:int) -> int: 88 | """Retrieves the numbers on an operators right side""" 89 | digits = [] 90 | for char in equation[op_index+1:]: 91 | if not is_operator(char): 92 | digits.append(char) 93 | else: 94 | break 95 | return int("".join(digits)) 96 | 97 | def parse_equation(equation:str, equation_ops:List[int]): 98 | """Function is a bit messy""" 99 | result = None 100 | 101 | for i in equation_ops: 102 | current_op = equation[i] 103 | left_num = get_initial_op_left_num(equation, i) if result is None else result 104 | right_num = get_op_right_num(equation, i) 105 | result = calculate(current_op, left_num, right_num) 106 | 107 | return result 108 | 109 | def locate_operators(equation:str) -> List[int]: 110 | """Given an equation, locates the string indices of each operator""" 111 | op_indices = [] 112 | for i, char in enumerate(equation): 113 | if char in SUPPRORTED_OPS: 114 | if i == 0 and begins_with_negative(equation): 115 | continue 116 | op_indices.append(i) 117 | 118 | return op_indices 119 | 120 | def main(): 121 | 122 | print("Enter your equation here. Example: 4+3-55/2**2") 123 | print(f"Currently supported operations:{SUPPRORTED_OPS}\n") 124 | print("NOTE: Equations are strictly evaluated left-to-right (parenthesis NOT supported)") 125 | print("Type '\end' to exit the application") 126 | equation = "" 127 | while equation != "\end": 128 | equation = input(">>> ").strip() 129 | 130 | if equation != "\end": 131 | equation_ops = locate_operators(equation) 132 | if not valid_equation_format(equation, equation_ops): 133 | print(f"Invalid equation: '{equation}'. Please try again or type \end to quit") 134 | else: 135 | try: 136 | print(parse_equation(equation, equation_ops)) 137 | except ZeroDivisionError: 138 | print("Your equation resulted in a ZeroDivisonError. Try again.") 139 | 140 | 141 | 142 | 143 | 144 | 145 | if __name__ == "__main__": 146 | main() -------------------------------------------------------------------------------- /Tools/cookie_macro/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Cookie Macro Auto Script 8 | 9 | ## Features 10 | 1. Macro script for https://orteil.dashnet.org/cookieclicker 11 | 2. You'll have to download your browser driver to run this script. 12 | 3. Change the `DRIVER_PATH` to the path to your driver. 13 | 4. Run the script, Sit back, Enjoy watching you get rich. 14 | 15 | ## How to install and run 16 | 1. Fork the repo by clicking the fork logo on the top right 17 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 18 | 3. Head to the cookie_macro folder 19 | 4. Run the file using python command `python main.py` 20 | -------------------------------------------------------------------------------- /Tools/cookie_macro/main.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.by import By 3 | import time 4 | 5 | 6 | # You have to download the driver for your own web-browser 7 | # - Chrome: https://chromedriver.chromium.org/downloads 8 | # - Firefox: https://pythonbasics.org/selenium-firefox/ 9 | # - Safari: https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari/ 10 | 11 | # **Change the value to your driver path** 12 | DRIVER_PATH = "BROWSER DRIVER PATH" 13 | 14 | driver = webdriver.Chrome(DRIVER_PATH) 15 | 16 | 17 | # Selects language at start 18 | def sel_lang(): 19 | driver.get("https://orteil.dashnet.org/cookieclicker/") 20 | 21 | time.sleep(5) 22 | 23 | lang_sel = driver.find_element(By.ID, "langSelect-EN") 24 | lang_sel.click() 25 | 26 | 27 | # Clicks cookie 28 | def cookie_clicker(): 29 | cookie_btn = driver.find_element(By.ID, "bigCookie") 30 | end_t = time.time() + 5 31 | while time.time() < end_t: 32 | cookie_btn.click() 33 | 34 | 35 | # Upgrade products 36 | def upgrade(): 37 | products = driver.find_elements(By.CLASS_NAME, "product.unlocked.enabled") 38 | 39 | for product in products: 40 | product.click() 41 | 42 | cookie_clicker() 43 | 44 | 45 | # Upgrade upgrades 46 | def click_up(): 47 | ups = driver.find_element(By.ID, "upgrade0") 48 | ups.click() 49 | 50 | 51 | # Main 52 | sel_lang() 53 | time.sleep(5) 54 | cookie_clicker() 55 | i = 0 56 | while True: 57 | if i % 2 == 0: 58 | upgrade() 59 | i += 1 60 | else: 61 | click_up() 62 | i += 1 63 | -------------------------------------------------------------------------------- /Tools/custom_password_generator/custom_password_generator.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import tkinter as tk 4 | from tkinter import messagebox 5 | from typing import Optional 6 | 7 | 8 | # Function to generate a strong password based on a custom word 9 | def generate_password(custom_word: str) -> str: 10 | # Define the required characters for a strong password 11 | uppercase_letters: str = string.ascii_uppercase 12 | lowercase_letters: str = string.ascii_lowercase 13 | digits: str = string.digits 14 | symbols: str = "!@#$%^&*()-_=+" 15 | 16 | # Ensure the final password is at least 12 characters 17 | target_length: int = max(12, len(custom_word) + 4) 18 | 19 | # Add random selections of characters around the custom word to increase strength 20 | prefix: list[str] = [ 21 | random.choice(uppercase_letters), 22 | random.choice(digits), 23 | random.choice(symbols) 24 | ] 25 | 26 | suffix: list[str] = [ 27 | random.choice(lowercase_letters), 28 | random.choice(digits), 29 | random.choice(symbols) 30 | ] 31 | 32 | # Combine prefix, custom word, and suffix 33 | password: str = ''.join(prefix) + custom_word + ''.join(suffix) 34 | 35 | # Add more random characters if the password is still too short 36 | while len(password) < target_length: 37 | password += random.choice(uppercase_letters + lowercase_letters + digits + symbols) 38 | 39 | # Shuffle prefix and suffix slightly to add randomness 40 | password_list: list[str] = list(password) 41 | random.shuffle(password_list[:len(prefix)]) 42 | random.shuffle(password_list[-len(suffix):]) 43 | final_password: str = ''.join(password_list) 44 | 45 | return final_password 46 | 47 | 48 | # Function to display generated password 49 | def display_password() -> None: 50 | custom_word: str = entry.get() 51 | if not custom_word: 52 | messagebox.showerror("Error", "Please enter a custom word") 53 | return 54 | 55 | password: str = generate_password(custom_word) 56 | result_label.config(text="Generated Password: " + password) 57 | copy_button.config(state="normal") # Enable copy button 58 | result_label.password = password # Store password for copying 59 | 60 | 61 | # Function to copy password to clipboard 62 | def copy_to_clipboard() -> None: 63 | if result_label.password is not None: 64 | root.clipboard_clear() 65 | root.clipboard_append(result_label.password) 66 | messagebox.showinfo("Copied", "Password copied to clipboard!") 67 | else: 68 | messagebox.showerror("Error", "No password to copy") 69 | 70 | 71 | # Setting up the UI 72 | root: tk.Tk = tk.Tk() 73 | root.title("Password Generator") 74 | root.geometry("400x250") 75 | 76 | # Input label and entry box 77 | label: tk.Label = tk.Label(root, text="Enter a custom word:") 78 | label.pack(pady=10) 79 | 80 | entry: tk.Entry = tk.Entry(root, width=30) 81 | entry.pack(pady=5) 82 | 83 | # Generate button 84 | generate_button: tk.Button = tk.Button(root, text="Generate Password", command=display_password) 85 | generate_button.pack(pady=10) 86 | 87 | # Result label to display the generated password 88 | result_label: tk.Label = tk.Label(root, text="") 89 | result_label.pack(pady=10) 90 | result_label.password: Optional[str] = None # Store password as an optional attribute 91 | 92 | # Copy button to copy password to clipboard 93 | copy_button: tk.Button = tk.Button(root, text="Copy Password", command=copy_to_clipboard, state="disabled") 94 | copy_button.pack(pady=5) 95 | 96 | # Run the Tkinter event loop 97 | root.mainloop() 98 | -------------------------------------------------------------------------------- /Tools/distance_calculator/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Distance conversion calculator 8 | 9 | ## Features 10 | 1. GUI conversion calculator 11 | 2. Enter distance in mile 12 | 3. Avilable conversions: meter, kilo-meter, foot, and yard 13 | 14 | ## How to install and run 15 | 1. Fork the repo by clicking the fork logo on the top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 17 | 3. Head to the distance_calculator folder 18 | 4. Run the file using python command `python main.py` 19 | -------------------------------------------------------------------------------- /Tools/distance_calculator/main.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | 3 | window = tk.Tk() 4 | window.title("Distance conversion calculator") 5 | window.config(padx=40,pady=40, background="dark gray") 6 | 7 | 8 | def convert(): 9 | miles_to_km() 10 | miles_to_ft() 11 | miles_to_yd() 12 | miles_to_m() 13 | 14 | 15 | def miles_to_km(): 16 | miles = float(inp.get()) 17 | km = round(miles * 1.609) 18 | result_km.config(text=f"{km} km") 19 | 20 | def miles_to_m(): 21 | miles = float(inp.get()) 22 | m = round(miles * 1609) 23 | result_m.config(text=f"{m} m") 24 | 25 | def miles_to_ft(): 26 | miles = float(inp.get()) 27 | ft = round(miles * 5280) 28 | result_ft.config(text=f"{ft} ft") 29 | 30 | def miles_to_yd(): 31 | miles = float(inp.get()) 32 | yd = round(miles * 1760) 33 | result_yd.config(text=f"{yd} yd") 34 | 35 | 36 | start_label = tk.Label(text="Enter distance in mile") 37 | start_label.grid(row=0, column=2) 38 | start_label.config(pady=15, font=("Arial", 12), background="dark gray") 39 | 40 | inp = tk.Entry() 41 | inp.grid(row=1, column=2) 42 | inp.insert(tk.END, string="0") 43 | 44 | result_km = tk.Label(text="0 km") 45 | result_km.grid(row=2, column=0) 46 | result_km.config(padx=15, font=("Arial", 10)) 47 | 48 | result_m = tk.Label(text="0 m") 49 | result_m.grid(row=2, column=1) 50 | result_m.config(padx=15, font=("Arial", 10)) 51 | 52 | result_ft = tk.Label(text="0 ft") 53 | result_ft.grid(row=2, column=3) 54 | result_ft.config(padx=15, font=("Arial", 10)) 55 | 56 | result_yd = tk.Label(text="0 yd") 57 | result_yd.grid(row=2, column=4) 58 | result_yd.config(padx=15, font=("Arial", 10)) 59 | 60 | button = tk.Button(text="Calculate", command=convert) 61 | button.grid(row=3, column=2) 62 | button.config(borderwidth=2, font=("Arial", 12)) 63 | 64 | 65 | window.mainloop() -------------------------------------------------------------------------------- /Tools/encoding/encode.py: -------------------------------------------------------------------------------- 1 | alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] 2 | 3 | 4 | def start(): 5 | eord = input("encode? or decode? \n") 6 | msg = input("enter your message \n") 7 | shift = int(input("shifting number \n")) 8 | 9 | if eord == "encode": 10 | encode(msg, shift) 11 | elif eord == "decode": 12 | decode(msg, shift) 13 | 14 | 15 | 16 | def encode(msg, shift): 17 | encoded = "" 18 | for i in msg: 19 | let = alphabet.index(i) 20 | encoded += alphabet[let + shift] 21 | print(encoded) 22 | 23 | def decode(msg, shift): 24 | decoded = "" 25 | for i in msg: 26 | let = alphabet.index(i) 27 | decoded += alphabet[let - shift] 28 | print(decoded) 29 | 30 | 31 | start() 32 | keep = True 33 | while keep: 34 | again = input("try again? \n") 35 | if again == "yes": 36 | start() 37 | else: 38 | break -------------------------------------------------------------------------------- /Tools/kanye_says/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Kanye Say... 8 | 9 | ## Features 10 | 1. Your daily Kanye West Quotes. 11 | 2. Click the Kaynye icon for your daily quote. 12 | 13 | 14 | 15 | 16 | ## How to install and run 17 | 1. Fork the repo by clicking the fork logo on the top right 18 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 19 | 3. Head to the kanye_says folder 20 | 4. Run the file using python command `python main.py` 21 | -------------------------------------------------------------------------------- /Tools/kanye_says/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Tools/kanye_says/Screenshot.png -------------------------------------------------------------------------------- /Tools/kanye_says/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Tools/kanye_says/background.png -------------------------------------------------------------------------------- /Tools/kanye_says/kanye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Tools/kanye_says/kanye.png -------------------------------------------------------------------------------- /Tools/kanye_says/main.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import tkinter as tk 3 | 4 | # Fetch API and display 5 | def get_quote(): 6 | res = requests.get(url="https://api.kanye.rest") 7 | res.raise_for_status() 8 | data = res.json() 9 | canvas.itemconfig(quote_text, text=data["quote"]) 10 | 11 | 12 | # Window GUI 13 | window = tk.Tk() 14 | window.title("Kanye Says...") 15 | window.config(padx=50, pady=50) 16 | window.resizable(width=False, height=False) 17 | 18 | canvas = tk.Canvas(width=300, height=414) 19 | bg_img = tk.PhotoImage(file="background.png") 20 | canvas.create_image(150,207, image=bg_img) 21 | quote_text = canvas.create_text(150, 207, text="Click me!", width=250, font=("Arial", 18, "bold")) 22 | canvas.grid(row=0,column=0) 23 | 24 | btn_img = tk.PhotoImage(file="kanye.png") 25 | btn = tk.Button(image=btn_img, highlightthickness=0, command=get_quote) 26 | btn.config(bd=0) 27 | btn.grid(row=1, column=0) 28 | 29 | window.mainloop() -------------------------------------------------------------------------------- /Tools/merge_pdf/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Merge PDFs' 8 | 9 | 10 | ## Features 11 | 1. Effortless merging of PDFS from your local device. 12 | 2. Top-Notch Security. 13 | 3. Easy to use. 14 | 15 | ## How to install and run 16 | 1. Fork the repo by clicking the fork logo on the top right 17 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 18 | 3. Head to the merge_pdf folder 19 | 4. Run the file using python command `python merge_pdf.py` -------------------------------------------------------------------------------- /Tools/merge_pdf/merge_pdf.py: -------------------------------------------------------------------------------- 1 | from PyPDF2 import PdfWriter 2 | import tkinter as tk 3 | from tkinter import filedialog 4 | from tkinter import ttk 5 | 6 | ''' 7 | You have to install PyPDF2 8 | command: pip install PyPDF2 9 | ''' 10 | 11 | pdf_to_be_merged = [] #this list will contain all the select pdf files to be merged 12 | 13 | 14 | ''' 15 | function openfile 16 | opens a file manager dialog box, helps to select and open files to merged. 17 | ''' 18 | def openFile(): 19 | filename = filedialog.askopenfilename(title='Open PDF files', filetypes=[('PDF files', '*.pdf')]) 20 | if filename: 21 | pdf_to_be_merged.append(filename) 22 | update_listbox() 23 | 24 | ''' 25 | listbox will display all the files selected. 26 | ''' 27 | def update_listbox(): 28 | filenames_listbox.delete(0, tk.END) 29 | for pdf in pdf_to_be_merged: 30 | filenames_listbox.insert(tk.END, pdf) 31 | 32 | 33 | ''' 34 | using move_up and move_down 35 | we can select a pdf and can arrange the order in which it is to be merged. 36 | ''' 37 | def move_up(): 38 | selected_index = filenames_listbox.curselection() 39 | if selected_index: 40 | selected_index = int(selected_index[0]) 41 | if selected_index > 0: 42 | pdf_to_be_merged[selected_index], pdf_to_be_merged[selected_index - 1] = \ 43 | pdf_to_be_merged[selected_index - 1], pdf_to_be_merged[selected_index] 44 | update_listbox() 45 | 46 | def move_down(): 47 | selected_index = filenames_listbox.curselection() 48 | if selected_index: 49 | selected_index = int(selected_index[0]) 50 | if selected_index < len(pdf_to_be_merged) - 1: 51 | pdf_to_be_merged[selected_index], pdf_to_be_merged[selected_index + 1] = \ 52 | pdf_to_be_merged[selected_index + 1], pdf_to_be_merged[selected_index] 53 | update_listbox() 54 | 55 | 56 | 57 | ''' 58 | merge function uses the list, pdf_to_be_merged and merge pdfs' using pyPDF2 59 | after merging it will open up a file manager dialog box asking filename and location of stroing the merged pdf. 60 | ''' 61 | 62 | def merge(): 63 | try: 64 | if not pdf_to_be_merged: 65 | tk.messagebox.showwarning("No Files", "Please select PDF files to merge.") 66 | return 67 | 68 | merger = PdfWriter() 69 | for pdf in pdf_to_be_merged: 70 | merger.append(pdf) 71 | 72 | output = filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF files", "*.pdf")], 73 | title="Save Merged PDF As") 74 | if output: 75 | with open(output, "wb") as output_file: 76 | merger.write(output_file) 77 | tk.messagebox.showinfo("Merge Complete", "PDF files merged successfully.") 78 | merger.close() 79 | except Exception as e: 80 | tk.messagebox.showinfo("Error happened.", f"Error happened please try again : error message - {str(e)}") 81 | 82 | 83 | ''' 84 | reset function clears the pdf_to_merged and update_listbox, thus removing all the selected files. 85 | ''' 86 | def reset(): 87 | pdf_to_be_merged.clear() 88 | update_listbox() 89 | 90 | 91 | 92 | root = tk.Tk() 93 | root.title('PDF Merger') 94 | 95 | style = ttk.Style() 96 | style.configure("TButton", padding=6, relief="flat", background="#ccc") 97 | 98 | filenames_label = tk.Label(root, text='Selected PDF files:') 99 | filenames_label.grid(row=0, column=0, columnspan=3, pady=5) 100 | 101 | move_up_button = ttk.Button(root, text='Move Up', command=move_up) 102 | move_up_button.grid(row=1, column=0, padx=5) 103 | 104 | inputfiles_button = ttk.Button(root, text='Select PDF files', command=openFile) 105 | inputfiles_button.grid(row=1, column=1, padx=5) 106 | 107 | move_down_button = ttk.Button(root, text='Move Down', command=move_down) 108 | move_down_button.grid(row=1, column=2, padx=5) 109 | 110 | filenames_listbox = tk.Listbox(root, selectmode=tk.SINGLE, width=60, height=5) 111 | filenames_listbox.grid(row=2, column=0, columnspan=3, pady=5) 112 | 113 | mergepdf_button = ttk.Button(root, text='Merge PDF', command=merge) 114 | mergepdf_button.grid(row=3, column=1, padx=10) 115 | 116 | reset_button = ttk.Button(root, text='Reset', command=reset) 117 | reset_button.grid(row=4, column=0, padx=5) 118 | 119 | quit_button = ttk.Button(root, text="Quit", command=root.destroy) 120 | quit_button.grid(row=4, column=2, padx=5) 121 | 122 | root.geometry("400x300") #intital dimensions of tkinter window 123 | 124 | 125 | 126 | 127 | root.mainloop() 128 | -------------------------------------------------------------------------------- /Tools/pomodoro_timer/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Pomodoro Timer 8 | 9 | ## What is the Pomodoro Technique? 10 | 1. The Pomodoro Technique is a time management method based on 25 miniute streches of focused work broken by 5 mintue breaks 11 | 2. It was developed in the late 1980s by Francesco Crillo 12 | 3. It is highly effective as it helps you effectively manage your time and work on a task without distractions. It is also beneficial as it helps you become more disciplined and think about your work. This technique is designed to combat multitasking and improve concentration. 13 | 14 | ## Features 15 | 16 | 17 | ## How to install and run 18 | 1. Fork the repo by clicking the fork logo on the top right 19 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 20 | 3. Head to the pomodoro_timer folder 21 | 4. Run the file using python command `python main.py` -------------------------------------------------------------------------------- /Tools/pomodoro_timer/main.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from time import sleep 3 | import math 4 | 5 | # Global val 6 | PINK = "#e2979c" 7 | RED = "#e7305b" 8 | GREEN = "#9bdead" 9 | YELLOW = "#f8e2aa" 10 | FONT_NAME = "Courier" 11 | WORK_MIN = 25 12 | SHORT_BREAK_MIN = 5 13 | LONG_BREAK_MIN = 20 14 | 15 | reps = 0 16 | timer = None 17 | 18 | 19 | # Raise window in after each cycle 20 | def raise_above_all(window): 21 | window.attributes('-topmost', 1) 22 | window.attributes('-topmost', 0) 23 | 24 | 25 | # Reset timer 26 | def reset(): 27 | global reps 28 | 29 | window.after_cancel(timer) 30 | canvas.itemconfig(time, text="00:00") 31 | start_label.config(text="Timer", fg=GREEN, bg=YELLOW) 32 | check_mark.config(text="") 33 | reps = 0 34 | 35 | 36 | # Pass correct time to the count_down function 37 | def start_timer(): 38 | global reps 39 | reps += 1 40 | 41 | if reps > 1: 42 | window.after_cancel(timer) 43 | 44 | if reps % 8 == 0: 45 | count_down(LONG_BREAK_MIN * 60) 46 | start_label.config(text="Break", fg=RED, bg=YELLOW) 47 | elif reps % 2 == 0: 48 | count_down(SHORT_BREAK_MIN * 60) 49 | start_label.config(text="Break", fg=PINK, bg=YELLOW) 50 | else: 51 | count_down(WORK_MIN * 60) 52 | start_label.config(text="Work", fg=GREEN, bg=YELLOW) 53 | 54 | 55 | # Count down 56 | def count_down(count): 57 | global timer 58 | 59 | min = math.floor(count / 60) 60 | sec = count % 60 61 | 62 | # Better display 63 | if sec < 10: 64 | sec = f"0{sec}" 65 | 66 | canvas.itemconfig(time, text=f"{min}:{sec}") 67 | 68 | if count > 0: 69 | timer = window.after(1000, count_down, count - 1) 70 | else: 71 | start_timer() 72 | mark = "" 73 | raise_above_all(window) 74 | 75 | for _ in range(math.floor(reps / 2)): 76 | mark += " ✔ " 77 | check_mark.config(text=mark) 78 | if reps > 8: 79 | reset() 80 | 81 | 82 | # Add tasks to list_box 83 | def new_task(): 84 | task = todo_entry.get() 85 | 86 | if task != "": 87 | list_box.insert(tk.END, task) 88 | todo_entry.delete(0, "end") 89 | 90 | 91 | # Delete tasks from list_box 92 | def del_task(): 93 | list_box.delete(tk.ANCHOR) 94 | 95 | 96 | # GUI 97 | window = tk.Tk() 98 | window.title("Pomodoro Timer") 99 | window.config(padx=100, pady=60, bg=YELLOW) 100 | 101 | canvas = tk.Canvas(width=200, height=224, bg=YELLOW, highlightthickness=0) 102 | img = tk.PhotoImage(file="tomato.png") 103 | canvas.create_image(100, 112, image=img) 104 | time = canvas.create_text(100,135, text="00:00", fill="white", font=(FONT_NAME, 35, "bold")) 105 | 106 | start_label = tk.Label(text="Timer") 107 | start_label.config(fg=GREEN, bg=YELLOW, font=(FONT_NAME, 40, "bold")) 108 | 109 | start_btn = tk.Button(text="Start", command=start_timer) 110 | start_btn.config(bg=GREEN, font=(FONT_NAME, 12), activebackground=GREEN) 111 | 112 | reset_btn = tk.Button(text="Reset", command=reset) 113 | reset_btn.config(bg=GREEN, font=(FONT_NAME, 12), activebackground=GREEN) 114 | 115 | check_mark = tk.Label() 116 | check_mark.config(fg=RED, bg=YELLOW, font=(FONT_NAME, 8)) 117 | 118 | todo_label = tk.Label(text="Tasks", font=(FONT_NAME, 16, "bold")) 119 | todo_label.config(bg=YELLOW, fg=PINK) 120 | 121 | list_box = tk.Listbox( 122 | width=25, 123 | height=8, 124 | font=(FONT_NAME, 12), 125 | bg=YELLOW, 126 | highlightthickness=0, 127 | selectbackground=PINK, 128 | activestyle="none" 129 | ) 130 | 131 | todo_entry = tk.Entry(font=(FONT_NAME, 12)) 132 | 133 | addtodo = tk.Button(text="Add", font=(FONT_NAME, 8), command=new_task) 134 | addtodo.config(bg=PINK, activebackground=PINK, width=5) 135 | 136 | deltodo = tk.Button(text="Delete", font=(FONT_NAME, 8), command=del_task) 137 | deltodo.config(bg=PINK, activebackground=PINK, width=5) 138 | 139 | # GUi grid 140 | start_label.grid(row=0, column=1) 141 | canvas.grid(row=1, column=1) 142 | start_btn.grid(row=2, column=0) 143 | reset_btn.grid(row=2, column=2) 144 | check_mark.grid(row=3, column=1) 145 | todo_label.grid(row=4,column=1) 146 | list_box.grid(row=5, column=1) 147 | todo_entry.grid(row=6, column=1) 148 | addtodo.grid(row=7, column=2) 149 | deltodo.grid(row=8, column=2) 150 | 151 | window.mainloop() -------------------------------------------------------------------------------- /Tools/pomodoro_timer/screen_shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Tools/pomodoro_timer/screen_shot.png -------------------------------------------------------------------------------- /Tools/pomodoro_timer/tomato.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/Tools/pomodoro_timer/tomato.png -------------------------------------------------------------------------------- /Tools/qrcode_gen/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # QRcode generator 8 | 9 | ## Features 10 | 1. Created with qrcode module 11 | 2. Custom qrcode can be generated and the default 12 | 3. Easy to use 13 | 14 | ## How to install and run 15 | 1. Fork the repo by clicking the fork logo on the top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 17 | 3. Head to the qrcode_gen folder 18 | 4. Run the file using python command `python main.py` 19 | 20 | 21 | -------------------------------------------------------------------------------- /Tools/qrcode_gen/main.py: -------------------------------------------------------------------------------- 1 | import qrcode 2 | 3 | def create(data): 4 | qr = qrcode.make(data) 5 | qr.save('qrcode.png') 6 | 7 | def create_custom(data, size=10, border=2, bg='white', fill='black'): 8 | qr = qrcode.QRCode( 9 | box_size=size, 10 | border=border 11 | ) 12 | qr.add_data(data) 13 | qr.make(fit=True) 14 | res = qr.make_image(fill_color=fill,back_color=bg) 15 | res.save('qrcode.png') 16 | 17 | if __name__ == '__main__': 18 | while True: 19 | cont = input('Press Enter to continue or (Q) to Quit\n') 20 | data = input('Enter the data you want to generate\n') 21 | custom = input('Would you like to custom your qrcode? (Yes or No) \n').lower() 22 | if custom == 'yes' or custom == 'y': 23 | size = input('Enter the size of the qrcode (Enter for default)\n') 24 | border = input('Enter the border width (Enter for default)\n') 25 | bg = input('Enter the background color (Enter for default)\n') 26 | fill = input('Enter the fill color (Enter for default)\n') 27 | 28 | create_custom(data, size, border, bg, fill) 29 | 30 | elif custom == 'no' or custom == 'n': 31 | create(data) 32 | 33 | else: 34 | print('Please enter "Yes" or "No"') 35 | -------------------------------------------------------------------------------- /Tools/remove_duplicates/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Name of your tool 8 | A simple Python tool to clean up txt, CSV, JSON, xlsx, xml files by removing duplicate lines while preserving the order. The tool removes duplicate lines within the file and saves to new file. 9 | ## Features 10 | 1. Removes duplicate lines within a txt, CSV, JSON, xlsx, xml file to create a clean, organized version 11 | 2. Preserves the original line order while filtering out duplicates 12 | 13 | ## How to install and run 14 | 1. Fork the repo by clicking the fork logo on the top right 15 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 16 | 3. Head to the remove_duplicates folder 17 | 4. Run the file using python command ` python main_gui.py` -------------------------------------------------------------------------------- /Tools/remove_duplicates/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import csv 3 | import json 4 | import subprocess 5 | import sys 6 | import xml.etree.ElementTree as ET 7 | 8 | 9 | def ensure_package_installed(package_name): 10 | try: 11 | __import__(package_name) 12 | except ImportError: 13 | print(f"Installing {package_name}...") 14 | subprocess.check_call([sys.executable, "-m", "pip", "install", package_name]) 15 | 16 | ensure_package_installed("pandas") 17 | ensure_package_installed("openpyxl") 18 | 19 | import pandas as pd 20 | 21 | 22 | def remove_duplicates(input_file, output_file): 23 | file_ext = os.path.splitext(input_file)[1].lower() 24 | 25 | if file_ext == '.txt': 26 | process_text_file(input_file, output_file) 27 | elif file_ext == '.csv': 28 | process_csv_file(input_file, output_file) 29 | elif file_ext == '.json': 30 | process_json_file(input_file, output_file) 31 | elif file_ext == '.xlsx': 32 | process_excel_file(input_file, output_file) 33 | elif file_ext == '.xml': 34 | process_xml_file(input_file, output_file) 35 | else: 36 | raise ValueError(f"Unsupported file format: {file_ext}") 37 | 38 | 39 | def process_text_file(input_file, output_file): 40 | unique_lines = set() 41 | with open(input_file, 'r') as infile: 42 | lines = infile.readlines() 43 | unique_lines = list(dict.fromkeys(line.strip() for line in lines)) 44 | 45 | with open(output_file, 'w') as outfile: 46 | outfile.write('\n'.join(unique_lines)) 47 | 48 | 49 | def process_csv_file(input_file, output_file): 50 | unique_rows = set() 51 | with open(input_file, 'r') as infile: 52 | reader = csv.reader(infile) 53 | unique_rows = {tuple(row) for row in reader} 54 | 55 | with open(output_file, 'w', newline='') as outfile: 56 | writer = csv.writer(outfile) 57 | writer.writerows(list(unique_rows)) 58 | 59 | 60 | def process_json_file(input_file, output_file): 61 | with open(input_file, 'r') as infile: 62 | data = json.load(infile) 63 | 64 | if isinstance(data, list): 65 | unique_data = list({json.dumps(item, sort_keys=True) for item in data}) 66 | unique_data = [json.loads(item) for item in unique_data] 67 | 68 | with open(output_file, 'w') as outfile: 69 | json.dump(unique_data, outfile, indent=4) 70 | else: 71 | raise ValueError("Only JSON arrays are supported.") 72 | 73 | 74 | def process_excel_file(input_file, output_file): 75 | df = pd.read_excel(input_file) 76 | df.drop_duplicates(inplace=True) 77 | df.to_excel(output_file, index=False) 78 | 79 | 80 | def process_xml_file(input_file, output_file): 81 | tree = ET.parse(input_file) 82 | root = tree.getroot() 83 | 84 | seen = set() 85 | unique_elements = [] 86 | for element in root: 87 | serialized = ET.tostring(element, encoding='unicode') 88 | if serialized not in seen: 89 | seen.add(serialized) 90 | unique_elements.append(element) 91 | 92 | new_root = ET.Element(root.tag) 93 | for unique_element in unique_elements: 94 | new_root.append(unique_element) 95 | 96 | new_tree = ET.ElementTree(new_root) 97 | new_tree.write(output_file, encoding='unicode') 98 | 99 | 100 | -------------------------------------------------------------------------------- /Tools/remove_duplicates/main_gui.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter import filedialog, messagebox 3 | from main import remove_duplicates 4 | import os 5 | 6 | 7 | def select_input_file(): 8 | input_file = filedialog.askopenfilename( 9 | title="Select Input File", 10 | filetypes=[("Supported Files", "*.txt *.csv *.json *.xlsx *.xml")] 11 | ) 12 | input_file_entry.delete(0, tk.END) 13 | input_file_entry.insert(0, input_file) 14 | 15 | 16 | def process_file(): 17 | input_file = input_file_entry.get() 18 | output_file = output_file_entry.get() 19 | 20 | if not input_file: 21 | messagebox.showerror("Input Error", "Please select an input file.") 22 | return 23 | 24 | if not output_file: 25 | file_ext = os.path.splitext(input_file)[1] 26 | default_output = f"{os.path.splitext(input_file)[0]}_output{file_ext}" 27 | output_file_entry.delete(0, tk.END) 28 | output_file_entry.insert(0, default_output) 29 | output_file = default_output 30 | 31 | try: 32 | remove_duplicates(input_file, output_file) 33 | messagebox.showinfo("Success", f"Duplicates removed and saved to {output_file}.") 34 | except Exception as e: 35 | messagebox.showerror("Error", f"An error occurred: {e}") 36 | 37 | 38 | # GUI Setup 39 | root = tk.Tk() 40 | root.title("Duplicate Remover") 41 | 42 | # Input File Selection 43 | tk.Label(root, text="Input File:").grid(row=0, column=0, padx=5, pady=5) 44 | input_file_entry = tk.Entry(root, width=50) 45 | input_file_entry.grid(row=0, column=1, padx=5, pady=5) 46 | tk.Button(root, text="Browse", command=select_input_file).grid(row=0, column=2, padx=5, pady=5) 47 | 48 | # Output File Input 49 | tk.Label(root, text="Output File:").grid(row=1, column=0, padx=5, pady=5) 50 | output_file_entry = tk.Entry(root, width=50) 51 | output_file_entry.grid(row=1, column=1, padx=5, pady=5) 52 | 53 | # Process Button 54 | tk.Button(root, text="Remove Duplicates", command=process_file, bg="blue", fg="white").grid( 55 | row=2, column=1, pady=20) 56 | 57 | root.mainloop() 58 | -------------------------------------------------------------------------------- /Tools/text_summarizer/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Simple Text Summarizer 8 | 9 | 10 | ## Features 11 | 1. Effortless extarction of summary from text corpus. 12 | 2. Easy to use. 13 | 14 | ## How to install and run 15 | 1. Fork the repo by clicking the fork logo on the top right 16 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-tools-and-games.git` 17 | 3. Head to the text_summarizer folder 18 | 4. Run the file using python command `python main.py` -------------------------------------------------------------------------------- /Tools/text_summarizer/main.py: -------------------------------------------------------------------------------- 1 | from nltk.corpus import stopwords 2 | from nltk.tokenize import sent_tokenize 3 | from nltk.tokenize import word_tokenize 4 | import tkinter as tk 5 | from tkinter import filedialog 6 | from tkinter import ttk 7 | 8 | 9 | #please run: pip install nltk 10 | 11 | import nltk 12 | 13 | ''' 14 | if running nltk.download using jio wifi( Indian telecom service), please use a VPN or try using hotspot 15 | refer to: https://github.com/nltk/nltk/issues/3140 16 | ''' 17 | nltk.download('stopwords') 18 | nltk.download('punkt') 19 | 20 | 21 | text = "" 22 | summaryx = "" 23 | 24 | ''' 25 | open file function opens a dialog box, which allows text files to be selected 26 | and data from text file is shown onto the screen. 27 | ''' 28 | def openFile(): 29 | global text 30 | filename = filedialog.askopenfilename( 31 | title='Open text files', filetypes=[('Text files', '*.txt')]) 32 | 33 | with open(filename, 'r') as f: 34 | text_cur = f.read() 35 | 36 | text += text_cur 37 | T.delete('1.0', tk.END) 38 | T.insert(tk.END, text) 39 | 40 | ''' 41 | reset button flushes out selected text files and currently generated summary. 42 | ''' 43 | def reset(): 44 | global text 45 | global summaryx 46 | text = "" 47 | summaryx = "" 48 | 49 | T.delete('1.0', tk.END) 50 | T_summary.delete('1.0', tk.END) 51 | 52 | 53 | 54 | ''' 55 | summary function extracts the summary from the text. 56 | methodology 57 | 1. create a word vectors list using word_tokenize from nltk, ignore all stop words. 58 | 2. create a sentence vector using sent_tokenize from nltk 59 | 3. give a importance value to sentences, by checking occurence of words in sentence. 60 | 4. calculate the average importance. 61 | 5. dispalyed sentences with higher importance than certain average. 62 | ''' 63 | def summary(): 64 | 65 | global text 66 | global summaryx 67 | 68 | stop_words = set(stopwords.words('english')) 69 | 70 | words = word_tokenize(text) 71 | 72 | words_freq = {} 73 | 74 | for word in words: 75 | if word in stop_words: 76 | continue 77 | elif word in words_freq: 78 | words_freq[word] += 1 79 | elif word not in words_freq: 80 | words_freq[word] = 1 81 | 82 | sentences = sent_tokenize(text) 83 | 84 | sentence_value = {} 85 | 86 | for sentence in sentences: 87 | for wordx, freq in words_freq.items(): 88 | 89 | if wordx in sentence.lower(): 90 | sentence_value[sentence] += freq 91 | else: 92 | sentence_value[sentence] = freq 93 | 94 | sum_val = 0 95 | for sentence in sentence_value: 96 | sum_val += sentence_value[sentence] 97 | 98 | average = sum_val // len(sentence_value) 99 | 100 | for sentence in sentences: 101 | if sentence in sentence_value and sentence_value[sentence] > (1.2 * average): 102 | summaryx += " " + sentence 103 | 104 | T_summary.delete('1.0', tk.END) 105 | T_summary.insert(tk.END, summaryx) 106 | 107 | 108 | root = tk.Tk() 109 | root.title('Text Summarizer') 110 | 111 | # Text widget 112 | T = tk.Text(root, height=20, width=52) 113 | T.insert(tk.END, "Text here!") 114 | T.grid(row=0, column=0, columnspan=3, pady=5, sticky="ew") 115 | 116 | # Select Text file button 117 | inputfiles_button = ttk.Button(root, text='Select Text file', command=openFile) 118 | inputfiles_button.grid(row=1, column=0, columnspan=3, 119 | padx=6, pady=6, sticky="nsew") 120 | 121 | # Reset button 122 | reset_button = ttk.Button(root, text='Reset', command=reset) 123 | reset_button.grid(row=2, column=1, padx=5) 124 | 125 | # Generate summary button 126 | generate_summary_button = ttk.Button( 127 | root, text='Generate summary', command=summary) 128 | generate_summary_button.grid(row=2, column=0, padx=5) 129 | 130 | # Text widget for summary 131 | T_summary = tk.Text(root, height=10, width=52) 132 | T_summary.insert(tk.END, "summary......") 133 | T_summary.grid(row=3, column=0, columnspan=3, pady=5, sticky="ew") 134 | 135 | inputfiles_button = ttk.Button(root, text='Exit', command=root.destroy) 136 | inputfiles_button.grid(row=4, column=0, columnspan=3, 137 | padx=6, pady=6, sticky="nsew") 138 | 139 | # Make the columns and rows resizable 140 | root.columnconfigure(0, weight=1) 141 | root.columnconfigure(1, weight=1) 142 | root.rowconfigure(0, weight=1) 143 | root.rowconfigure(1, weight=1) 144 | root.rowconfigure(2, weight=1) 145 | root.rowconfigure(3, weight=1) 146 | 147 | root.mainloop() 148 | -------------------------------------------------------------------------------- /Tools/tip_calculator/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # Tip Calculator / Splitter 8 | 9 | ## Features 10 | 1. This program splits a given amount of bill and tip equally between a given number of persons eg it can split $120 alongside a tip of 12% equally between 5 persons and gives you the amount each person is expected to pay 11 | 2. Follow the prompts and enter the required information and the app handles the rest for you 12 | 13 | ## How to install and run 14 | 1. Fork the repo by clicking the fork logo on the top right 15 | 2. Clone the repo `git clone git@github.com:AseanK/beginner-python-games.git` 16 | 3. Head to the tip_calculator folder 17 | 4. Run the file using python command `python main.py` -------------------------------------------------------------------------------- /Tools/tip_calculator/main.py: -------------------------------------------------------------------------------- 1 | # If the bill is $150.00, split between 5 persons 2 | # Each person should pay (150.00/5) * 1.12 = $33.6 3 | # round the result to 2 decimal places 4 | 5 | print("Welcome to the tip Calculator") 6 | bill = float(input("What was the total bill? $")) 7 | tip = int(input("How much tip would you like to give? 10, 12 or 15 ")) 8 | people = int(input("How many people to split the bill?")) 9 | bill_with_tip = (bill + (tip/100 * bill)) 10 | print(bill_with_tip) 11 | bill_per_head = (bill_with_tip / people) 12 | print("Bill per person is " "$" + str(bill_per_head)) -------------------------------------------------------------------------------- /images/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/images/fork.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/images/logo.png -------------------------------------------------------------------------------- /images/mainLogo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/images/mainLogo.jpg -------------------------------------------------------------------------------- /images/main_logo.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/images/main_logo.JPG -------------------------------------------------------------------------------- /images/tools_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AseanK/python-tools-and-games/5f8fb7fcba5a00995866023cc7106efa184454ee/images/tools_logo.png --------------------------------------------------------------------------------