Как написать игру крестики нолики на питоне

Если вы учитесь программировать, то программирование игр — это очень хороший способ освоить алгоритмы и структуры данных. В этом уроке мы разберем запрограммируем игру крестики нолики на Python. Полный код программы с искусственным интеллектом для игрока-компьютера занимает всего 140 строк. В варианте игры где человек играет против человека — раза в два меньше.

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

Шаг 1. Подбор структуры данных

Программирование любой игры начинается с моделирования ее объектов средствами языка программирования. Когда мы программируем игру крестики нолики нам нужно подумать где в программе хранить поле для игры с ходами которые сделали игроки.

В языке программирования Python наилучшим выбором будет список из 9 значений. Назовем его maps. Первоначально этот список будет заполнен цифрами от 1 до 9. Это сделано для удобства организации диалога с пользователем. Пользователю будет достаточно ввести символ от 1 до 9, что бы мы смогли понять куда он сделал ход. После того как ход сделан, цифру мы заменим на символ нолика или крестика. (Можно было заполнить цифрами от 0 до 8. В этом случает было бы удобнее работать — цифра и есть индекс элемента в списке, но первый нолик будет смущать игроков).

Еще мы создадим второй список victories в котором будем хранить информацию обо всех выигрышных комбинациях. И нам будет нужно создать функцию print_maps, которая будет выводить содержимое нашего списка maps на экран.

# Инициализация карты
maps = [1,2,3,
        4,5,6,
        7,8,9]

# Инициализация победных линий
victories = [[0,1,2],
             [3,4,5],
             [6,7,8],
             [0,3,6],
             [1,4,7],
             [2,5,8],
             [0,4,8],
             [2,4,6]]

# Вывод карты на экран
def print_maps():
    print(maps[0], end = " ")
    print(maps[1], end = " ")
    print(maps[2])

    print(maps[3], end = " ")
    print(maps[4], end = " ")
    print(maps[5])

    print(maps[6], end = " ")
    print(maps[7], end = " ")
    print(maps[8]) 

Со структурами данных разобрались.

Шаг 2. Выполнение очередного хода и проверка на выигрыш

Карта для игры у нас есть, отображать ее мы умеем. Теперь нужно создать две вспомогательные функции, прежде чем мы приступим к программированию основного цикла игры.

Первая функция будет рисовать на поле крестик или нолик, в зависимости от того что в нее передали. Позицию в нее так же нужно будет передавать. Вставлять переданный элемент мы будем по индексу. Индекс определим функцией index (если бы мы пронумеровали от 0 до 8 элементы в maps, то переданное значение и было бы индексом. Можете попробовать — будет на одну строчку кода меньше.)

# Сделать ход в ячейку
def step_maps(step,symbol):
    ind = maps.index(step)
    maps[ind] = symbol

После каждого ходы мы должны проверять — не победил ли кто то из игроков. Для этого переберем все победные линии из списка victories и проверим нет ли там комбинации из трех крестиков или трех ноликов.

# Получить текущий результат игры
def get_result():
    win = ""

    for i in victories:
        if maps[i[0]] == "X" and maps[i[1]] == "X" and maps[i[2]] == "X":
            win = "X"
        if maps[i[0]] == "O" and maps[i[1]] == "O" and maps[i[2]] == "O":
            win = "O"    
            
    return win

Эта функция вернет «X» в случае победы крестиков и «O» в случае победы ноликов.

Шаг 3. Основный игровой цикл

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

# Основная программа
game_over = False
player1 = True

while game_over == False:

    # 1. Показываем карту
    print_maps()

    # 2. Спросим у играющего куда делать ход
    if player1 == True:
        symbol = "X"
        step = int(input("Человек 1, ваш ход: "))
    else:
        symbol = "O"
        step = int(input("Человек 2, ваш ход: "))

    step_maps(step,symbol) # делаем ход в указанную ячейку
    win = get_result() # определим победителя
    if win != "":
        game_over = True
    else:
        game_over = False

    player1 = not(player1)        

# Игра окончена. Покажем карту. Объявим победителя.        
print_maps()
print("Победил", win) 

Вот полный код программы крестики-нолики на Python для двух игроков:


# Инициализация карты
maps = [1,2,3,
        4,5,6,
        7,8,9]

# Инициализация победных линий
victories = [[0,1,2],
             [3,4,5],
             [6,7,8],
             [0,3,6],
             [1,4,7],
             [2,5,8],
             [0,4,8],
             [2,4,6]]

# Вывод карты на экран
def print_maps():
    print(maps[0], end = " ")
    print(maps[1], end = " ")
    print(maps[2])

    print(maps[3], end = " ")
    print(maps[4], end = " ")
    print(maps[5])

    print(maps[6], end = " ")
    print(maps[7], end = " ")
    print(maps[8])    

# Сделать ход в ячейку
def step_maps(step,symbol):
    ind = maps.index(step)
    maps[ind] = symbol

# Получить текущий результат игры
def get_result():
    win = ""

    for i in victories:
        if maps[i[0]] == "X" and maps[i[1]] == "X" and maps[i[2]] == "X":
            win = "X"
        if maps[i[0]] == "O" and maps[i[1]] == "O" and maps[i[2]] == "O":
            win = "O"    
            
    return win

# Основная программа
game_over = False
player1 = True

while game_over == False:

    # 1. Показываем карту
    print_maps()

    # 2. Спросим у играющего куда делать ход
    if player1 == True:
        symbol = "X"
        step = int(input("Человек 1, ваш ход: "))
    else:
        symbol = "O"
        step = int(input("Человек 2, ваш ход: "))

    step_maps(step,symbol) # делаем ход в указанную ячейку
    win = get_result() # определим победителя
    if win != "":
        game_over = True
    else:
        game_over = False

    player1 = not(player1)        

# Игра окончена. Покажем карту. Объявим победителя.        
print_maps()
print("Победил", win)

Вот так выглядит процесс игры в крестики-нолики для 2 игроков:

1 2 3
4 5 6
7 8 9
Человек 1, ваш ход: 5
1 2 3
4 X 6
7 8 9
Человек 2, ваш ход: 1
O 2 3
4 X 6
7 8 9
Человек 1, ваш ход: 6
O 2 3
4 X X
7 8 9
Человек 2, ваш ход: 4
O 2 3
O X X
7 8 9
Человек 1, ваш ход: 3
O 2 X
O X X
7 8 9
Человек 2, ваш ход: 7
O 2 X
O X X
O 8 9
Победил O

Шаг 4. Добавление алгоритма для искусственного интеллекта в игре крестики-нолики

А вот теперь мы подобрались к самому интересному моменту в программировании. Нам нужно создать искусственный интеллект, который всегда будет выигрывать или сводить игру к ничьей. На самом деле в игре крестики-нолики такой алгоритм написать совсем не сложно.

Для написания такого алгоритма нам понадобится вспомогательная функция, которая будет проверять все победные линии в игре и подсчитывать в них количество крестиков и ноликов. Если функция находит такую линию, то она возвращает позицию на этой линии куда нужно сделать ход. Например мы будем отслеживать линии где противник поставил два крестика и обязательно поставим нолик, что бы не дать ему выиграть. Вот эта функция:

#Искусственный интеллект: поиск линии с нужным количеством X и O на победных линиях
def check_line(sum_O,sum_X):

    step = ""
    for line in victories:
        o = 0
        x = 0

        for j in range(0,3):
            if maps[line[j]] == "O":
                o = o + 1
            if maps[line[j]] == "X":
                x = x + 1

        if o == sum_O and x == sum_X:
            for j in range(0,3):
                if maps[line[j]] != "O" and maps[line[j]] != "X":
                    step = maps[line[j]]
                
    return step

