Начинающий: код в крестики-нолики Python 3.9.6 и вопросы по оптимизации

Я только начинаю изучать Python и думал, что поставлю перед собой задачу, используя уроки, которые я усвоил до сих пор. Я слежу за курсом Udemy «Автоматизация скучных вещей с помощью Python». То, что я до сих пор достиг, касалось основ функций, обработки ошибок, списков и словарей.

Я хотел посмотреть, понял ли я, что я узнал, создав игру в крестики-нолики с учетом определенных функций / задач / целей:

  • использовать циклы, функции, методы, списки / словари.
  • игроку нужно будет увидеть доску и то, какие места были заняты / оставлены
  • Я хотел, чтобы игроки могли выбирать в верхнем / нижнем / смешанном регистре.
  • игра должна была учитывать все условия победы, условия проигрыша и патовые ситуации.
  • оппоненту (в данном случае ЦП) нужно будет иметь доступ только к оставшимся вариантам. На данный момент это будет случайным образом, но, возможно, я вернусь к коду, чтобы иметь какую-то форму ИИ.
  • Когда игра закончится, дайте игроку возможность начать новую игру и следить за счетом.

Это мой код, и, насколько я могу судить, он работает, и мне удалось достичь всех целей, которые я поставил перед собой:


import copy
import time
import random
import sys

##Board design to make it look pretty
def printBoard(board):
    print('')
    print(board['top-l'] + '|' + board['top-m'] + '|' + board['top-r'])
    print('-----')
    print(board['mid-l'] + '|' + board['mid-m'] + '|' + board['mid-r'])
    print('-----')
    print(board['low-l'] + '|' + board['low-m'] + '|' + board['low-r'])
    print('')

##Function for initiating the board back to blank
def blankBoard(zeroBoard):
    for value in zeroBoard:
        zeroBoard[value] = ' '

##Function for initiating a New Game after a game over situation
def newGame(YorN):
    print('n ~ Would you like to play again? if yes, type ''Y'': ~ ')
    newGame = input()
    if newGame.upper() == 'Y':
        print(' ~ okay, please wait while we set up a new game! ~ ')
        blankBoard(theBoard)
        time.sleep(random.randint(1,2))
        printBoard(theBoard)
    else:
        print('n ~ Bye and thank you for playing!! ~ ')
        sys.exit()        

##Function containing all the win conditions
def winCondition(winner):
    if ((winner['top-l'] == winner['top-m'] == winner['top-r'] == 'X') or
    (winner['mid-l'] == winner['mid-m'] == winner['mid-r'] == 'X') or
    (winner['low-l'] == winner['low-m'] == winner['low-r'] == 'X') or
    (winner['top-l'] == winner['mid-l'] == winner['low-l'] == 'X') or
    (winner['top-m'] == winner['mid-m'] == winner['low-m'] == 'X') or
    (winner['top-r'] == winner['mid-r'] == winner['low-r'] == 'X') or
    (winner['top-l'] == winner['mid-m'] == winner['low-r'] == 'X') or
    (winner['top-r'] == winner['mid-m'] == winner['low-l'] == 'X')):
        print('n ~ Congratulations! You are a winner!  ')
        return 'win'


##Function containing all the loss conditions
def loseCondition(loser):
    if ((loser['top-l'] == loser['top-m'] == loser['top-r'] == 'O') or
    (loser['mid-l'] == loser['mid-m'] == loser['mid-r'] == 'O') or
    (loser['low-l'] == loser['low-m'] == loser['low-r'] == 'O') or
    (loser['top-l'] == loser['mid-l'] == loser['low-l'] == 'O') or
    (loser['top-m'] == loser['mid-m'] == loser['low-m'] == 'O') or
    (loser['top-r'] == loser['mid-r'] == loser['low-r'] == 'O') or
    (loser['top-l'] == loser['mid-m'] == loser['low-r'] == 'O') or
    (loser['top-r'] == loser['mid-m'] == loser['low-l'] == 'O')):
        print('n ~ Aww man, you''re are a loser! ~ ')
        return 'lose'
 

##Function for Computer Players Choice
def computerChoice(cpuChoice):
    theBoardCPU = copy.deepcopy(theBoardChoices)
    print(','.join(theBoardCPU.keys()))
    cpuChoice = random.choice(list(theBoardCPU.keys()))
    print(' ~ ' + cpuChoice + ' ~ ')
    del theBoardChoices[cpuChoice]
    theBoard[cpuChoice] = 'O'
    printBoard(theBoard)



