текстовая ролевая игра с выбором персонажей на питоне

Я делаю ролевую игру, используя Python. На данный момент я запрограммировал выбор вашего персонажа и его сохранение.

Однако сегодня я ранее задавал вопрос NameError: name 'character' is not defined на stackoverflow. Пока я получил ответ на свой вопрос и моя программа теперь работает, я получил комментарий на свой вопрос (от человека с репутацией 15 000, так что я предполагаю, что им можно доверять), в котором говорится:

#BTW: После исправления перенесите код на codereview.stackexchange.com, там есть несколько очень плохих практик

Я предполагаю, что этот человек имел в виду мой код, поэтому я пришел сюда, чтобы получить обратную связь.

Пока я beginner и я не уверен, как исправить любые плохие практики, которые я сделал, я знаю, что критика — это только хорошо, и я могу учиться на своих ошибках. Мне было интересно, может ли кто-нибудь указать на что-нибудь / дать мне несколько советов о том, что я мог бы улучшить с моей программой. Спасибо.

Мой полный код:

from os import system
from ascii_art_functions import mountain_range
from ascii_art_functions import character_selection_horse_and_knight
from ascii_art_functions import screen_line

import random
import math
import time
import datetime
import pickle
import sys
import os

#miscellaneous functions + procedures

def w
    time.sleep

def version_counter(filename="adventure_colussus_version_counter.dat"):
    with open(filename, "a+") as f:
        f.seek(0)
        val = int(f.read() or 0) + 1
        f.seek(0)
        f.truncate()
        f.write(str(val))
        return val
counter = version_counter()

def t(text):
    for char in text:
        sys.stdout.write(char)
        sys.stdout.flush()
        time.sleep(0.021)

def save_character(save_name, character):
    save_name_pickle = save_name + '.pickle'
    t('> saving character')
    w(1)
    with open(save_name_pickle, 'wb') as f:
        pickle.dump(character, f)
        t('> character saved successfully')

def load_character(load_name):
    load_name_pickle = load_name + '.pickle'
    t(' > loading character...')
    w(1)
    pickle_in = open(load_name_pickle,"rb")
    character = pickle.load(pickle_in)
    t(' > character loaded successfullyn')
    t('n> welcome back ')
    t(character['name'])
    t('!!!n')
    w(0.5)
    t('n> here are your stats from last time: n')
    print(' >',character)



def character_generator():
    t('n > we have reached the first crucial part of your journey: we must choose the path that you will take! the decisionn')
    w(0.5)
    t(' > is up to you my friend! Whether you choose to be a bloodthisty warrior or a cunning and strategic fighter,n')
    w(0.8)
    t(' > the choice is yours!n')
    w(0.5)
    t('n > now then, lets get right into it!')
    w(0.8)
    t(' are you more of a tanky player[1] or a strategic player[2]?')
    
    player_t_choice_1 = input('n > ')

    if player_t_choice_1 == '1':
        health = 100
        damage = 75

    elif player_t_choice_1 == '2':
        health = 75 
        damage = 50

    t('n > so, we have that out of the way, lets carry on!')
    w(0.8)
    t(' oh of course! sorry to forget! another quick question: ')
    w(0.5)
    t('do you like n')
    t(' > to use magic from great distances[1] or run in to the thick of battle weilding a deadly blade[2]? ')

    player_t_choice_2 = input('n > ')

    if player_t_choice_2 == '1':
        shield = 50
        magic = 75

    elif player_t_choice_2 == '2':
        shield = 75 
        magic = 45

    t('n > good good! we have decided your play style and your preffered ways of attacking the enemy!n')
    w(0.5)
    t(' > now, we must see what luck we are able to bestow upon you. be warned: it is entirely random!n')
    w(0.8)
    random_luck = input('n > press enter to roll a dice...')
    w(0.3)
    t(' > rolling dice...n')
    luck = random.randint(0,10)
    w(1)
    print(' > your hero has',luck,'luck out of 10!')
    w(0.8)
    t('n > we have reached the most important part of creating your character! The naming!n')
    t(' > choose wisely. your hero will be named this for the rest of their lives...n')
    w(1)

    t('n > what should your hero be named?n ')
    name = input('> ')
    w(1)
    t('n > welcome mighty hero! you shall be named: ')
    t(name)
    t(' !!!n')
    t(' > a fine choice')
    t('n')

    t(' n > now then. i guess you be on your way! you have a journey to start and a belly to fill!n')
    t(' > i have to say, i have rather enjoyed your company! feel free to come by at any time!n ')
    t('> goodbye and god speed!')
    w(1)
    print('n')
    t(' > your final stats are as follows: n')
    w(0.3)
    print(' >', '[', 'health:', health, ', damage:',  damage, ', shield:', shield, ', magic:', magic, ', luck:', luck, ', name:', name, ']')
    t('n > we should now save your character if you want to come back to it later:n ')

    character = {'health': health, 'damage': damage, 'shield': shield, 'magic': magic, 'luck': luck, 'name': name}
    character_file_name = input('> ')
    save_character(character_file_name, character)