А сейчас мы напишем функцию для поиска очередного лучшего хода для искусственного интеллекта. Запрограммируем такой алгоритм для каждого хода (компьютер играет ноликами):

  1. Если этим ходом можем выиграть — выигрываем (уже 2 нолика стоят на одной из линий). Иначе идем к шагу 2.
  2. Если можем помешать выиграть человеку — мешаем ( у человека уже 2 крестика на линии — ставим на нее нолик). Иначе идем к шагу 3.
  3. Если на линии одна наша фигура — ставим вторую. Если пока ни одной нашей фигуры — идем к шагу 4.
  4. Ставим нолик в центр. Если центр занят идем к шагу 5.
  5. Ставим в левый верхний угол.

А вот так все это выглядит в программе на Python:

#Искусственный интеллект: выбор хода
def AI():        

    step = ""

    # 1) если на какой либо из победных линий 2 свои фигуры и 0 чужих - ставим
    step = check_line(2,0)


    # 2) если на какой либо из победных линий 2 чужие фигуры и 0 своих - ставим
    if step == "":
        step = check_line(0,2)
        

    # 3) если 1 фигура своя и 0 чужих - ставим
    if step == "":
        step = check_line(1,0)
           

    # 4) центр пуст, то занимаем центр
    if step == "":
        if maps[4] != "X" and maps[4] != "O":
            step = 5
            

    # 5) если центр занят, то занимаем первую ячейку
    if step == "":
        if maps[0] != "X" and maps[0] != "O":
            step = 1            
  
    return step

Немного перепишем и основной цикл игры. Теперь вместо человека 2 ход будет делать компьютер. Компьютер каждый раз будет говорить куда делает ход. Если компьютер не дает ответ, значит наметилась ничья — завершаем партию и объявляем ничью. Вот таким станет основной цикл игры, когда мы перепишем программу крестики-нолики под игру против компьютера:

# Основная программа
game_over = False
human = True

while game_over == False:

    # 1. Показываем карту
    print_maps()

    # 2. Спросим у играющего куда делать ход
    if human == True:
        symbol = "X"
        step = int(input("Человек, ваш ход: "))
    else:
        print("Компьютер делает ход: ")
        symbol = "O"
        step = AI()

    # 3. Если компьютер нашел куда сделать ход, то играем. Если нет, то ничья.
    if step != "":
        step_maps(step,symbol) # делаем ход в указанную ячейку
        win = get_result() # определим победителя
        if win != "":
            game_over = True
        else:
            game_over = False
    else:
        print("Ничья!")
        game_over = True
        win = "дружба"

    human = not(human)        

# Игра окончена. Покажем карту. Объявим победителя.        
print_maps()
print("Победил", win)    

Вот готовая программа для для игры против искусственного интеллекта.

# Инициализация карты
maps = [1,2,3,
        4,5,6,
        7,8,9]

# Инициализация победных линий
victories = [[0,1,2],
             [3,4,5],
             [6,7,8],
             [0,3,6],
             [1,4,7],
             [2,5,8],
             [0,4,8],
             [2,4,6]]

# Вывод карты на экран
def print_maps():
    print(maps[0], end = " ")
    print(maps[1], end = " ")
    print(maps[2])

    print(maps[3], end = " ")
    print(maps[4], end = " ")
    print(maps[5])

    print(maps[6], end = " ")
    print(maps[7], end = " ")
    print(maps[8])
    
# Сделать ход в ячейку
def step_maps(step,symbol):
    ind = maps.index(step)
    maps[ind] = symbol

# Получить текущий результат игры
def get_result():
    win = ""

    for i in victories:
        if maps[i[0]] == "X" and maps[i[1]] == "X" and maps[i[2]] == "X":
            win = "X"
        if maps[i[0]] == "O" and maps[i[1]] == "O" and maps[i[2]] == "O":
            win = "O"    
            
    return win

#Искусственный интеллект: поиск линии с нужным количеством X и O на победных линиях
def check_line(sum_O,sum_X):

    step = ""
    for line in victories:
        o = 0
        x = 0

        for j in range(0,3):
            if maps[line[j]] == "O":
                o = o + 1
            if maps[line[j]] == "X":
                x = x + 1

        if o == sum_O and x == sum_X:
            for j in range(0,3):
                if maps[line[j]] != "O" and maps[line[j]] != "X":
                    step = maps[line[j]]
                
    return step

#Искусственный интеллект: выбор хода
def AI():        

    step = ""

    # 1) если на какой либо из победных линий 2 свои фигуры и 0 чужих - ставим
    step = check_line(2,0)

    # 2) если на какой либо из победных линий 2 чужие фигуры и 0 своих - ставим
    if step == "":
        step = check_line(0,2)        

    # 3) если 1 фигура своя и 0 чужих - ставим
    if step == "":
        step = check_line(1,0)           

    # 4) центр пуст, то занимаем центр
    if step == "":
        if maps[4] != "X" and maps[4] != "O":
            step = 5            

    # 5) если центр занят, то занимаем первую ячейку
    if step == "":
        if maps[0] != "X" and maps[0] != "O":
            step = 1            
  
    return step

# Основная программа
game_over = False
human = True

while game_over == False:

    # 1. Показываем карту
    print_maps()

    # 2. Спросим у играющего куда делать ход
    if human == True:
        symbol = "X"
        step = int(input("Человек, ваш ход: "))
    else:
        print("Компьютер делает ход: ")
        symbol = "O"
        step = AI()

    # 3. Если компьютер нашел куда сделать ход, то играем. Если нет, то ничья.
    if step != "":
        step_maps(step,symbol) # делаем ход в указанную ячейку
        win = get_result() # определим победителя
        if win != "":
            game_over = True
        else:
            game_over = False
    else:
        print("Ничья!")
        game_over = True
        win = "дружба"

    human = not(human)        

# Игра окончена. Покажем карту. Объявим победителя.        
print_maps()
print("Победил", win)   


Вот пример игрового процессе. В этой игре победил компьютер:

1 2 3
4 5 6
7 8 9
Человек, ваш ход: 1
X 2 3
4 5 6
7 8 9
Компьютер делает ход: 
X 2 3
4 O 6
7 8 9
Человек, ваш ход: 2
X X 3
4 O 6
7 8 9
Компьютер делает ход: 
X X O
4 O 6
7 8 9
Человек, ваш ход: 4
X X O
X O 6
7 8 9
Компьютер делает ход: 
X X O
X O 6
O 8 9
Победил O

Вы можете прямо сейчас поиграть в крестики нолики против компьютера или друг против друга. Просто скопируйте текст программы на этой странице и вставьте его в поле программы в этом онлайн эмуляторе Python: https://replit.com/languages/python3 или тут https://www.onlinegdb.com/online_python_compiler

Домашнее задание

У нас получилась довольно беспощадная программа. Ее искусственный интеллект победить не возможно. Человек либо проигрывает, либо играет в ничью. Подумайте как можно дать человеку иногда выигрывать? Возможно вы захотите создать несколько уровней. Например в первом искусственный интеллект очень слаб, дальше он умнет. Или у вас будет на выбор несколько режимов игры на выбор: слабый ИИ, средний и непобедимый.

В общем ваша задача немного ослабить искусственный интеллект в нашей игре крестики-нолики. Сделать его чуть более человечным.

На чтение 5 мин Просмотров 1к. Опубликовано 09.11.2022

Содержание

  1. Введение
  2. Рисуем игровое поле
  3. Принимаем ввод пользователя
  4. Проверка, выиграл ли игрок
  5. Создание главной функции
  6. Итоговый код игры “Крестики-нолики” на Python
  7. Заключение

Введение

В статье напишем игру “Крестики-нолики” на Python.

Крестики-нолики — логическая игра между двумя соперниками на квадратном поле 3×3 клетки, или бо́льшего размера. Один из игроков играет за “крестики”, а второй за “нолики”.

Рисуем игровое поле

Начнём с того, что нарисуем само игровое поле для игры.

Для начала сгенерируем список с числами от одного, до 9:

board = list(range(1, 10))

Создадим функцию draw_board(), аргументом которой будет board:

