我大约在3周前开始编写代码,只是为了好玩,以后可能会用于实际用途。我的GF敢于让我制作一个PGM,它将取代这个骰子游戏,在这个游戏中,您掷两个骰子,一个掷骰子,一个掷骰子,然后产生类似“亲吻,嘴唇”的东西。不知道YouTube和Stack Overflow之类的网站。如果能获得一些技巧和建设性的批评,我将不胜感激,这些技巧和建设性的批评是关于如何更高效,清晰,正确,甚至更多的“ pythonic”编码。 。据我测试,它工作正常。如您将看到的,有一个加载/保存功能旨在将游戏数据存储到文本文件中。

def enterplayers():
    # Set players for the game
    global player1
    player1 = input('Enter player 1 name: ')

    global player2
    player2 = input('Enter player 2 name: ')

    global playerlist
    playerlist = [player1, player2]

    global player
    player = cycle(playerlist)

def enteractions():
    # Add actions to existing (or empty) list
    print("Add ACTIONS and enter 'q' when done")
    while True:
        nextitem = input("Add: ")
        if nextitem == 'q':
            break
        elif nextitem == '':
            continue
        else:
            nextitem = nextitem.lower()
            if ' ' in nextitem:
                nextitem = nextitem.replace(' ', '_')
            actionlist.append(nextitem)

def enterbp():
    # Add body parts to existing (or empty) list
    print("Add BODY PARTS and enter 'q' when done")
    while True:
        nextitem = input("Add: ")

        if nextitem == 'q':
            break
        elif nextitem == '':
            continue
        else:
            nextitem = nextitem.lower()
            if ' ' in nextitem:
                nextitem = nextitem.replace(' ', '_')
            bplist.append(nextitem)

def loaddata():
    #empty them out in case something there
    global bplist
    bplist = []

    global actionlist
    actionlist = []

    #Load each one in its correct list and players in each variable
    while True:
        loadfile = input('Enter file name to LOAD (including ".txt"): ')
        print()
        if loadfile == 'q':
            return # It was told to me that using this is baaadddd baaaaddddd; is that true?
        try:
            with open(loadfile,'rt') as file:
                for line in file:
                    line = line.split()

                    if 'action:' in line:
                        line.remove('action:')
                        newitem = ''
                        newitem = newitem.join(line)
                        actionlist.append(newitem)

                    if 'bodypart:' in line:
                        line.remove('bodypart:')
                        newitem = ''
                        newitem = newitem.join(line)
                        bplist.append(newitem)

                    if 'player1:' in line:
                        line.remove('player1:')
                        newitem = ''
                        newitem = newitem.join(line)
                        global player1
                        player1 = newitem

                    if 'player2:' in line:
                        line.remove('player2:')
                        newitem = ''
                        newitem = newitem.join(line)
                        global player2
                        player2 = newitem
                break

        except FileNotFoundError:
            print("That didn't work out! Probably file does not exist or wrong file location.")
            print("Try again, or enter 'q' to return to main menu.")
            print()


    #Tell user what is loaded
    print('Loaded players:')
    print('-', player1)
    print('-', player2)
    print()

    print('Loaded actions:')
    for item in actionlist:
        print('-', item)
    print()

    print('Loaded body parts:')
    for item in bplist:
        print('-', item)
    print()

    print('Loading complete')
    print()


    # Set lists to cycle through (since enterplayers() was not used)
    global playerlist
    playerlist = [player1, player2]

    global player
    player = cycle(playerlist)

def savedata():
    print("Save including '.txt', any existing file will be overwritten!")
    print()
    while True:
        savename = input('SAVE to what file? ')
        if '.txt' in savename:
            break
        print("Don't forget .txt!")
        print()

    with open(savename, 'wt') as file:
        file.write('player1: ' + player1 + '\n')
        file.write('player2: ' + player2 + '\n')
        for item in actionlist:
            file.write('action: ' + item + '\n')
        for item in bplist:
            file.write('bodypart: ' + item + '\n')


    print()
    print('Successfully saved the following data to file', savename + ':')


    print('Player 1:', player1)
    print('Player 2:', player2)
    print()
    for item in actionlist:
        print('Action:', item)
    print()
    for item in bplist:
        print('Body part:', item)
    print()