##Blank board to begin with and making a copy of the board for choices remaining, and finally printing a pretty board
theBoard = {'top-l': ' ', 'top-m': ' ', 'top-r': ' ',
        'mid-l': ' ', 'mid-m': ' ', 'mid-r': ' ',
        'low-l': ' ', 'low-m': ' ', 'low-r': ' '}
theBoardChoices = copy.deepcopy(theBoard)
printBoard(theBoard)

##The actual game
print(' ~ Hello player. What is your name? ~ ')
player1Name = input()
print(' ~ Hello ' + player1Name + ', welcome to tic-tac-toe ~ ')
playerScore = 0
CPUScore = 0

while theBoardChoices != None:
    print(' ~ ' +player1Name + ', please type in one of the options for blank spaces: ~ ')
    print('')
    print(' , '.join(theBoardChoices.keys()))
    playerInput = input()
    playerChoice = playerInput.lower()
    choiceCheck = theBoard.get(playerChoice,'bad choice')
    
    if choiceCheck != 'bad choice':
        
        if theBoard[playerChoice] == ' ':
            theBoard[playerChoice] = 'X'
            printBoard(theBoard)
            del theBoardChoices[playerChoice]
            if winCondition(theBoard) == 'win':
                theBoardChoices = copy.deepcopy(theBoard)
                playerScore = playerScore + 1
                print('  ~  the current score is ' + str(playerScore) +'-' + str(CPUScore) + '  ~  ')
                newGame(theBoardChoices)
                continue
            if theBoardChoices == {}:
                theBoardChoices = copy.deepcopy(theBoard)
                newGame(theBoardChoices)
                continue               
            print(' ~ Please wait. Computer making a choice... ~ ')
            time.sleep(random.randint(1,2))
            computerChoice(theBoard)
            if loseCondition(theBoard) == 'lose':
                theBoardChoices = copy.deepcopy(theBoard)
                CPUScore = CPUScore + 1
                print('  ~  the current score is ' + str(playerScore) +'-' + str(CPUScore) + '  ~  ')
                newGame(theBoardChoices)
                continue             
            
        else:
            print(' ~ that space is already taken ~ ')

Мои вопросы по этому коду следующие:

  1. Мои функции условий выигрыша и проигрыша кажутся очень громоздкими, но я не мог придумать другого способа уменьшить их или, желательно, превратить их в одну функцию. Я подумал, что, может быть, я смогу сделать что-то вроде «если эти три ключа = x», а затем «x = O, то проиграют» или «x = X, то проиграют». Но я думаю, что мое понимание функций все еще немного туманно. Есть ли способ создать функцию, которая будет генерировать этот список условий выигрыша / проигрыша, используя мою настройку? Или мне пришлось бы сделать доску списком, а не словарем, чтобы использовать более математический подход, чтобы уменьшить это?

  2. У меня куча вложенных ifв моем разогнанном заявлении. Я чувствую, что мог бы больше использовать функции, чтобы уменьшить это, но даже в этом случае мне интересно, есть ли проблемы с этим.

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

  4. В общем, я знаю, что от старых привычек трудно избавиться, и то же самое можно сказать и о вредных привычках. Я очень хотел бы знать, есть ли в моем коде признаки плохих вещей, которых я могу опасаться, чтобы пресечь их в зародыше, прежде чем продолжить. Я планирую вернуться к этому коду в будущем и добавить к нему (вариант с двумя игроками-людьми или против ЦП или с двумя лицами ЦП друг с другом, какой-то своего рода ИИ, возможность разрешить игрокам устанавливать размер доски и т. Д.).

В любом случае, я с нетерпением жду отзывов!

1 ответ
1

Как … МЕЖДУНАРОДНАЯ … Думаю, я может дать несколько рекомендаций / советов по этому поводу.

  1. При создании чего-либо не думайте о том, какие структуры данных или синтаксические функции вы собираетесь использовать. Вы можете выполнить поиск, например, «упражнения по словарю / циклам Python», чтобы попрактиковаться в этих основах, но при создании приложения разделите основную цель на шаги и, следовательно, закодируйте их.

Позже вы определенно получите эти основы, потому что вы будете реализовывать их почти в каждом проекте, который вы делаете.

Что касается кода, попробуйте разделить функции, которые связаны с одним и тем же, в разных файлах .py, например модули (если они вам нравятся), а затем используйте импортИспользуйте это не только для того, чтобы не создавать беспорядка, но и для легкого поиска ошибки или ошибки. Это сделает ваш код чище и удобнее для чтения.

СКОРО РЕДАКТИРУЕТСЯ:

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

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