def draw_board(board):
    print("-" * 13)
    for i in range(3):
        print("|", board[0 + i * 3], "|", board[1 + i * 3], "|", board[2 + i * 3], "|")
        print("-" * 13)

В функции выводим первую строку состоящую из 13 символов “тире”, после чего, в цикле прорисовываем остальные края поля.

При вызове функции будет следующий вывод:

Игровое поле “Крестики-нолики”

Принимаем ввод пользователя

Теперь нам нужно создать функцию для приёма ввода.

Создадим функцию take_input() с аргументом player_token:

def take_input(player_token):
    valid = False
    while not valid:
        player_answer = input("Куда поставим " + player_token + "? ")
        try:
            player_answer = int(player_answer)
        except ValueError:
            print("Некорректный ввод. Вы уверены, что ввели число?")
            continue
        if 1 <= player_answer <= 9:
            if str(board[player_answer - 1]) not in "XO":
                board[player_answer - 1] = player_token
                valid = True
            else:
                print("Эта клетка уже занята!")
        else:
            print("Некорректный ввод. Введите число от 1 до 9.")

Внутри функции сначала задаётся переменная valid, которая равняется False, после чего идёт цикл while, который не закончится, пока valid не примет значение True. В цикле производится ввод пользователем определённой клетки, в которую будет ставиться крестик, либо нолик. Если же пользователь ввёл, а какой-либо другой символ, выведется ошибка.

Далее в условии проверяется, занята ли введённая клетка. Если клетка занята, то выведется соответствующая ошибка, если же введено число не в диапазоне от 1, до 10 – будет так же выведено соответствующее сообщение.

Проверка, выиграл ли игрок

Создадим функцию check_win(), в которой будем проверять, выиграл ли игрок. Аргументом функции будет board:

def check_win(board):
    win_coord = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6))
    for each in win_coord:
        if board[each[0]] == board[each[1]] == board[each[2]]:
            return board[each[0]]
    return False

Внутри функции создаётся кортеж win_coord, в котором хранятся победные комбинации. В цикле производится проверка на победу игрока, если он побеждает, то выводится сообщение о победе, если же нет – возвращается False, и игра продолжается.

Создание главной функции

Теперь создадим функцию main() с аргументом board:

def main(board):
    counter = 0
    win = False
    while not win:
        draw_board(board)
        if counter % 2 == 0:
            take_input("X")
        else:
            take_input("O")
        counter += 1

        tmp = check_win(board)
        if tmp:
            print(tmp, "выиграл!")
            win = True
            break
        if counter == 9:
            print("Ничья!")
            break
    draw_board(board)

Внутри функции, после обозначения переменных, создаётся цикл, который закончится после победы одного из игроков, или ничьей. Внутри цикла проводится проверка, какой игрок сходил, после чего вызывается функция take_input() с соответствующим символом игрока. Далее идёт проверка, какой игрок выиграл, или вышла ничья.

Итоговый код игры “Крестики-нолики” на Python

Итоговый код:

board = list(range(1, 10))

def draw_board(board):
    print("-" * 13)
    for i in range(3):
        print("|", board[0 + i * 3], "|", board[1 + i * 3], "|", board[2 + i * 3], "|")
        print("-" * 13)


def take_input(player_token):
    valid = False
    while not valid:
        player_answer = input("Куда поставим " + player_token + "? ")
        try:
            player_answer = int(player_answer)
        except ValueError:
            print("Некорректный ввод. Вы уверены, что ввели число?")
            continue
        if 1 <= player_answer <= 9:
            if str(board[player_answer - 1]) not in "XO":
                board[player_answer - 1] = player_token
                valid = True
            else:
                print("Эта клетка уже занята!")
        else:
            print("Некорректный ввод. Введите число от 1 до 9.")


def check_win(board):
    win_coord = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6))
    for each in win_coord:
        if board[each[0]] == board[each[1]] == board[each[2]]:
            return board[each[0]]
    return False


def main(board):
    counter = 0
    win = False
    while not win:
        draw_board(board)
        if counter % 2 == 0:
            take_input("X")
        else:
            take_input("O")
        counter += 1

        tmp = check_win(board)
        if tmp:
            print(tmp, "выиграл!")
            win = True
            break
        if counter == 9:
            print("Ничья!")
            break
    draw_board(board)


main(board)

input("Нажмите Enter для выхода!")

Заключение

В статье мы с Вами написали игру “Крестики-нолики” на Python! Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂

import random

import tkinter

from tkinter import *

from functools import partial

from tkinter import messagebox

from copy import deepcopy

sign = 0

global board

board = [[" " for x in range(3)] for y in range(3)]

def winner(b, l):

    return ((b[0][0] == l and b[0][1] == l and b[0][2] == l) or

            (b[1][0] == l and b[1][1] == l and b[1][2] == l) or

            (b[2][0] == l and b[2][1] == l and b[2][2] == l) or

            (b[0][0] == l and b[1][0] == l and b[2][0] == l) or

            (b[0][1] == l and b[1][1] == l and b[2][1] == l) or

            (b[0][2] == l and b[1][2] == l and b[2][2] == l) or

            (b[0][0] == l and b[1][1] == l and b[2][2] == l) or

            (b[0][2] == l and b[1][1] == l and b[2][0] == l))

def get_text(i, j, gb, l1, l2):

    global sign

    if board[i][j] == ' ':

        if sign % 2 == 0:

            l1.config(state=DISABLED)

            l2.config(state=ACTIVE)

            board[i][j] = "X"

        else:

            l2.config(state=DISABLED)

            l1.config(state=ACTIVE)

            board[i][j] = "O"

        sign += 1

        button[i][j].config(text=board[i][j])

    if winner(board, "X"):

        gb.destroy()

        box = messagebox.showinfo("Winner", "Player 1 won the match")

    elif winner(board, "O"):

        gb.destroy()

        box = messagebox.showinfo("Winner", "Player 2 won the match")

    elif(isfull()):

        gb.destroy()

        box = messagebox.showinfo("Tie Game", "Tie Game")

def isfree(i, j):

    return board[i][j] == " "

def isfull():

    flag = True

    for i in board:

        if(i.count(' ') > 0):

            flag = False

    return flag

def gameboard_pl(game_board, l1, l2):

    global button

    button = []

    for i in range(3):

        m = 3+i

        button.append(i)

        button[i] = []

        for j in range(3):

            n = j

            button[i].append(j)

            get_t = partial(get_text, i, j, game_board, l1, l2)

            button[i][j] = Button(

                game_board, bd=5, command=get_t, height=4, width=8)

            button[i][j].grid(row=m, column=n)

    game_board.mainloop()

def pc():

    possiblemove = []

    for i in range(len(board)):

        for j in range(len(board[i])):

            if board[i][j] == ' ':

                possiblemove.append([i, j])

    move = []

    if possiblemove == []:

        return

    else:

        for let in ['O', 'X']:

            for i in possiblemove:

                boardcopy = deepcopy(board)

                boardcopy[i[0]][i[1]] = let

                if winner(boardcopy, let):

                    return i

        corner = []

        for i in possiblemove:

            if i in [[0, 0], [0, 2], [2, 0], [2, 2]]:

                corner.append(i)

        if len(corner) > 0:

            move = random.randint(0, len(corner)-1)

            return corner[move]

        edge = []

        for i in possiblemove:

            if i in [[0, 1], [1, 0], [1, 2], [2, 1]]:

                edge.append(i)

        if len(edge) > 0:

            move = random.randint(0, len(edge)-1)

            return edge[move]

