9
\$\begingroup\$

A few weeks ago, I developed a terminal game that increases your typing speed. The game is all about typing, providing difficulty levels from easy to hard. I feel like this terminal game won't become as popular as my others, so I need tips on how I could improve this code to make it shorter, easier to run, and more entertaining.

Here is the code developed by me, PYWPM:

import time import random logo = ''' _____ __ _______ __ __ | __ \ \ \ / / __ \| \/ | | |__) | \ \ /\ / /| |__) | \ / | | ___/ | | \ \/ \/ / | ___/| |\/| | | | | |_| |\ /\ / | | | | | | |_| \__, | \/ \/ |_| |_| |_| __/ | |___/ ''' print(logo) print(" ") difficulty = input("Enter difficulty level (easy/hard): ") if difficulty == "easy": openPlz = open('easywordbank.txt','r') readPlz = openPlz.read() wordBank = readPlz.split() elif difficulty == "hard": openPlz = open('hardwordbank.txt','r') readPlz = openPlz.read() wordBank = readPlz.split() open2 = open('highscore.txt','r+') open2lst = open2.readlines() stat = True strike = 0 score = 0 def gameMain(wordBank): #Primary game loop. Returns a lst: #lst[0] = added points, lst[1] = added strikes lst = [0,0] start = time.time() wordQuiz = wordBank[random.randint(0,(len(wordBank)-1))] wordType = input('Enter the word, '+ wordQuiz + ' : ') if wordType == wordQuiz and time.time()-start < 3: lst[0] += 1 elif time.time()-start >= 3: print('STRIKE! Too Slow! ') lst[1] += 1 else: print('STRIKE! Watch your spelling. Be careful with strikes!') lst[1] += 1 return lst def highScore(name,score,highScoreLst,zFile): for line in highScoreLst: if score >= int(line[-3:-1]): highScoreLst.insert(highScoreLst.index(line),name+'-'+str(score)+'\n') highScoreLst.pop() zFile.seek(0,0) zFile.writelines(highScoreLst) break def rsg(): print('Ready?') time.sleep(1) print('Set?') time.sleep(1) print('Go!') time.sleep(1) name = input('Enter a username for this session: ') print("Type the word then press enter in under 3 seconds!") time.sleep(2) rsg() #MainState while stat == True: lst = gameMain(wordBank) score += lst[0] strike += lst[1] if strike == 3: time.sleep(.5) print('Game Over! The game has ended..!\n') time.sleep(2) print('Your Typing & Accuracy Score: ' + str(score)) highScore(name,score,open2lst,open2) time.sleep(2) break print('\nHighscores for PyWPM:') time.sleep(2) for line in open2lst: print(line, end='') time.sleep(1.5) time.sleep(5) openPlz.close() open2.close() 
  1. Yes, this game includes a word bank that randomizes words.
  2. The high scores aren't global.

How could I make this better?

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

I made some changes to your code, here's the description:

  • Indentation correction;
  • Removal of possible spaces in user input;
  • Change of While stat ==. True for While stat. It's the same thing;
  • PEP8 (and good practices) use 1 blank space after a comma and 2 line breaks before and after the functions;
  • You can also simplify the import of packages by specifying exactly what you are going to use: I did it in the code below;
  • Finally, the documentation always provides for an empty line break at the end of the code.
from time import time, sleep from random import randint logo = ''' _____ __ _______ __ __ | __ \ \ \ / / __ \| \/ | | |__) | \ \ /\ / /| |__) | \ / | | ___/ | | \ \/ \/ / | ___/| |\/| | | | | |_| |\ /\ / | | | | | | |_| \__, | \/ \/ |_| |_| |_| __/ | |___/ ''' print(logo) print(" ") difficulty = input("Enter difficulty level (easy/hard): ").strip if difficulty == "easy": openPlz = open('easywordbank.txt', 'r') readPlz = openPlz.read() wordBank = readPlz.split() elif difficulty == "hard": openPlz = open('hardwordbank.txt', 'r') readPlz = openPlz.read() wordBank = readPlz.split() open2 = open('highscore.txt', 'r+') open2lst = open2.readlines() stat = True strike = 0 score = 0 def gameMain(wordBank): """ Primary game loop. Returns a lst: #lst[0] = added points, lst[1] = added strikes :param wordBank: :return: """ lst = [0, 0] start = time() wordQuiz = wordBank[randint(0,(len(wordBank)-1))] wordType = input('Enter the word, '+ wordQuiz + ' : ') if wordType == wordQuiz and time()-start < 3: lst[0] += 1 elif time()-start >= 3: print('STRIKE! Too Slow! ') lst[1] += 1 else: print('STRIKE! Watch your spelling. Be careful with strikes!') lst[1] += 1 return lst def highScore(name, score, highScoreLst, zFile): for line in highScoreLst: if score >= int(line[-3:-1]): highScoreLst.insert(highScoreLst.index(line), name+'-'+str(score)+'\n') highScoreLst.pop() zFile.seek(0, 0) zFile.writelines(highScoreLst) break def rsg(): print('Ready?') sleep(1) print('Set?') sleep(1) print('Go!') sleep(1) name = input('Enter a username for this session: ') print("Type the word then press enter in under 3 seconds!") sleep(2) rsg() # MainState while stat: lst = gameMain(wordBank) score += lst[0] strike += lst[1] if strike == 3: sleep(.5) print('Game Over! The game has ended..!\n') sleep(2) print('Your Typing & Accuracy Score: ' + str(score)) highScore(name, score, open2lst, open2) sleep(2) break print('\nHighscores for PyWPM:') sleep(2) for line in open2lst: print(line, end='') sleep(1.5) sleep(5) openPlz.close() open2.close() 
\$\endgroup\$
0
5
\$\begingroup\$