def pickfirstplayer():
    # Check if user wants to pick randomly
    while True:
        print()
        randomplayer = input('Pick first player randomly? ')
        if randomplayer in ('no','yes'):
            break
        print('Please enter yes or no')
        print()

    # Pick randomly
    if randomplayer == 'yes':
        topickfrom = [player1,player2]
        nextplayer = random.choice(topickfrom)
        nextplayercheck = nextplayer
        print('The first player is ' + nextplayer + '!')

        # Here make sure that the firt playthrough is correct and not
        # player1 or player2 do something to himself
        nextplayer = next(player)
        if nextplayer != nextplayercheck:
            nextplayer = next(player)


    # Pick manually
    elif randomplayer == 'no':
        check = 0
        nextplayer = ''
        while check == 0:
            var = input('who is first player? ')
            if var not in playerlist:
                 print('That player is not playing!')
                 continue

            while var != nextplayer:
                nextplayer = next(player)
            check = 1
            print()

def menu():
    print()
    print('- - - - - - - - - - - -')
    print('   MAIN MENU')
    print()
    print('1. Start game')
    print()
    print('2. Enter player names')
    print('3. Add actions')
    print('4. Add body parts')
    print()
    print('6. Load data')
    print('7. Save data')
    print()
    print('8. Print instructions')
    print('9. Quit ')
    print('- - - - - - - - - - - -')
    print()

def instructions():
    print('Before starting the game you must set the following:')
    print('\t\t- Names of the players')
    print('\t\t- Actions (touch, kiss, etc.)')
    print('\t\t- Body parts')
    print()
    print('You can also just load a file with game data.')
    print()
    print('You do not need to capitalize, this is done automatically.')
    print()
    print('When this is done you can play the game!')
    print()
    print('Notice that when you use the load function,')
    print('  all previously loaded data will be removed.')
    print()



actionlist = []
bplist = []



import random
import time
import sys
from itertools import cycle



## 'actual code' starts here
while True:
    menu()
    try:
        menuchoice = int(input('Enter choice: '))

    except ValueError:
        print('Please enter a number!')
        continue


    print()

    if menuchoice == 1:

        print('- - - - - - - -')
        print('STARTING GAME!')

        pickfirstplayer()

        while True:
            # Set action and place randomly
            nextaction = random.choice(actionlist)
            nextplace = random.choice(bplist)

            # Print it
            print('Okay', nextplayer + ',')
            time.sleep(1)
            nextplayer = next(player)
            print()

            print(nextaction + ' ', end="", flush=True)
            time.sleep(1)
            print(nextplayer+"'s ", end="", flush=True)
            time.sleep(2)
            print(nextplace + '!')
            time.sleep(5)

            print()
            print()

            anotherone = input('Press enter for another, type anything to quit ')

            if anotherone == '':
                print()
                continue
            else:
                print('Returning to main menu')
                print()
                break

    elif menuchoice == 2:
        enterplayers()

    elif menuchoice == 3:
        enteractions()

    elif menuchoice == 4:
        enterbp()

    elif menuchoice == 6:
        loaddata()

    elif menuchoice == 7:
        savedata()

    elif menuchoice == 8:
        instructions()

    elif menuchoice == 9:
        quit()

    else:
        print('Please enter a valid number!')
        print()


评论

后续问题

#1 楼

首先,欢迎使用编程和Python。都很棒!

好吧,这是您第一次尝试编码,而不是对代码进行特定的改进,我将给出一些高级建议,然后让您随便使用它们。

样式

Python有一个称为PEP8的官方样式指南,该指南定义了样式代码的首选方法。它涉及变量命名约定,适当的空格,代码流等。我强烈建议您看一看,并尝试使您的代码适合其内容。



该程序说明基本上是为面向对象编程(OOP)构建的。在Python中创建类非常容易,并且提供了访问相似数据的简单方法。下面是一个基本的Die类,可以用来表示游戏中的骰子之一: br />
class Die():
    def __init__(self, options=[]):
        # This is the function that is called when a new `Die` instance
        # is created. The `options` parameter is optional (denoted with the `=`).
        self.options = options 

    def __str__(self):
        # This 'magic method' is called when you used the `print` function.
        return ', '.join(self.options)

    def add_options(self, options):
        # Adds multiple options. HINT: use the following method.

    def add_option(self, option):
        # Add an option to the current list

    def roll(self):
        # Return one of its options based on a random number