def get_text_pc(i, j, gb, l1, l2):

    global sign

    if board[i][j] == ' ':

        if sign % 2 == 0:

            l1.config(state=DISABLED)

            l2.config(state=ACTIVE)

            board[i][j] = "X"

        else:

            button[i][j].config(state=ACTIVE)

            l2.config(state=DISABLED)

            l1.config(state=ACTIVE)

            board[i][j] = "O"

        sign += 1

        button[i][j].config(text=board[i][j])

    x = True

    if winner(board, "X"):

        gb.destroy()

        x = False

        box = messagebox.showinfo("Winner", "Player won the match")

    elif winner(board, "O"):

        gb.destroy()

        x = False

        box = messagebox.showinfo("Winner", "Computer won the match")

    elif(isfull()):

        gb.destroy()

        x = False

        box = messagebox.showinfo("Tie Game", "Tie Game")

    if(x):

        if sign % 2 != 0:

            move = pc()

            button[move[0]][move[1]].config(state=DISABLED)

            get_text_pc(move[0], move[1], gb, l1, l2)

def gameboard_pc(game_board, l1, l2):

    global button

    button = []

    for i in range(3):

        m = 3+i

        button.append(i)

        button[i] = []

        for j in range(3):

            n = j

            button[i].append(j)

            get_t = partial(get_text_pc, i, j, game_board, l1, l2)

            button[i][j] = Button(

                game_board, bd=5, command=get_t, height=4, width=8)

            button[i][j].grid(row=m, column=n)

    game_board.mainloop()

def withpc(game_board):

    game_board.destroy()

    game_board = Tk()

    game_board.title("Tic Tac Toe")

    l1 = Button(game_board, text="Player : X", width=10)

    l1.grid(row=1, column=1)

    l2 = Button(game_board, text="Computer : O",

                width=10, state=DISABLED)

    l2.grid(row=2, column=1)

    gameboard_pc(game_board, l1, l2)

def withplayer(game_board):

    game_board.destroy()

    game_board = Tk()

    game_board.title("Tic Tac Toe")

    l1 = Button(game_board, text="Player 1 : X", width=10)

    l1.grid(row=1, column=1)

    l2 = Button(game_board, text="Player 2 : O",

                width=10, state=DISABLED)

    l2.grid(row=2, column=1)

    gameboard_pl(game_board, l1, l2)

def play():

    menu = Tk()

    menu.geometry("250x250")

    menu.title("Tic Tac Toe")

    wpc = partial(withpc, menu)

    wpl = partial(withplayer, menu)

    head = Button(menu, text="---Welcome to tic-tac-toe---",

                  activeforeground='red',

                  activebackground="yellow", bg="red",

                  fg="yellow", width=500, font='summer', bd=5)

    B1 = Button(menu, text="Single Player", command=wpc,

                activeforeground='red',

                activebackground="yellow", bg="red",

                fg="yellow", width=500, font='summer', bd=5)

    B2 = Button(menu, text="Multi Player", command=wpl, activeforeground='red',

                activebackground="yellow", bg="red", fg="yellow",

                width=500, font='summer', bd=5)

    B3 = Button(menu, text="Exit", command=menu.quit, activeforeground='red',

                activebackground="yellow", bg="red", fg="yellow",

                width=500, font='summer', bd=5)

    head.pack(side='top')

    B1.pack(side='top')

    B2.pack(side='top')

    B3.pack(side='top')

    menu.mainloop()

if __name__ == '__main__':

    play()

import random

import tkinter

from tkinter import *

from functools import partial

from tkinter import messagebox

from copy import deepcopy

sign = 0

global board

board = [[" " for x in range(3)] for y in range(3)]

def winner(b, l):

    return ((b[0][0] == l and b[0][1] == l and b[0][2] == l) or

            (b[1][0] == l and b[1][1] == l and b[1][2] == l) or

            (b[2][0] == l and b[2][1] == l and b[2][2] == l) or

            (b[0][0] == l and b[1][0] == l and b[2][0] == l) or

            (b[0][1] == l and b[1][1] == l and b[2][1] == l) or

            (b[0][2] == l and b[1][2] == l and b[2][2] == l) or

            (b[0][0] == l and b[1][1] == l and b[2][2] == l) or

            (b[0][2] == l and b[1][1] == l and b[2][0] == l))

def get_text(i, j, gb, l1, l2):

    global sign

    if board[i][j] == ' ':

        if sign % 2 == 0:

            l1.config(state=DISABLED)

            l2.config(state=ACTIVE)

            board[i][j] = "X"

        else:

            l2.config(state=DISABLED)

            l1.config(state=ACTIVE)

            board[i][j] = "O"

        sign += 1

        button[i][j].config(text=board[i][j])

    if winner(board, "X"):

        gb.destroy()

        box = messagebox.showinfo("Winner", "Player 1 won the match")

    elif winner(board, "O"):

        gb.destroy()

        box = messagebox.showinfo("Winner", "Player 2 won the match")

    elif(isfull()):

        gb.destroy()

        box = messagebox.showinfo("Tie Game", "Tie Game")

def isfree(i, j):

    return board[i][j] == " "

def isfull():

    flag = True

    for i in board:

        if(i.count(' ') > 0):

            flag = False

    return flag

def gameboard_pl(game_board, l1, l2):

    global button

    button = []

    for i in range(3):

        m = 3+i

        button.append(i)

        button[i] = []

        for j in range(3):

            n = j

            button[i].append(j)

            get_t = partial(get_text, i, j, game_board, l1, l2)

            button[i][j] = Button(

                game_board, bd=5, command=get_t, height=4, width=8)

            button[i][j].grid(row=m, column=n)

    game_board.mainloop()

def pc():

    possiblemove = []

    for i in range(len(board)):

        for j in range(len(board[i])):

            if board[i][j] == ' ':

                possiblemove.append([i, j])

    move = []

    if possiblemove == []:

        return

    else:

        for let in ['O', 'X']:

            for i in possiblemove:

                boardcopy = deepcopy(board)

                boardcopy[i[0]][i[1]] = let

                if winner(boardcopy, let):

                    return i

        corner = []

        for i in possiblemove:

            if i in [[0, 0], [0, 2], [2, 0], [2, 2]]:

                corner.append(i)

        if len(corner) > 0:

            move = random.randint(0, len(corner)-1)

            return corner[move]

        edge = []

        for i in possiblemove:

            if i in [[0, 1], [1, 0], [1, 2], [2, 1]]:

                edge.append(i)

        if len(edge) > 0:

            move = random.randint(0, len(edge)-1)

            return edge[move]

def get_text_pc(i, j, gb, l1, l2):

    global sign

    if board[i][j] == ' ':

        if sign % 2 == 0:

            l1.config(state=DISABLED)

            l2.config(state=ACTIVE)

            board[i][j] = "X"

        else:

            button[i][j].config(state=ACTIVE)

            l2.config(state=DISABLED)

            l1.config(state=ACTIVE)

            board[i][j] = "O"

        sign += 1

        button[i][j].config(text=board[i][j])

    x = True

    if winner(board, "X"):

        gb.destroy()

        x = False

        box = messagebox.showinfo("Winner", "Player won the match")

    elif winner(board, "O"):

        gb.destroy()

        x = False

        box = messagebox.showinfo("Winner", "Computer won the match")

    elif(isfull()):

        gb.destroy()

        x = False

        box = messagebox.showinfo("Tie Game", "Tie Game")

    if(x):

        if sign % 2 != 0:

            move = pc()

            button[move[0]][move[1]].config(state=DISABLED)

            get_text_pc(move[0], move[1], gb, l1, l2)

def gameboard_pc(game_board, l1, l2):

    global button

    button = []

    for i in range(3):

        m = 3+i

        button.append(i)

        button[i] = []

        for j in range(3):

            n = j

            button[i].append(j)

            get_t = partial(get_text_pc, i, j, game_board, l1, l2)

            button[i][j] = Button(

                game_board, bd=5, command=get_t, height=4, width=8)

            button[i][j].grid(row=m, column=n)

    game_board.mainloop()

def withpc(game_board):

    game_board.destroy()

    game_board = Tk()

    game_board.title("Tic Tac Toe")

    l1 = Button(game_board, text="Player : X", width=10)

    l1.grid(row=1, column=1)

    l2 = Button(game_board, text="Computer : O",

                width=10, state=DISABLED)

    l2.grid(row=2, column=1)

    gameboard_pc(game_board, l1, l2)