There's a lot.

  • logo should be LOGO since it's a constant. The other global code, such as acquiring the difficulty, should be moved into functions
  • Consider generating the difficulty list based off of a file glob from your actual dictionaries
  • openPlz is not a great variable name; consider word_bank_file
  • stat is wholly unneeded and you only need a while True; or better yet a loop whose predicate checks the number of strikes
  • Use monotonic instead of time; the latter will fail in weird and wonderful ways on some time edge cases
  • Save 3 to a global constant
  • Consider adding a maximum number of saved high scores
  • Doing a simple sort will reduce complexity in highScore
  • highScore should be named high_score by PEP8
  • rsg is a poor function name; consider countdown
  • Do not return a list from gameMain; instead return a tuple of two integers, which is more standard
  • Call random.choice instead of juggling list indices

Suggested

from time import sleep, monotonic import random from pathlib import Path from typing import List, Tuple, TextIO, Iterable, Sequence LOGO = ''' _____ __ _______ __ __ | __ \ \ \ / / __ \| \/ | | |__) | \ \ /\ / /| |__) | \ / | | ___/ | | \ \/ \/ / | ___/| |\/| | | | | |_| |\ /\ / | | | | | | |_| \__, | \/ \/ |_| |_| |_| __/ | |___/ ''' TIMEOUT = 3 MAX_SCORES = 10 def load_words(bank_dir: Path) -> List[str]: """ Pulled from: https://simple.wikipedia.org/wiki/Wikipedia:List_of_1000_basic_words https://raw.githubusercontent.com/dwyl/english-words/master/words.txt """ paths = tuple(bank_dir.glob('*-word-bank.txt')) stems = {p.stem.split('-', 1)[0].lower(): p for p in paths} diffs = '/'.join(stems.keys()) prompt = f'Enter difficulty level ({diffs}): ' while True: diff = input(prompt) path = stems.get(diff.lower()) if path is None: print('Invalid difficulty') else: break with path.open() as f: return [line.rstrip() for line in f] def countdown() -> None: for msg in ('Ready?', 'Set?', 'Go!'): sleep(1) print(msg, end=' ') print() def game_main(word_bank: Sequence[str]) -> Tuple[ int, # added points int, # added strikes ]: start = monotonic() request = random.choice(word_bank) answer = input(f'Enter the word - {request} : ') if monotonic() - start >= TIMEOUT: print('STRIKE! Too Slow!') return 0, 1 if request == answer: return 1, 0 print('STRIKE! Watch your spelling. Be careful with strikes!') return 0, 1 def update_high_scores(name: str, score: int, file: TextIO) -> List[Tuple[int, str]]: file.seek(0) scores = [(score, name)] for line in file: name, score = line.rsplit(' - ', 1) scores.append((int(score), name)) scores.sort(reverse=True) scores = scores[:MAX_SCORES] file.truncate(0) for score, name in scores: file.write(f'{name} - {score}\n') return scores def print_high_scores(scores: Iterable[Tuple[int, str]]) -> None: print('Highscores for PyWPM:') for score, name in scores: print(f'{name} - {score}') sleep(0.5) def main() -> None: print(LOGO) word_bank = load_words(Path('.')) name = input('Enter a username for this session: ') print(f"Type the word then press enter in under {TIMEOUT} seconds!") countdown() strike, score = 0, 0 while strike < 3: score_addend, strike_addend = game_main(word_bank) score += score_addend strike += strike_addend print( 'Game Over! The game has ended..!\n' f'Your Typing & Accuracy Score: {score}' ) with open('highscore.txt', 'a+') as highscore_file: scores = update_high_scores(name, score, highscore_file) print_high_scores(scores) if __name__ == '__main__': main() 
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.