您的许多代码都可以放入类中(如上述DieDieGame等)。通过使用Player关键字的数量可以明显看出这一点。必须在许多地方使用变量意味着该变量与其使用的函数之间存在关系。这种关系是OOP背后的主要思想之一。

字符串

您执行许多打印语句。那样就好。但是,如果使用三引号语法,则可以删除其中的95%。本质上,通过使用global,Python可以保持字符串在代码中的外观。因此,您的'''Some text'''函数可以按以下比例缩放:

 >>>body_parts = Die(['arm', 'leg', 'nose'])
 >>>body_parts.add_options(['head', 'foot'])
 >>>body_parts.roll()
 'leg'
 >>>print(body_parts)
 arm, leg, nose, head, foot


如此:

def menu():
    print()
    print('- - - - - - - - - - - -')
    print('   MAIN MENU')
    print()
    print('1. Start game')
    print()
    print('2. Enter player names')
    print('3. Add actions')
    print('4. Add body parts')
    print()
    print('6. Load data')
    print('7. Save data')
    print()
    print('8. Print instructions')
    print('9. Quit ')
    print('- - - - - - - - - - - -')
    print()


此外,您有一些使用这样的字符串的语句:

def menu():
    print('''
- - - - - - - - - - - -
   MAIN MENU
1. Start game

2. Enter player names
3. Add actions
4. Add body parts

5. Load data
6. Save data

7. Print instructions
8. Quit
- - - - - - - - - - - -
''')


一种简单的编写方法是使用Python提供的menu函数:

file.write('player1: ' + player1 + '\n')


这样,我们不必担心旧语句中发生的所有字符串连接。

其他想法

这里有一些随机的改进,我可以看到:



format()

在替换之前,无需检查字符串中的子字符串。如果没有,则replace()会优雅地处理它:

file.write('player1: {}\n'.format(player1))



'无限'循环

虽然我喜欢replace()循环在适当的情况下,您不需要大多数(如果不是全部)。带您进入while True的while循环:

>>>'Hello Planet!'.replace('Planet', 'World')
Hello World!
>>>'Hello World!'.replace('Planet', 'World')
Hello World!


可以简化为:

def enterbp():
    # Add body parts to existing (or empty) list
    print("Add BODY PARTS and enter 'q' when done")
    while True:
        nextitem = input("Add: ")

        if nextitem == 'q':
            break
        elif nextitem == '':
            continue
        else:
            nextitem = nextitem.lower()
            if ' ' in nextitem:
                nextitem = nextitem.replace(' ', '_')
            bplist.append(nextitem)



使用enterbp s

list s很棒。您可以简单地使用list来实现菜单:

def enterbp():
    # Add body parts to existing (or empty) list
    print("Add BODY PARTS and enter 'q' when done")

    nextitem = input("Add: ")
    while nextitem != 'q':
        if nextitem == '':
            continue

        bplist.append(nextitem.lower().replace(' ', '_'))  

        nextitem = input("Add: ")



还有其他一些东西,但是我认为这是一个喘口气的好地方我已经向您介绍了一些信息。 :D

评论


\ $ \ begingroup \ $
好答案!我现在正在重新编写代码。将print('Player 1:',player1)替换为print('Player 1:{0}'。format(player1))还是更好?还是您认为它没用(因为现在的代码更长了)?感谢您抽出宝贵的时间!
\ $ \ endgroup \ $
– LuukV
2014年5月21日14:56



\ $ \ begingroup \ $
就我个人而言,我仍然会使用format函数,因为它只是Pythonic。至于性能,我发现说连接更快的资源和说字符串替换更快的资源。
\ $ \ endgroup \ $
–BeetDemGuise
2014年5月21日在15:27

\ $ \ begingroup \ $
谢谢,我仍在弄清楚类(__init__等),但我将使用现有教程进行管理。到目前为止,这无疑已经大大改善了我的代码。
\ $ \ endgroup \ $
– LuukV
2014年5月21日在20:10

\ $ \ begingroup \ $
是的,在一等语法和思维上可能有点奇怪。如果您还有其他问题,请继续提问。
\ $ \ endgroup \ $
–BeetDemGuise
2014年5月22日晚上11:53

