Не уверен насчет смены доски tic_tac_toe - PullRequest
0 голосов
/ 12 января 2019

Я программирую игру Tic-Tac-Toe на Python 3. Я сделал доски в виде 2D-массивов, и у меня есть функции для печати доски в виде сетки, учебника, а также для ввода и ввода данных.

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

  1. Обнаружение того, произошел ли выигрыш. (После этого он должен спросить игроков, хотят ли они играть снова и действовать соответственно.) 2. (Необязательно, но приветствуется). Как создать процессор для игры с одним игроком.

У меня есть грубая концепция использования цикла «for» для переключения хода и механики выигрыша в игре, но игра может прерваться в случае ничьей, если это не будет реализовано.

Если у кого-то есть решение следующих проблем или общие предложения, пожалуйста, разместите их здесь.

    from array import *
    class board:
        def __init__(self, row_1, row_2, row_3):
            self.row_1 = row_1
            self.row_2 = row_2
            self.row_3 = row_3
            # full_board is two-dimensional array
            self.full_board = row_1, row_2, row_3
    dash = "-"
    main_board = board([dash, dash, dash], [dash, dash, dash], [dash, dash, 
    dash,])
    def board_print(board):
        for row in board:
            for item in row:
                print(item, end = " ")
            print()

    def take_input():
        player = input("What space would you like to mark?(From 1 through 9):")
        input_process(player)

# Algorithm for player input
# Make a dictionary of player inputs as keys, and 2d array coordinates as values
# if player's input equals a dictionary value:
#   take the string and split it at ":"
#   assign the two numbers of the 2d dictionary value as part_1 and part_2
#   change the value of the matching coordinate to a "X" or "O", on the player(sorry, I can't make good CPU.)
# else:
#   print a notification that their input was invalid and recall the function
def input_process(pl_choice):
    possible_inputs = {"1" : "0:0", "2" : "0:1", "3" : "0:2", "4" : "1:0", "5" : "1:1", "6" : "1:2", "7": "2:0", "8" : "2:1", "9" : "2:2"}
    if pl_choice in possible_inputs:
        confirm = input("Are you sure you want to select %s? y/n: "%pl_choice)
        if confirm == "y":
            choice = possible_inputs[pl_choice].split(":")
            answer_p1 = choice[0]
            answer_p2 = choice[1]
            choice_parts = [answer_p1, answer_p2]
        elif confirm == "n":
            print("Oh. Well you can try again.\n")
            take_input()
    elif pl_choice not in possible_inputs or not pl_choice.isdigit():
        print("Your choice was invalid. Please try again.")
        take_input()

def change_board(play_board, player_id, input_p1, input_p2):
        if player_id == 1:
            play_board[input_p1][input_p2] = "X"
        elif player_id == 2:
            play_board[input_p1][input_p2] = "O" 

def tutorial():
        print("Welcome to the Tic-Tac-Toe tutorial.\n")
        print("This version of Tic-Tac-Toe is two-player only, although CPU may be added in the future. To play, \nYou input a number, 1-9. The numbers bind like so: ")
        tutorial_board = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
        print(board_print(tutorial_board))
        print("Otherwise, this plays like on paper; get 3 in a row vertically, horizontally, or diagonally before your opponent, and you win.")
        # Placeholder for main game

    def main_game():
        print("Hello, and welcome to Tic-Tac-Toe.\nWould you like to see the tutorial? y/n:")
        tutorial_needed = input
        if tutorial_needed == "y":
            tutorial()
        elif tutorial_needed == "n":
            print("Okay. Let's start!")
            game_end = False
            actual_board = main_board.full_board
            board_print(actual_board)
            take_input()

1 Ответ

0 голосов
/ 12 января 2019

1. Обнаружение того, произошел ли выигрыш.

Мы определяем «выигрыш» для игрока X как случай, когда одно из следующего является Истиной:

  • Один ряд состоит из X
  • Один столбец состоит из X
  • диагональ от верхнего левого до нижнего правого состоит из X
  • диагональ от нижнего левого до верхнего правого состоит из X

Как мы можем перевести это на Python?

Строка - это просто подсписок в вашем кортеже (это типы, которые вы использовали), поэтому мы можем просто написать board[row], чтобы получить строку. Чтобы проверить, если any (обратите внимание на формат кода) * строка 1022 * состоит из «X», мы должны проверить, что all его значение равно «X». Итак, мы можем написать any(all(field == 'X' for field in row) for row in board).

Столбцы сложнее, потому что мы должны работать с индексами. Но, по сути, это то же самое, только наоборот: any столбец с all полями "X": any(all(board[row][column] == 'X' for row in range(3)) for column in range(3))

Диагонали: у нас только одна строка, поэтому нам нужен только один цикл.
Для TL-> BR оба индекса равны. Итак, мы хотим, чтобы all полей с равными индексами были равны «X». all(board[i][i] == 'X' for i in range(3))
для BL-> TR один индекс равен 2-other_index (, а не 3, поскольку последовательности индексируются нулем). Мы хотим, чтобы all поля с двумя индексами были равны "X" all(board[i][2-i] for i in range(3)) Вопрос: что произойдет, если вы инвертируете i и 2-i? Если вы не знаете, пусть это будет распечатано.

Возможно, вы захотите написать check_win(board, player) функцию, которая сделает все вышеперечисленное для общего player - здесь «X» или «O», но, если вы решите включить трех игроков на большую доску позже на ...

2. Создание CPU AI:

Если вы действительно хотите создать CPU , это неправильное место для запроса. Если вы хотите создать (простой) AI , читайте дальше. Если вы хотите, чтобы это было сложно, задайте новый вопрос.

Подумайте, что он должен делать:

  • он должен предпочитать некоторые поля из-за их положения?
  • Должен ли он попытаться быстро заблокировать противника?
  • Должен ли он попытаться создать несколько возможностей выигрыша или сосредоточиться на одной?
  • если это ...?

Хотя в этом случае, вероятно, проще будет просто смоделировать несколько ходов и выбрать те, которые имеют наилучшие возможности для выигрыша, задать себе вопросы выше и написать что-то, что также будет работать с (намного) большими досками, будет интересно.

3. Переключатель поворотов.

Одна возможность:

У вас есть последовательность (str, list или tuple) игроков, например: "XO" и переменная round_counter, которая всегда увеличивается. Затем вы используете PLAYERS[round_counter % len(PLAYERS)], чтобы получить текущего игрока. Используйте оператор модуля %, чтобы всегда получать действительный индекс.

Альтернатива:

Использование itertools.cycle:

цикл ('ABCD') -> A B C D A B C D A B C D ...

Это проще (for current_player in itertools.cycle("XO"):), но с первой альтернативой у вас есть номер, по которому вам нужно будет позвонить enumerate(itertools.cycle("XO")), и вы ограничите использование библиотеки (если этот код кому-то показывается, вы можете хочу объяснить как это работает).

4. Как обнаружить ничью:

Ничья происходит, когда all поля not пусты (в вашем случае, != тире); это равносильно тому, что есть поле not any с тире. См. Понимание списка , чтобы выровнять доску:

>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

- второй-последний пример

...