def withplayer(game_board):

    game_board.destroy()

    game_board = Tk()

    game_board.title("Tic Tac Toe")

    l1 = Button(game_board, text="Player 1 : X", width=10)

    l1.grid(row=1, column=1)

    l2 = Button(game_board, text="Player 2 : O",

                width=10, state=DISABLED)

    l2.grid(row=2, column=1)

    gameboard_pl(game_board, l1, l2)

def play():

    menu = Tk()

    menu.geometry("250x250")

    menu.title("Tic Tac Toe")

    wpc = partial(withpc, menu)

    wpl = partial(withplayer, menu)

    head = Button(menu, text="---Welcome to tic-tac-toe---",

                  activeforeground='red',

                  activebackground="yellow", bg="red",

                  fg="yellow", width=500, font='summer', bd=5)

    B1 = Button(menu, text="Single Player", command=wpc,

                activeforeground='red',

                activebackground="yellow", bg="red",

                fg="yellow", width=500, font='summer', bd=5)

    B2 = Button(menu, text="Multi Player", command=wpl, activeforeground='red',

                activebackground="yellow", bg="red", fg="yellow",

                width=500, font='summer', bd=5)

    B3 = Button(menu, text="Exit", command=menu.quit, activeforeground='red',

                activebackground="yellow", bg="red", fg="yellow",

                width=500, font='summer', bd=5)

    head.pack(side='top')

    B1.pack(side='top')

    B2.pack(side='top')

    B3.pack(side='top')

    menu.mainloop()

if __name__ == '__main__':

    play()

Очень полезно в целях изучения языка программирования написать на нем несколько простых программ. Здесь мы представим игру крестики-нолики, которая написана на Python 3 с графическим интерфейсом.

О программе

В этой игре можно помериться силами с компьютером. Первый ход за игроком. Но победить искусственный интеллект в этом противостоянии будет не так уж и просто. Компьютер не делает «зевков» и если у него есть шанс победить, он непременно им воспользуется.

Внизу расположена кнопка для начала новой игры. По её нажатию игровое поле очистится и можно будет начать игру заново.

Игрок ставит крестики, а компьютер нолики. Как всегда, побеждает тот, кто первый составит линию из своих символов: по горизонтали, вертикали или диагонали.

Библиотеки и объявление переменных

Для отображения графики будем использовать стандартную библиотеку Tkinter, которая устанавливается вместе с Python. Так же нам потребуется библиотека random для того, чтобы получать случайные числа, благодаря которым ходы компьютера будут неожиданными.

Это также стандартная библиотека Python. Так что ничего дополнительно устанавливать не надо. Просто подключаем их с помощью import. Создаем окно root, устанавливаем ему заголовок и объявляем необходимые переменные:

  • game_run – в эту переменную будем записывать False при завершении игры, чтобы запретить делать ходы когда уже выявлен победитель.
  • field – это будет двумерный список, в котором будут храниться кнопки игрового поля. Ходом будет изменение надписи на кнопке на символ «X» или «O».
  • cross_count в этой переменной мы будем отслеживать количество крестиков на поле. Чтобы по выставлению пятого крестика, в случае если никто не выиграл фиксировать ничью.
from tkinter import *
import random
root = Tk()
root.title('Criss-cross')
game_run = True
field = []
cross_count = 0

Обработка нажатия кнопок

Функция new_game будет вызываться при нажатии кнопки начала новой игры. На поле убираются все крестики и нолики. Цвет кнопок делаем бледно-лиловым. Устанавливаем глобальные переменные game_run и cross_count в начальные значения. Это глобальные переменные к которым пытаемся обратиться из функции. Поэтому перед попыткой изменить их значение, в Python надо использовать ключевое слово global.

def new_game():
    for row in range(3):
        for col in range(3):
            field[row][col]['text'] = ' '
            field[row][col]['background'] = 'lavender'
    global game_run
    game_run = True
    global cross_count
    cross_count = 0

Функция click будет вызываться после нажатия на поле, то есть при попытки поставить крестик. Если игра еще не завершена, то крестик ставится. После этого увеличиваем счетчик количества выставленных крестиков.

Потом проверяем с помощью функции check_win, не победили ли мы этим ходом. Если еще не выявлен победитель и есть еще ходы, то выполняет ход компьютер функцией computer_move, и также после хода идет проверка выигрыша.

def click(row, col):
    if game_run and field[row][col]['text'] == ' ':
        field[row][col]['text'] = 'X'
        global cross_count
        cross_count += 1
        check_win('X')
        if game_run and cross_count < 5:
            computer_move()
            check_win('O')

Проверка победы

Функция check_win осуществляет проверку выигрыша. Она перебирает все возможные комбинации полей, образующих линию и вызывает с ними функцию check_line. Переменная smb – это символ «X» или «O», то есть крестики или нолики. Если задан «O», то проверяется: не победил ли компьютер.

Если зафиксирован выигрыш, то меняем цвет фона кнопок, составляющих линию на розовый. А также записываем в game_run значение False.

def check_win(smb):
    for n in range(3):
        check_line(field[n][0], field[n][1], field[n][2], smb)
        check_line(field[0][n], field[1][n], field[2][n], smb)
    check_line(field[0][0], field[1][1], field[2][2], smb)
    check_line(field[2][0], field[1][1], field[0][2], smb)

def check_line(a1,a2,a3,smb):
    if a1['text'] == smb and a2['text'] == smb and a3['text'] == smb:
        a1['background'] = a2['background'] = a3['background'] = 'pink'
        global game_run
        game_run = False

Проверяем все возможные варианты, так как теоретически можно одним ходом составить сразу 2 линии.

Действия компьютера

Ход компьютера рассчитывается в функции computer_move. Алгоритм его действий следующий:

  1. Проверка возможности победы. Если компьютеру представился шанс победы – он не должен его упустить. Сразу же делает победу.
  2. Проверка возможной победы противника за один ход. Если игрок выставил два крестика в ряд, компьютер пытается разрушить планы игрока.
  3. Случайный ход. Так как победить нет возможности и нет угрозы проигрыша, то выбирается случайное свободное поле. В бесконечном цикле wile перебираются случайные числа, пока они не выпадут на не занятое поле.
def can_win(a1,a2,a3,smb):
    res = False
    if a1['text'] == smb and a2['text'] == smb and a3['text'] == ' ':
        a3['text'] = 'O'
        res = True
    if a1['text'] == smb and a2['text'] == ' ' and a3['text'] == smb:
        a2['text'] = 'O'
        res = True
    if a1['text'] == ' ' and a2['text'] == smb and a3['text'] == smb:
        a1['text'] = 'O'
        res = True
    return res

def computer_move():
    for n in range(3):
        if can_win(field[n][0], field[n][1], field[n][2], 'O'):
            return
        if can_win(field[0][n], field[1][n], field[2][n], 'O'):
            return
    if can_win(field[0][0], field[1][1], field[2][2], 'O'):
        return
    if can_win(field[2][0], field[1][1], field[0][2], 'O'):
        return
    for n in range(3):
        if can_win(field[n][0], field[n][1], field[n][2], 'X'):
            return
        if can_win(field[0][n], field[1][n], field[2][n], 'X'):
            return
    if can_win(field[0][0], field[1][1], field[2][2], 'X'):
        return
    if can_win(field[2][0], field[1][1], field[0][2], 'X'):
        return
    while True:
        row = random.randint(0, 2)
        col = random.randint(0, 2)
        if field[row][col]['text'] == ' ':
            field[row][col]['text'] = 'O'
            break

Графический интерфейс

Все элементы графического интерфейса мы будем размещать с помощью упаковщика grid. В цикле добавим кнопки игрового поля. Они будут храниться в двумерном список. В языке программирования Python добавляют элементы в список с помощью метода append.

Свойство colorspan у кнопки начала игры выставляем в 3, чтобы он занимал всю ширину таблицы

for row in range(3):
    line = []
    for col in range(3):
        button = Button(root, text=' ', width=4, height=2, 
                        font=('Verdana', 20, 'bold'),
                        background='lavender',
                        command=lambda row=row, col=col: click(row,col))
        button.grid(row=row, column=col, sticky='nsew')
        line.append(button)
    field.append(line)
new_button = Button(root, text='new game', command=new_game)
new_button.grid(row=3, column=0, columnspan=3, sticky='nsew')
root.mainloop()

Игровое поле мы делали таким же образом как и кнопки в примере с калькулятором, размещённом в отдельной статье.

В целом, реализация игры крестики-нолики неплохо подходит для изучающих программирование на Python 3. Можно немного усложнить задачу, добавив уровни сложности. Например, на простом уровне сложности компьютер делает абсолютно случайные ходы. На более сложном не упускает возможности победить, но все еще может прозевать два крестика выставленных в ряд.

В данном руководстве мы создадим игру, известную как Tic-Tac-Toe (крестики-нолики), используя язык программирования Python с нуля. Мы разделили всю программу на несколько этапов для лучшего понимания. Но прежде чем мы перейдем к процедуре, давайте разберемся с игрой.

Что такое крестики-нолики?

Крестики-нолики на Python – одна из игр, в которые играют два игрока на квадратной сетке 3 x 3. Каждый игрок заселяет клетку в свои ходы, стараясь поставить три одинаковых метки по вертикали, горизонтали или диагонали. Первый игрок использует Крестик (X) как маркер, а другой использует Ноль (O).

Теперь давайте разберемся с ее дизайном.

Дизайн крестиков-ноликов

Мы будем использовать командную строку, чтобы играть в крестики-нолики. Таким образом, основная цель – создать дизайн для игры «Крестики-нолики».

Задача: если игроку нужно отметить определенный блок, он / она должен ввести соответствующую цифру, отображаемую в сетке. Например, мы хотели занять верхний правый блок, а затем нам нужно ввести цифру 3 в терминал.

Давайте разберемся с фрагментом кода для создания сетки.

Программа:

 
# Function to print the Tic-Tac-Toe Design 
def mytictactoe(val): 
    print("n") 
    print("t     |     |") 
    print("t  {}  |  {}  |  {}".format(val[0], val[1], val[2])) 
    print('t_____|_____|_____') 
  
    print("t     |     |") 
    print("t  {}  |  {}  |  {}".format(val[3], val[4], val[5])) 
    print('t_____|_____|_____') 
  
    print("t     |     |") 
  
    print("t  {}  |  {}  |  {}".format(val[6], val[7], val[8])) 
    print("t     |     |") 
    print("n") 

Объяснение:

В приведенном выше фрагменте кода мы определили функцию для игры Tic-Tac-Toe, которая принимает значения в качестве параметра. Здесь параметр val представляет собой список, состоящий из статуса каждой ячейки в сетке. Затем внутри функции мы распечатали дизайн сетки игры.

Теперь следующий шаг – сохранить данные с помощью структур данных.

Хранение данных с использованием структур данных

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

В любой момент времени требуются две важные части информации:

  1. Состояние сетки: мы должны создать структуру данных, которая будет содержать состояние каждой ячейки. Состояние может быть как занятым, так и вакантным.
  2. Ходы каждого игрока: каким-то образом требуется знание прошлых и настоящих ходов каждого игрока, то есть позиций, занятых ‘X’ и ‘O’.

Примечание: к приведенным выше данным можно получить доступ с помощью Grid Status. Однако нам потребуется просматривать эту информацию каждый раз, когда нам нужны позиции игрока. Это можно назвать компромиссом между временем и сложностью пространства. Это общая техника для экономии времени.

Синтаксис для этого показан ниже.

Фрагмент кода:

 
# Function for a single game of Tic-Tac-Toe 
def singlegame(curplayer): 
    # Representing the Tic-Tac-Toe 
    val = [' ' for i in range(9)] 
      
    # Storing the positions occupied by X and O 
    playerpos = {'X' : [], 'O' : []} 

Объяснение:

В приведенном выше фрагменте кода мы определили функцию для одной игры в крестики-нолики, где val представляет параметр для предыдущей функции, а playerpos хранит позицию блока, занятого крестиком(X) и нулем( O) соответственно.

Обычно в списке символов, управляющих статусом сетки, есть три значения:

  1. ‘ ‘ – этот символ обозначает свободную или пустую ячейку.
  2. «X» – этот символ означает, что в ячейке находится игрок X.
  3. ‘O’ – этот символ означает, что эта ячейка игрока O.

Действия каждого игрока хранятся в виде словаря из списка целых чисел, где ключи обозначены буквами «X» и «O» для соответствующего игрока. Их списки состоят из цифр, предоставленных ячейкам сетки, в которой они находятся.

Примечание. В переменной curplayer хранится текущий игрок, делающий ход, как в «X» или «O».

Понимание игрового цикла

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

Давайте рассмотрим следующий фрагмент кода, чтобы разработать игровой цикл.

Синтаксис:

 
# Loop of Game for a single game of Tic-Tac-Toe 
while True: 
    mytictactoe(val) 

Объяснение:

Мы использовали цикл while для вывода значений функции mytictactoe(), создав игровой цикл для одной игры в крестики-нолики.

Обработка ввода от Player

Для каждой итерации в игре игрок должен вводить данные для своего хода. Давайте рассмотрим следующий синтаксис, чтобы обработать ввод Player.

Синтаксис:

 
# Try-Exception block for CHANCE input 
try: 
    print("Player ", curplayer, " turn. Choose your Block : ", end="") 
    chance = int(input()) 
except ValueError: 
    print("Invalid Input!!! Try Again") 
    continue 
 
# Sanity check for CHANCE input 
if chance < 1 or chance > 9: 
    print("Invalid Input!!! Try Again") 
    continue 
  
# Checking if the block is not occupied already 
if val[chance - 1] != ' ': 
    print("Oops! The Place is already occupied. Try again!!") 
    continue 

Объяснение:

Для приведенного выше фрагмента кода мы создали блок try для обработки непредусмотренного значения игроков. Затем мы обработали исключение ValueError, чтобы игру нельзя было останавливать. Позже мы выполнили несколько проверок работоспособности, например, является ли введенное значение допустимой позицией или нет, и если это действительная позиция, заполнена ли она уже?

Теперь перейдем к следующему шагу.

Обновление информации об игре

В соответствии с вводом, предоставленным игроком, мы должны обновить информацию для бесперебойной работы игры. Мы можем обновить информацию об игре, добавив следующий фрагмент кода в основной проект.

Синтаксис:

 
# Updating the game information 
  
# Update the status of the grid 
val[chance - 1] = curplayer 
  
# Update the positions of the player 
playerpos[curplayer].append(chance) 

Объяснение:

В приведенном выше фрагменте кода мы обновили информацию об игре, обновив состояние сетки и положение игрока. Список val обновит ячейку, заполненную в соответствии с текущим игроком. Позиция игрока добавит позицию, только что занятую текущим игроком.

После обновления списка val мы вызовем функцию mytictactoe(), и сетка будет выглядеть следующим образом:

Выход:

             |     | 
          1  |  2  |  3 
        _____|_____|_____ 
             |     | 
          4  |  5  |  6 
        _____|_____|_____ 
             |     | 
          7  |  8  |  9 
             |     | 

Проверка победы или ничьей

После каждого хода нам нужно проверять, выиграл ли какой-либо игрок матч или матч был ничейным. Мы можем проверить это с помощью синтаксиса, приведенного ниже:

Синтаксис:

 
# Calling Function to check Victory 
if check_Victory(playerpos, curplayer): 
    mytictactoe(val) 
    print("Congratulations! Player ", curplayer, " has won the game!")      
    print("n") 
    return curplayer 
     
# Calling Function to check Tie 
if check_Tie(playerpos): 
    mytictactoe(val) 
    print("Oh! Game Tied") 
    print("n") 
    return 'D' 

Объяснение:

В приведенном выше синтаксисе мы использовали оператор if для проверки Win или Tie. Функция singlegame() вернет текущего игрока, если он / она выиграет игру. В противном случае игра заканчивается вничью, D отправляется обратно.

Рассмотрим функцию проверки, выиграл ли кто-нибудь из игроков.

Синтаксис:

 
# Defining Function to check Victory 
def check_Victory(playerpos, curplayer): 
  
    # All probable winning combinations 
    solution = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]] 
  
    # Loop to check whether any winning combination is satisfied or not 
    for i in solution: 
        if all(j in playerpos[curplayer] for j in i): 
  
            # Return True if any winning combination is satisfied 
            return True 
    # Return False if no combination is satisfied  
    return False        
  
# Defining Function to check if the game is Tied 
def check_Tie(playerpos): 
    if len(playerpos['X']) + len(playerpos['O']) == 9: 
        return True 
    return False    

Объяснение:

В приведенном выше фрагменте кода мы определили функции для проверки победы или ничьей. Это функции check_Victory() и check_Tie() соответственно.

  1. check_Victory(): хранит все комбинации для победы в игре. Функция проверяет, удовлетворяет ли позиция текущего игрока какой-либо из выигрышных комбинаций. Если это так, она вернет ИСТИНА; в противном случае будет ЛОЖЬ, если не удовлетворяет требованию.
  2. check_Tie(): Это довольно просто, проверяет, заняты ли все позиции “Девять”, и игра ставится вничью.

Смена текущего игрока

У каждого игрока за один ход был только один шанс. Таким образом, после каждого успешного повторения текущий игрок будет заменен. Давайте рассмотрим следующий фрагмент кода для того же:

Синтаксис:

 
# Switching moves of the player 
if curplayer == 'X': 
    curplayer = 'O' 
else: 
    curplayer = 'X' 

Объяснение:

Мы использовали оператор if-else для переключения ходов игрока таким образом, что если текущий игрок отмечает одну позицию, то текущий игрок будет изменен, а другой игрок будет совершать  ход.

Вот некоторые шаги, о которых нам нужно позаботиться при создании одиночной игры. Однако мы будем создавать систему табло, чтобы отслеживать игроков, желающих сыграть в несколько игр.

Ввод имен игроков

Поскольку мы создаем Табло, нам необходимо отображать имена каждого игрока.

Синтаксис:

 
if __name__ == "__main__": 
  
    print("First Player") 
    FirstPlayer = input("Specify the Name: ") 
    print("n") 
  
    print("Second Player") 
    SecondPlayer = input("Specify the Name: ") 
    print("n") 

Объяснение:

Как мы можем заметить, мы использовали специальную переменную __name__, чтобы иметь значение «__main__». Затем мы предоставили ввод для имен первого и второго игроков соответственно. Это станет точкой входа для программы, и программа, которую мы будем выполнять, сначала запросит имена.

Хранение информации об игре

Мы должны хранить такую информацию, как текущий игрок, выбор игрока (например, X или O), доступные варианты выбора (X или O) и табло.

Синтаксис:

 
# Storing the player who chooses X and O 
curplayer = FirstPlayer 
  
# Storing the Players' choice 
playerchoice = {'X' : "", 'O' : ""} 
  
# Storing the options 
opt = ['X', 'O'] 
  
# Storing the scoreboard 
scoreboard = {FirstPlayer: 0, SecondPlayer: 0} 
myscoreboard(scoreboard) 

Объяснение:

В приведенном выше фрагменте кода мы установили текущего игрока как Первого игрока. Мы также сохранили выбор, сделанный игроками, доступные варианты и табло.

Разработка табло

Мы спроектируем табло в структуре данных словаря. На этом табло имена игроков будут действовать как ключи, а их общее количество побед будет действовать как значения. Давайте рассмотрим следующий фрагмент кода для разработки табло для крестиков-ноликов.

Синтаксис:

 
def myscoreboard(scoreboard): 
    print("t--------------------------------") 
    print("t         SCORE BOARD       ") 
    print("t--------------------------------") 
  
    listofplayers = list(scoreboard.keys()) 
    print("t   ", listofplayers[0], "t    ", scoreboard[listofplayers[0]]) 
    print("t   ", listofplayers[1], "t    ", scoreboard[listofplayers[1]]) 
  
    print("t--------------------------------n") 

Объяснение:

В приведенном выше фрагменте кода мы определили функцию как myscoreboard, которая принимает параметр как табло. Затем мы напечатали дизайн Таблицы оценок. Мы определили переменную, которая хранит имена игроков в виде списка, используя функцию .keys(). Затем мы проиндексировали их на табло и отобразили баллы.

Создание внешнего игрового цикла

Чтобы поддерживать несколько совпадений крестиков-ноликов, нам нужен еще один цикл для игры. Текущий игрок будет выбирать оценку для каждого матча. Меню выбора должно отображаться на каждой итерации игры.

Давайте рассмотрим следующий синтаксис, чтобы создать Outer Gamer Loop.

Синтаксис:

 
# Loop for a series of Tic-Tac-Toe game 
# The loop executes until the players quit 
while True: 
  
     # Main Menu for Players 
     print(curplayer, "will make the choice:") 
     print("Press 1 for X") 
     print("Press 2 for O") 
     print("Press 3 to Quit") 

Объяснение:

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

Выход:

First Player 
Specify the Name: Andy 
 
 
Second Player 
Specify the Name: Carlo 
 
 
        -------------------------------- 
                 SCORE BOARD        
        -------------------------------- 
            Andy             0 
            Carlo            0 
        -------------------------------- 
 
Andy will make the choice: 
Press 1 for X 
Press 2 for O 
Press 3 to Quit 

Обработка и назначение выбора для игрока

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

Синтаксис:

 
# Try exception for THE_CHOICE input 
try: 
    the_choice = int(input())    
  except ValueError: 
    print("Invalid Input!!! Try Againn") 
    continue 
  
# Conditions for player choice   
if the_choice == 1: 
    playerchoice['X'] = curplayer 
    if curplayer == FirstPlayer: 
        playerchoice['O'] = SecondPlayer 
    else: 
        playerchoice['O'] = FirstPlayer 
  
elif the_choice == 2: 
     playerchoice['O'] = curplayer 
     if curplayer == FirstPlayer: 
         playerchoice['X'] = SecondPlayer 
     else: 
         playerchoice['X'] = FirstPlayer 
          
elif the_choice == 3: 
     print("The Final Scores") 
     myscoreboard(scoreboard) 
     break   
  
else: 
     print("Invalid Selection!! Try Againn") 

Объяснение:

Мы использовали блок try-exception для обработки любого исключения для ввода the_choice. Затем мы использовали оператор if-else для создания меню выбора для текущего игрока.

В соответствии с выбором, сделанным игроком, данные будут сохранены. Это важно, так как в каждом матче мы узнаем, какой игрок выиграл.

Запуск игры

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

Синтаксис для того же был показан ниже.

Синтаксис:

 
# Storing the winner in a single game of Tic-Tac-Toe 
win = singlegame(opt[the_choice - 1]) 

Объяснение:

В приведенном выше фрагменте кода мы сохранили сведения о победителе для одной игры в крестики-нолики.

Обновление табло

Мы должны обновлять табло после каждого матча в игре «Крестики-нолики».

Давайте рассмотрим следующий фрагмент кода для обновления табло.

Синтаксис:

 
# Updation of the scoreboard as per the winner 
if win != 'D' : 
    playerWon = playerchoice[win] 
    scoreboard[playerWon] = scoreboard[playerWon] + 1 
  
myscoreboard(scoreboard) 

Объяснение:

В приведенном выше фрагменте кода мы использовали оператор if, чтобы проверить, не привязано ли совпадение. Как только матч не будет сыгран вничью, табло будет обновлено.

Переключение выбранного игрока

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

Синтаксис:

 
# Switching player who chooses X or O 
if curplayer == FirstPlayer: 
    curplayer = SecondPlayer 
else: 
    curplayer = FirstPlayer 

Объяснение:

В приведенном выше фрагменте кода мы снова использовали оператор if-else для переключения между игроками для выбора меток (крестик или нолик).

Таким образом, мы успешно создали нашу собственную игру «Крестики-нолики».

Пришло время игры

Поскольку все шаги, наконец, завершены, вот окончательный код игры.

Выход:

First Player 
Specify the Name: Andy 
 
 
Second Player 
Specify the Name: Carlo 
 
 
        -------------------------------- 
                 SCORE BOARD        
        -------------------------------- 
            Andy             0 
            Carlo            0 
        -------------------------------- 
 
Andy will make the choice: 
Press 1 for X 
Press 2 for O 
Press 3 to Quit 
1 
 
 
             |     | 
             |     | 
        _____|_____|_____ 
             |     | 
             |     | 
        _____|_____|_____ 
             |     | 
             |     | 
             |     | 
 
 
Player  X  turn. Choose your Block : 5 
 
 
             |     | 
             |     |    
        _____|_____|_____ 
             |     | 
             |  X  |    
        _____|_____|_____ 
             |     | 
             |     |    
             |     | 
 
 
Player  O  turn. Choose your Block : 3 
 
 
             |     | 
             |     |  O 
        _____|_____|_____ 
             |     | 
             |  X  |    
        _____|_____|_____ 
             |     | 
             |     |    
             |     | 
 
 
Player  X  turn. Choose your Block : 1 
 
 
             |     | 
          X  |     |  O 
        _____|_____|_____ 
             |     | 
             |  X  |    
        _____|_____|_____ 
             |     | 
             |     |    
             |     | 
 
 
Player  O  turn. Choose your Block : 9 
 
 
             |     | 
          X  |     |  O 
        _____|_____|_____ 
             |     | 
             |  X  |    
        _____|_____|_____ 
             |     | 
             |     |  O 
             |     | 
 
 
Player  X  turn. Choose your Block : 6 
 
 
             |     | 
          X  |     |  O 
        _____|_____|_____ 
             |     | 
             |  X  |  X 
        _____|_____|_____ 
             |     | 
             |     |  O 
             |     | 
 
 
Player  O  turn. Choose your Block : 4 
 
 
             |     | 
          X  |     |  O 
        _____|_____|_____ 
             |     | 
          O  |  X  |  X 
        _____|_____|_____ 
             |     | 
             |     |  O 
             |     | 
 
 
Player  X  turn. Choose your Block : 2 
 
 
             |     | 
          X  |  X  |  O 
        _____|_____|_____ 
             |     | 
          O  |  X  |  X 
        _____|_____|_____ 
             |     | 
             |     |  O 
             |     | 
 
 
Player  O  turn. Choose your Block : 8 
 
 
             |     | 
          X  |  X  |  O 
        _____|_____|_____ 
             |     | 
          O  |  X  |  X 
        _____|_____|_____ 
             |     | 
             |  O  |  O 
             |     | 
 
 
Player  X  turn. Choose your Block : 7 
 
 
             |     | 
          X  |  X  |  O 
        _____|_____|_____ 
             |     | 
          O  |  X  |  X 
        _____|_____|_____ 
             |     | 
          X  |  O  |  O 
             |     | 
 
 
Game Tied 
 
 
        -------------------------------- 
                 SCORE BOARD        
        -------------------------------- 
            Andy             0 
            Carlo            0 
        -------------------------------- 
 
Carlo will make the choice: 
Press 1 for X 
Press 2 for O 
Press 3 to Quit 
3 
The Final Scores 
        -------------------------------- 
                 SCORE BOARD 
        -------------------------------- 
            Andy             0 
            Carlo            0 
        -------------------------------- 

Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.

# ВНИМАНИЕ! Это код для учеников — тут есть 5 мест, где делаем оптимизацию кода и меняем X на Y :) # ATTENTION! This is code for students — there are 5 places where we optimize the code and change X to Y :) from tkinter import * from tkinter import messagebox import time import random tk = Tk() app_running = True size_canvas_x = 768 size_canvas_y = 768 def on_closing(): global app_running if messagebox.askokcancel(«Выход из игры», «Хотите выйти из игры?»): app_running = False tk.destroy() tk.protocol(«WM_DELETE_WINDOW», on_closing) tk.title(«Игра крестики-нолики») tk.resizable(0, 0) tk.wm_attributes(«-topmost», 1) canvas = Canvas(tk, width=size_canvas_x, height=size_canvas_y, bd=0, highlightthickness=0) canvas.create_rectangle(0,0,size_canvas_x, size_canvas_y,fill=«white») canvas.pack() tk.update() s_x = 3 s_y = s_x step_x = size_canvas_x // s_x step_y = size_canvas_y // s_y def draw_table(): for i in range(0, s_x + 1): canvas.create_line(0, i * step_y, size_canvas_x, i * step_y) for i in range(0,s_y+1): canvas.create_line(i*step_y,0,i*step_y,size_canvas_y) #points = [[-1,-1,-1],[-1,-1,-1],[-1,-1,-1]] points = [[1 for i in range(s_x)] for i in range(s_x)] print(points) list_ids = [] draw_table() class Point: def __init__(self, x, y, type): self.x = x self.y = y self.type = type def __str__(self): return str(self.__class__) + «: « + str(self.__dict__) def draw_point(x, y, type): size = 25 color = «black» id = 0 if type == 0: color = «red» id = canvas.create_oval(x * step_x, y * step_y, x * step_x + step_x, y * step_y + step_y, fill=color) id2 = canvas.create_oval(x * step_x + size, y * step_y + size, x * step_x + step_x size, y * step_y + step_y size, fill=«white») list_ids.append(id) list_ids.append(id2) if type == 1: color = «blue» id = canvas.create_rectangle(x * step_x, y * step_y+ step_y//2step_y//10, x * step_x+step_x, y * step_y + step_y//2+step_y//10, fill=color) id2 = canvas.create_rectangle(x * step_x+ step_x // 2 step_x // 10, y * step_y, x * step_x+ step_x // 2 + step_x // 10, y * step_y + step_y, fill=color) list_ids.append(id) list_ids.append(id2) print(type) #id = canvas.create_oval(x*step_x, y*step_y, x*step_x+step_x, y*step_y+step_y, fill=color) def add_to_points(event): #print(event.num, event.x, event.y) global points type = 0 if event.num == 3: type = 1 if points[event.x // step_x][event.y // step_y] == 1: points[event.x // step_x][event.y // step_y] = type draw_point(event.x // step_x, event.y // step_y, type) if check_winner(type): print(«Победитель», type) points = [[10 for i in range(s_x)] for i in range(s_x)] #print(» «.join(map(str, points))) canvas.bind_all(«<Button-1>», add_to_points) # ЛКМ canvas.bind_all(«<Button-3>», add_to_points) # ПКМ def button_press(): global list_ids global points print(list_ids) for i in list_ids: canvas.delete(i) list_ids = [] print(list_ids) points = [[1 for i in range(s_x)] for i in range(s_x)] b1 = Button(tk, text=«Начать заново!», command=button_press) b1.pack() def check_winner(who): for j in range(0,s_y): win = True for i in range(0,s_x): if points[j][i] != who: win = False if win: return True for j in range(0,s_y): win = True for i in range(0,s_x): if points[i][j] != who: win = False if win: return True win = True for i in range(0,s_y): print(points[i][i]) if points[i][i] != who: win = False if win: return True while app_running: if app_running: tk.update_idletasks() tk.update() time.sleep(0.005)

Понравилась статья? Поделить с друзьями:
  • Как написать игру крестики нолики на python
  • Как написать игру кликер на python
  • Как написать игру змейку на python
  • Как написать игру змейка на python
  • Как написать игру дома