\ $ \ begingroup \ $
您能否阐明一下:我试过按照您说的将菜单放在列表中。但是现在对我而言,这意味着我将需要将几乎所有主要块放入一个名为play()的函数中。然后,我几乎没有全局变量,除非我开始着迷于全局,否则其他函数将无法使用它们。但是我知道那不是我应该做的。因此,现在我只能使用所有这些只能在该功能中使用的变量。还是我看错东西了?
\ $ \ endgroup \ $
– LuukV
2014年5月23日,0:42

#2 楼

许多事情需要改进,我会随着时间的推移编辑此答案。

print()和字符串。

您正在冗余使用print。考虑使用menu功能。您可以对""" """''' '''使用阻止文本。

menu函数可能只是一个打印语句。或像这样将其存储为全局变量

MAIN_MENU ='''
--------------------------
       MAIN MENU
    1. Start game

    2. Enter player names
    3. Add actions
    4. Add body parts

    6. Load data
    7. Save data

    8. Print instructions
    9. Quit 
----------------------------
'''


并简单地打印菜单

print(MAIN_MENU)


您还使用print()print()打印新行。只需使用print('\n\n') '\n'是几乎每种编程语言中常见的换行符。

使用Main Block

您可以像这样启动程序

## 'actual code' starts here
while True:


将您的主块放在这样的主块中

if __name__ == '__main__':
    while True:


global

global关键字是一个python中那些闻起来的东西。尽可能避免它。在您的主要代码块中,不清楚“ enterplayers”的功能,因为它不带参数也不返回任何值。然而,它以某种方式修改了您的局部变量。它应该返回输入的玩家。

实际上,在主块中的任何地方都没有声明players,这更加神秘。一个人应该只需要看一下那个块就可以知道players的定义。

重新实现switch


在您的主要块中,您实质上实现了一个菜单的C型switch块。在python中这也特别难闻。 br />请注意,在menu_actions中,我们自己存储函数而不调用它们。这是python我最喜欢的功能之一:使用不带menuchoice的函数名称,就可以得到函数的委托或指针。这是因为所有函数都是python中的对象。这是一个示例

,因为所有这些函数均不返回任何参数且不带参数,因此可以很好地与您的代码一起使用。如果您遵循我对()的建议,您将需要以不同的方式实现此建议,因为我建议enterplayers应该返回一些信息。

实施我的两个建议都会有些棘手。我不会声称要知道最好的方法,如果它变得太复杂,则简单的切换或全局调用可能是更好的方法。

传递参数

以上两个衬板之所以起作用,是因为您所有的功能都使用完全相同的参数enterplayers。如果他们使用完全相同的非void参数,第二行将是这样。

def enterplayers():
    player1 = input('Enter player 1 name: ')
    player2 = input('Enter player 2 name: ')
    return cycle([player1, player2])

...
if menuchoice == 2:
    players = enterplayers()


这种情况并非如此,每个函数都需要唯一的参数。 br />您可以使用functools.partial实现它们。将menu_actions用作部分函数的字典,

menu_actions = {1: play_game, 2: enterplayers, 3: enteractions, ... }
menu_actions[menuchoice]()


如果传递的参数的值在None的定义和部分函数的调用之间改变,则此方法将无效功能。每次更改某些参数时,您都需要重新声明menu_actions。这使它成为一个混乱的解决方案。

评论


\ $ \ begingroup \ $
感谢您的帮助,我会尽力跟上您在单独文件中提到的所有内容,并在完成后重新提交新帖子。
\ $ \ endgroup \ $
– LuukV
2014年5月21日在14:13

\ $ \ begingroup \ $
在最后一部分(菜单字典)上,如果我的函数需要参数怎么办?从中我了解到,我不添加(),这意味着没有空间添加该函数所需的参数。还是我可以根据需要添加它们?
\ $ \ endgroup \ $
– LuukV
2014年5月21日在20:14

\ $ \ begingroup \ $
仅供参考,请您关注全局变量。我尝试过players = cycle(player1,player2),但是由于cycle()仅采用一个参数,因此给出了错误。我将其更改为一个列表,例如,players = cycle([player1,player2])可以正常工作。再次感谢您的帮助。
\ $ \ endgroup \ $
– LuukV
2014年5月22日21:39

\ $ \ begingroup \ $
编辑。循环需要迭代。
\ $ \ endgroup \ $
–cheezsteak
2014年5月23日13:21