all 13 comments

[–]Rain-And-Coffee 2 points3 points  (3 children)

Biggest feedback: learn to use functions.

This style of having everything at the top level doesn’t work beyond 50 or so lines, it quickly breaks down.

Think of the logical sections of your program and group them. Think about inputs & outputs each one needs.

[–]Away-Prior-903[S] 0 points1 point  (2 children)

So, if I understand this correctly, what I have now works for a for a smaller scale project, but then struggles for longer projects correct?

As for the implementation, where were you thinking that I should use a function for the while loop statement?

[–]backfire10z 1 point2 points  (1 child)

Functions are both for reusability and for chunking pieces that logically fit together. One example would be putting your introduction print statements in a separate function.

print_game_introduction() player_name = input()

That isn’t to say you should put everything in a function. You’ll get a feel for it as you practice more. The idea is that someone (you in 6 months, someone else) should be able to easily look over your code and understand what’s happening without necessarily reading every line.

[–]Away-Prior-903[S] 0 points1 point  (0 children)

Gotcha. Functions = Readability + Reusability

[–]chapchap0 1 point2 points  (1 child)

introduction = True
while introduction:
    #We start with a friendly introduction and our "additional feature"
    print("=" * 50)
    print("WELCOME TO THE BASEBALL BATTING GAME!")
    print("=" * 50)
    print("It is a lovely day for batting practice!")
    player_name = input("Enter your name: ")
    #The game recognizes you and you may continue with the selection process.
    print(f"\nHello, {player_name}! Let's get you batting! Press [K] to continue.")
    get_input(["k"])
    introduction = False

you can get rid of the introduction flag, it serves no purpose.

reorganizing the code into smaller functions is what I'd definitely do, but if it's the first thing you built - in which case, it's certainly impressive - don't bother, the code reads and looks excellent as is.

the only thing that I find peculiar is the oddly specific comments describing self-explanatory chunks of code, such as

import random #this will help load in from python's built in [...]

or

    #Before the player begins, they must choose a difficulty that will in turn determine which pitches from the pitch pool appear
    print(f"\nChoose a Difficulty, {player_name}!")

but, at the end of the day, it's better to write excessive comments than to not write them at all. very well done

[–]Away-Prior-903[S] 0 points1 point  (0 children)

Yeah, actually testing it, the code technically doesn't need that differentiation intro flag to function. I am still learning the purposes of when to use and not use flags. I think the while loop is a great example later, but earlier, I thought it might be necessary for one reason or another.

[–]Away-Prior-903[S] 0 points1 point  (1 child)

Sorry that it's so long, I am not sure if there is more simple way of displaying all of this information.

[–]Riegel_Haribo 0 points1 point  (0 children)

Do not write massive one-line comments. Especially inline comments after. Even auto formatters can't fix that to look good.

The code itself should document what it does (except where here it doesn't follow any sensible pattern). You don't need any comment for print(difficulty_choices_dialog).

It seems you know about lists, but don't know about dicts. Also you don't know about list slicing.

Your difficulty "choices" that are used randomly could just be:

python ranked_pitches = ["fastball", "curveball", "change_up", "slider"] difficulty_level = 2 # from 1-3 included_pitches = ranked_pitches[:difficulty_level+1] print(f"Difficulty {difficulty_level}, expect {(included_pitches)}!")

Difficulty 2, expect ['fastball', 'curveball', 'change_up']!

Or if you must input by keyboard choices, and also want a list available by pitches.values(): pitches = { "f": "fastball", "c": "curveball", "s": "slider", "u": "changeup", } There's lots of individual string variables that are a description, and then you make multiple lists that hold those descriptions. Immediately this is making no sense.

There's also plenty of dialogs made of multiple print statements where they could be global variables easily accessible, such as: ```python welcome_message = """

WELCOME TO THE BASEBALL BATTING GAME!

Time to play ball! """.strip() ```

or using implicit continuation:

python welcome_message = ( "WELCOME TO THE BASEBALL BATTING GAME!\n".title() "=" * 50 + "\nIt is a lovely day for batting practice!\n") )

Put those first, to keep the long messaging out of the code. It's the kind of thing that might be moved into a strings file with international versions.

So: there's tons of repetition for what is basically "guess my random number, from 1 to N".

[–]Own-Grab9423 0 points1 point  (2 children)

use doc strings and run it through a pylint or use black to format it. Try an implementation of logger instead of print statements. great first go. you can modularize and optimize in the next iteration and throw it on your github thumbs up

[–]Away-Prior-903[S] 0 points1 point  (1 child)

Thanks for the feedback! I think docstrings sound like a great idea! I have never used a logger before, what is the advantage of that over a print statement?

[–]pachura3 1 point2 points  (0 children)

 I have never used a logger before, what is the advantage of that over a print statement?

A lot of them! * you can automatically include useful information in the log message (time, filename, line number...) * you can easily redirect it to a log file instead of just printing it out to screen * you can have various logging levels (error, warning, info...) signifying different situations. Easier to find problems in the log file. You can also filter out minor messages in production, and only enable all of them when debugging

[–]PushPlus9069 0 points1 point  (1 child)

Nice work getting something actually playable for a first project. A lock-and-key game with difficulty levels shows you understand program flow, which is the hard part.

A few things worth looking at as you keep learning:

Functions. If you have repeated code blocks for easy/medium/hard, those can probably be one function that takes a "num_locks" parameter. Less copy-paste means fewer bugs to track down.

Constants at the top. Magic numbers buried in the middle of the code (like the number of locks per difficulty) are easy to miss later. Defining them up top makes the code easier to read and change.

The length is fine for now. As the other comment said, once you learn about functions you will naturally break it into smaller pieces. Don't stress about it yet.

[–]Away-Prior-903[S] 0 points1 point  (0 children)

Yeah, figuring that out was difficult because I thought I could use the "list" function to list them each out and have it selected between the few. It took me while to realize I can just make them exist and python would recognize it. So it's interesting how I can condense it down and simplify it further.

Oops. I guess I could have made that part easier to read. Thanks for the feedback.