# main game        

w(0.5)
e = datetime.datetime.now()
screen_line()
print('n  <Adventure Colussus>         version: v',counter,'| current date: ',e, '| date of creation: 9.2.2021')
screen_line()
w(0.5)
mountain_range()
screen_line()
print('n > [1] create new game')
print(' > [2] load existing game')
print(' > [3] end game')
print(' > [4] credits')
choice = input("n > ")

if choice == '1':

    t("n > you have chosen to create a new game: redirecting...")
    w(0.75)
    system('cls')
    screen_line()
    print('  n  we will begin with creating your character:                                        quick tip: choose wisely')
    screen_line()
    w(0.5)
    character_selection_horse_and_knight()
    screen_line()
    w(0.3)
    
    character_generator()




elif choice == '2':

    t("n > you have chosen to load an existing game: redirecting...")
    w(0.75)
    system('cls')
    w(0.5)
    screen_line()
    print('  n  we will begin with choosing an existing character:                             quick tip: make sure it exists!')
    screen_line()
    w(0.5)
    character_selection_horse_and_knight()
    screen_line()
    

    character_file_name = input('n > character file name: ')
    load_character(character_file_name)



elif choice == '3':

    t(' > ending session...')
    w(0.5)
    t(' > session ended successfully')
    w(1)
    sys.exit()

elif choice == '4':
    pass

else:
    t('incorrect response. please try again')
    

1 ответ
1

Именование

Я бы внес следующие изменения

w() -> remove
t() -> print_text()

С w() просто time.sleep, это не обязательно. И кто-нибудь, посмотрев на ваш код, поймет time.sleep много после того, как увидел w(0.08), и смотреть, где w определено.

print_text намного описательнее, чем просто t.

Строки документации

Добавление простого лечения внутри каждой функции может очень помочь, когда вам нужно быстрое напоминание о том, что делает функция. Например,

def version_counter() -> int:
    """
    Determines the version of the last played game, either in the {VERSION_FILENAME}
    file, or generating a new file if none is found.
    """

Типовые подсказки

Вы можете добавить подсказки типа для отображения того, какие типы параметров принимаются и какие типы возвращаются, если таковые имеются. Например,

from typing import Dict, Any
def save_character(save_name: str, character: Dict[str, Any]) -> None:
    """
    Saves the current character to a pickle database.
    """

Раньше, видя просто character, можно было бы предположить, что это просто строка, представляющая имя персонажа. Теперь он четко представлен как словарь со строковыми ключами и значениями, которые могут быть любого типа.

Самое важное различие здесь — убедиться, что кто-то, читающий ваш код, знает типы, принимаемые вашей функцией, и возвращаемые типы. Поскольку эта функция не «возвращает» значение, вы используете None.

Импорт

Тебе не нужно import os, потому что в вашей программе вы используете только system функцию, которую вы импортировали несколькими строками выше. Вам также не нужно math.

Меньше кода

Я заметил вас time.sleep почти после каждого вывода на консоль. Вместо этого я бы рекомендовал передать это значение в (теперь названный print_text функция) и сделайте там time.sleep. Например,

def print_text(text: str, sleep_time: float=0.0) -> None:
    """
    Prints the text to the console character by character. RPG style.
    """
    for char in text:
        sys.stdout.write(char)
        sys.stdout.flush()
        time.sleep(0.021)
    if sleep_time != 0.0:
        time.sleep(sleep_time)

Затем вы используете его как таковой:

print_text('> saving character', 1)

И если вы не хотите ждать после, так как sleep_time параметр по умолчанию, просто

print_text('> saving character')

Проверка ошибок

Я играю в вашу игру, дохожу до функции генератора персонажей и случайно нажимаю 3 за первый вопрос! Теперь ваш код молча терпит неудачу, мой health и damage не установлены, и я не знаю, что случилось позже. Я бы порекомендовал примерно следующее:

def get_input(string: str, valid_options: List[str]) -> str:
    while True:
        user_input = input(string)
        if user_input in valid_options:
            return user_input

Затем использовали так:

print('n > [1] create new game')
print(' > [2] load existing game')
print(' > [3] end game')
print(' > [4] credits')
choice = get_input("n > ", ['1', '2', '3', '4'])

Постоянный интервал

В некоторых местах вашего кода есть один пробел между if/else операторы, а в других местах — 3 или 4 пробела. Последовательность может помочь организовать ваш код (я бы рекомендовал придерживаться меньшего количества пробелов между операторами)

Обязательный f""

С помощью f-strings позволяет напрямую включать переменные в ваши строки. Например, строка ниже

print(' >', '[', 'health:', health, ', damage:',  damage, ', shield:', shield, ', magic:', magic, ', luck:', luck, ', name:', name, ']')

можно сжать до

print(f" > [ health: {health}, damage: {damage}, shield: {shield}, magic: {magic}, luck: {luck}, name: {name} ]")

  • Благодаря тонну! Похоже, вы приложили много усилий для своего ответа и указали на несколько моментов, которые я обязательно улучшу. Еще раз спасибо!

    — some_user_3

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *