Главная страница
Навигация по странице:

  • 2 + 2 4>>> Это строковое значение. Это строковое значение.>>> None

  • Создание искусственного интеллекта

  • Проверка — сможет ли компьютер победить, сделав ход

  • Проверка — сможет ли игрок победить, сделав ход

  • Проверка угловых, центральной и боковых клеток (в порядке очереди)

  • Проверка — заполнено ли поле

  • Выбор буквы игрока и того, кто будет ходить первым

  • Переменная turn в значении Человек

  • Переменная turn в значении Компьютер

  • Предложение игроку сыграть заново

  • В ЭТОЙ ГЛАВЕ РАССМАТРИВАЮТСЯ СЛЕДУЮЩИЕ ТЕМЫ

  • Учим Python, делая крутые игры 2018. Invent your owncomputer gameswith python


    Скачать 6.56 Mb.
    НазваниеInvent your owncomputer gameswith python
    Дата10.12.2022
    Размер6.56 Mb.
    Формат файлаpdf
    Имя файлаУчим Python, делая крутые игры 2018.pdf
    ТипДокументы
    #837554
    страница18 из 39
    1   ...   14   15   16   17   18   19   20   21   ...   39
    Значение None
    Значение None представляет собой отсутствие значения. None — един- ственное значение типа данных NoneType. Это значение можно использовать, когда необходимо получить ответ типа «не существует» или «ни один из чис- ла, перечисленных выше».
    Например, в переменной с именем quizAnswer хранится ответ пользовате- ля на какой-нибудь вопрос популярной викторины в формате истина/ложь.
    То есть переменная возвращает значение True или False, оценивая ответ поль- зователя. Но если пользователь не отвечает на вопрос, значение True/False использовать нельзя, так как это означало бы ответ пользователя. Вместо это- го переменной quizAnswer можно присвоить значение None, если пользователь пропускает ответ.
    Необходимо отметить, что значение None не выводится в интерактивной оболочке, подобно другим значениям.
    >>>
    2 + 2
    4
    >>>
    'Это строковое значение.'
    'Это строковое значение.'
    >>>
    None
    >>>
    Значения первых двух выражений выводятся на экран в последующих строках, но None не имеет значения, поэтому не выводится ничего.

    184
    Глава 10
    Функция, которая, как кажется, не имеет возвращаемого значения, воз- вращает значение None. Например, print() возвращает значение None.
    >>>
    spam = print('Привет, мир!')
    Привет, мир!
    >>>
    spam == None
    True
    Здесь мы присваиваем переменной spam значение print('Привет, мир!').
    Подобно другим функциям, функция print() возвращает значение. Несмотря на то что print() — функция вывода на экран, при вызове она возвращает значение None. IDLE не показывает значение None в интерактивной оболочке, но можно сказать, что spam присвоено значение None, потому что выражение spam == None истинно.
    Создание искусственного интеллекта
    Код ИИ содержится в теле функции getComputerMove().
    83. def getComputerMove(board, computerLetter):
    84. # Учитывая заполнение игрового поля и букву компьютера, определяет допустимый ход и возвращает его.
    85. if computerLetter == 'Х':
    86. playerLetter = 'О'
    87. else:
    88. playerLetter = 'Х'
    Первый аргумент, переменная board, — это параметры игрового поля игры
    «Крестики-нолики». Второй аргумент, переменная letter, — это буква ком- пьютера — 'X' или 'O', которая хранится в переменной computerLetter. Первые несколько строк просто присваивают другую букву переменной playerLetter.
    Код один и тот же, присвоены компьютеру буквы «Х» или «О».
    Напомню, как работает алгоритм искусственного интеллекта игры
    «Крестики-нолики»:
    1. Проверить, существует ли ход, сделав который, компьютер победит.
    Если существует, сделать его. В противном случае перейти к шагу 2.
    2. Проверить, существует ли ход, сделав который, победит игрок. Если существует, блокировать его. В противном случае перейти к шагу 3.
    3. Проверить, свободна ли одна из угловых клеток (под номером 1, 3, 7 или 9). Если да, то сделать ход в эту клетку. Если нет свободных угло- вых клеток, перейти к шагу 4.

    Игра «Крестики-нолики»
    185
    4. Проверить, свободен ли центр. Если свободен, занять его. Если нет, перейти к шагу 5.
    5. Сделать ход на одну из боковых клеток (под номером 2, 4, 6 или 8).
    Если этот шаг выполнен, возможных ходов больше нет.
    Функция возвращает целочисленные значения в диапазоне от 1 до 9, представляющие собой ходы компьютера. Давайте посмотрим, как каждый из этих шагов реализуется в коде программы.
    Проверка — сможет ли компьютер победить, сделав ход
    Прежде всего, если компьютер может победить, сделав следующий ход, его надо сделать немедленно.
    90. # Это алгоритм для ИИ "Игры «Крестики-Нолики»":
    91. # Сначала проверяем — победим ли мы, сделав следующий ход.
    92. for i in range(1, 10):
    93. boardCopy = getBoardCopy(board)
    94. if isSpaceFree(boardCopy, i):
    95. makeMove(boardCopy, computerLetter, i)
    96. if isWinner(boardCopy, computerLetter):
    97. return i
    Цикл for, который начинается в строке 92, перебирает все возможные значения ходов от 1 до 9. Код внутри цикла имитирует ситуацию, которая возникнет, если компьютер сделает этот ход.
    Код в первой строке в цикле (строка 93) создает копию списка board. Та- ким образом, внутри цикла имитируется ход, не изменяя реальных значений игрового поля «Крестики-нолики», которые хранятся в переменной board.
    Функция getBoardCopy() возвращает другой список, хотя и идентичный спи- ску board.
    Код в строке 93 проверяет, свободна ли требуемая клетка, и делает ход в копии board. Если в результате компьютер побеждает, функция возвращает этот ход в виде целого значения.
    Если нет клеток, приводящих к победе, цикл завершается, и выполнение программы продолжается со строки 100.
    Проверка — сможет ли игрок победить, сделав ход
    Затем для каждой клетки код имитирует ход человека.
    99. # Проверяем — победит ли игрок, сделав следующий ход, и блокируем его.
    100. for i in range(1, 10):

    186
    Глава 10 101. boardCopy = getBoardCopy(board)
    102. if isSpaceFree(boardCopy, i):
    103. makeMove(boardCopy, playerLetter, i)
    104. if isWinner(boardCopy, playerLetter):
    105. return i
    Код такой же, как в цикле со строки 92, исключая букву игрока, поме- щенную в копию board. Если функция isWinner() показывает, что игрок может победить в следующем ходу, компьютер блокирует этот ход, чтобы этого не допустить. Если в следующем ходу победа игрока невозможна, цикл for за- вершается, и выполнение продолжается со строки 108.
    Проверка угловых, центральной и боковых клеток
    (в порядке очереди)
    Если компьютер не может сделать победный ход и нет необходимости блокировать ход игрока, ход совершается в угловую, центральную или боко- вую клетку, в зависимости от того, какие из них свободны.
    Сначала компьютер пытается сделать ход в одну из угловых клеток.
    107. # Пробуем занять один из углов, если есть свободные.
    108. move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
    109. if move != None:
    110. return move
    Вызов функции chooseRandomMoveFromList() со списком [1, 3, 7, 9] гаран- тирует, что функция вернет целочисленное значение угловой клетки: 1, 3, 7 или 9. Если все угловые клетки заняты, функция chooseRandomMoveFromList() возвращает значение None, и программа переходит к строке 113.
    112. # Пробуем занять центр, если он свободен.
    113. if isSpaceFree(board, 5):
    114. return 5
    Если нет свободных угловых клеток, код в строке 114 совершает ход в центр, если он свободен. Если центр занят, выполняется код в строке 117.
    116. # Делаем ход по одной стороне.
    117. return chooseRandomMoveFromList(board, [2, 4, 6, 8])

    Игра «Крестики-нолики»
    187
    Этот код тоже вызывает функцию chooseRandomMoveFromList(), только ей передается список [2, 4, 6, 8]. Эта функция не возвращает значения None, потому что боковые клетки — последние из возможных. На этом заканчива- ется выполнение функции getComputerMove() и алгоритма ИИ.
    Проверка — заполнено ли поле
    И последняя функция — isBoardFull().
    119. def isBoardFull(board):
    120. # Возвращает True, если клетка на игровом поле занята. В противном случае, возвращает
    False.
    121. for i in range(1, 10):
    122. if isSpaceFree(board, i):
    123. return False
    124. return True
    Эта функция возвращает True, если в переменную board для элементов всех индексов (исключая индекс 0, который просто игнорируется) в качестве аргументов переданы буквы 'X' или 'O'. Цикл for позволяет проверить все индексы списка board, от 1 до 9. Как только в списке board будет найдена сво- бодная клетка (когда isSpaceFree(board, i) вернет True), функция isBoardFull() вернет False.
    Если произведены все итерации цикла, значит, свободных клеток не оста- лось. Строка 124 вернет значение True.
    Игровой цикл
    Строка 127 — первая, которая не принадлежит коду функций, то есть это первая исполняемая строка программы.
    127. print('Игра "Крестики-нолики"')
    Эта строка приветствия перед началом игры. Затем программа переходит к выполнению цикла while в строке 129.
    129. while True:
    130. # Перезагрузка игрового поля
    131. theBoard = [' '] * 10

    188
    Глава 10
    Цикл while выполняется до тех пор, пока управление не будет передано инструкции break. Код в строке 131 сохраняет основное игровое поле игры
    «Крестики-нолики» в переменной theBoard.
    Сначала выводится пустое игровое поле, представленное списком из 10 пустых строк. Вместо того чтобы вводить этот список целиком, строка 131 использует репликацию списка. Проще ввести [' '] * 10, чем [' ', ' ', ' ',
    ' ', ' ', ' ', ' ', ' ', ' ', ' ']
    Выбор буквы игрока и того, кто будет ходить первым
    Далее функция inputPlayerLetter() предлагает игроку ввести букву, кото- рую он выбирает, «Х» или «О» .
    132. playerLetter, computerLetter = inputPlayerLetter()
    Функция возвращает список из двух элементов, ['X', 'O'] или ['O', 'X'].
    Операцией множественного присваивания переменной playerLetter присва- ивается значение первого элемента, а переменной computerLetter — второго.
    Затем функция whoGoesFirst() случайным образом выбирает, кому при- надлежит первый ход, возвращая строку 'Человек' или 'Компьютер', и в стро- ке 137 сообщает игроку о своем выборе.
    133. turn = whoGoesFirst()
    134. print('' + turn + ' ходит первым.')
    135. gameIsPlaying = True
    Переменная gameIsPlaying хранит информацию о состоянии сеанса игры — продолжается ли игра, или победил один из участников, или вышла ничья.
    Переменная turn в значении 'Человек'
    Цикл в строке 137 будет метаться между кодом хода игрока и кодом хода компьютера до тех пор, пока переменной gameIsPlaying присвоено значение True.
    137. while gameIsPlaying:
    138. if turn == 'Человек':
    139. # Ход игрока.
    140. drawBoard(theBoard)
    141. move = getPlayerMove(theBoard)
    142. makeMove(theBoard, playerLetter, move)

    Игра «Крестики-нолики»
    189
    Переменной turn уже было присвоено значение 'Человек' или 'Компьютер' при вызове функции whoGoesFirst() в строке 133. Если turn присвоено значе- ние 'Компьютер', то условие в строке 138 ложно и управление переходит к коду в строке 156.
    Но если условие этой строки истинно, код в строке 140 вызывает функ- цию drawBoard() и передает значение переменной theBoard для вывода на экран в игровом поле Игры «Крестики-нолики». Затем функция getPlayerMove() предлагает игроку сделать ход и проверяет его допустимость. Функция makeMove()
    добавляет в переменную theBoard букву игрока «Х» или «О».
    После совершения игроком хода программа должна проверить, привел ли этот ход к победе.
    144. if isWinner(theBoard, playerLetter):
    145. drawBoard(theBoard)
    146. print('Ура! Вы выиграли!')
    147. gameIsPlaying = False
    Если функция isWinner() возвращает значение True, код из блока if выво- дит на экран сообщение о победе игрока. Значение переменной gameIsPlaying становится равным False, и перехода к совершению хода компьютером не происходит. Если игрок не побеждает при последнем своем ходе, то, может быть, поле заполнено с результатом — ничья. Эта вероятность проверяется в инструкции else.
    148. else:
    149. if isBoardFull(theBoard):
    150. drawBoard(theBoard)
    151. print('Ничья!')
    152. break
    В блоке else функция isBoardFull() возвращает значение True, если боль- ше нет возможных ходов. В этом случае код из блока if в строке 149 выводит панель с сообщением игроку о ничьей. Программа выходит из цикла while и переходит к строке 173.
    Если не произошла ни победа игрока, ни ничья, программа переходит к следующей инструкции else.
    153. else:
    154. turn = 'Компьютер'

    190
    Глава 10
    В строке 154 переменной turn присваивается значение 'Компьютер' и в следу- ющей итерации программа выполняет код, который совершает ход компьютера.
    Переменная turn в значении 'Компьютер'
    Если в условии строки 138 значение переменной turn не равно 'Человек', значит, оно должно быть равно 'Компьютер'. Код в этом блоке else такой же, как и для переменной turn в значении 'Человек'.
    156. else:
    157. # Ход компьютера.
    158. move = getComputerMove(theBoard, computerLetter)
    159. makeMove(theBoard, computerLetter, move)
    160.
    161. if isWinner(theBoard, computerLetter):
    162. drawBoard(theBoard)
    163. print('Компьютер победил! Вы проиграли.')
    164. gameIsPlaying = False
    165. else:
    166. if isBoardFull(theBoard):
    167. drawBoard(theBoard)
    168. print('Ничья!')
    169. break
    170. else:
    171. turn = 'Человек'
    Строки 157–171 почти идентичны строкам 139–154. Единственное от- личие в том, что используется буква компьютера и вызывается функция getComputerMove()
    Если нет победителя или ничьей, код в строке 171 присваивает перемен- ной turn значение 'Человек'. В этом цикле while больше нет строк, поэтому управление передается инструкции while в строке 137.
    Предложение игроку сыграть заново
    В финале игры программа спрашивает игрока, хочет ли он сыграть еще раз.
    173. print('Сыграем еще раз? (да или нет)')
    174. if not input().lower().startswith('д'):
    175. break

    Код в строках 173–175 выполняется сразу после старта цикла в строке 137.
    Переменной gameIsPlaying присваивается значение False, когда завершается игра. В этот момент программа спрашивает игрока, не хочет ли он сыграть еще раз.
    Выражение not input().lower().startswith('д') принимает значение True, если игрок введет какую-либо строку, не начинающуюся с буквы 'д'. В этом случае будет выполнена инструкция break. Эта инструкция прерывает вы- полнение цикла while, который был запущен кодом в строке 129. Но так как в программе больше нет строк для выполнения, происходит выход из про- граммы и завершение игры.
    Заключение
    Создание программы с искусственным интеллектом сводится к тщатель- ному рассмотрению всех возможных ситуаций, с которыми он может стол- кнуться, и вариантов его реакции на каждую из этих ситуаций. Искусствен- ный интеллект игры «Крестики-нолики» прост, потому что в игре немного возможных ходов, по сравнению, скажем, с шахматами или шашками.
    Сначала наш компьютерный ИИ проверяет, есть ли у него победный ход.
    Затем проверяет необходимость блокировки ходов игрока. Далее ИИ просто выбирает свободную угловую клетку, потом центральную, а затем боковую.
    Это простой алгоритм для совершения хода.
    Ключ к реализации ИИ заключается в создании копии данных игрового поля и моделирования ходов в этой копии. Таким образом, ИИ может видеть, приведет ли ход к победе или поражению. Затем ИИ совершает ход в реаль- ном поле. Этот тип моделирования эффективен при прогнозировании ре- зультатов предложенного хода.

    192
    Глава 11
    11
    ДЕДУКТИВНАЯ ИГРА «ХОЛОДНО-ГОРЯЧО»
    «Холодно-горячо» — это дедуктивная игра, в которой игрок пытается угадать случайное трехзначное число (без по- вторяющихся цифр), сгенерированное компьютером. После каждой попытки компьютер предоставляет игроку подсказ- ки трех типов:

    Холодно. Ни одна цифра не отгадана.

    Тепло. Одна цифра отгадана, но не отгадана ее позиция.

    Горячо. Одна цифра и ее позиция отгаданы.
    Компьютер может дать несколько подсказок, сортируемых в алфавитном порядке. Если секретное число 456, а предположение игрока — 546, подсказ- ки будут иметь вид «Горячо Тепло Тепло». Подсказка «Горячо» относится к 6, а «Тепло Тепло» — к 4 и 5.
    В этой главе вы изучите несколько новых методов и функций, доступных в Python. Вы также узнаете о расширенных операторах присваивания и ин- терполяции строк. Хотя эти возможности и не позволяют делать ничего прин- ципиально нового, это хороший способ сэкономить время, упрощая код.
    В ЭТОЙ ГЛАВЕ РАССМАТРИВАЮТСЯ СЛЕДУЮЩИЕ ТЕМЫ:
    • Функция random.shuffle()
    • Расширенные операторы присваивания, +=, -=, *= и /=
    • Метод списка sort()
    • Строковый метод join()
    • Интерполяция строк
    • Спецификатор преобразования
    %s
    • Вложенные циклы

    Дедуктивная игра «Холодно-горячо»
    193
    Пример запуска игры «Холодно-горячо»
    Вот что видит пользователь, когда запускается программа «Холодно- горячо» . Текст, который вводит игрок, выделен полужирным шрифтом.
    Я загадаю 3-х значное число, которое вы должны отгадать.
    Я дам несколько подсказок...
    Когда я говорю: Это означает:
    Холодно Ни одна цифра не отгадана.
    Тепло Одна цифра отгадана, но не отгадана ее позиция.
    Горячо Одна цифра и ее позиция отгаданы.
    Итак, я загадал число. У вас есть 10 попыток, чтобы отгадать его.
    Попытка №1:
    123
    Тепло
    Попытка №2:
    245
    Тепло
    Попытка №3:
    672
    Горячо Горячо
    Попытка №4:
    682
    Горячо Горячо
    Попытка №5:
    692
    Вы угадали!
    Хотите сыграть еще раз? (да или нет)
    нет
    Исходный код игры «Холодно-горячо»
    В редакторе файлов создайте новый файл, вы- брав команду меню File
    New File (Файл ⇒ Новый файл). В открывшемся окне введите приведенный ниже исходный код и сохраните файл под именем
    bagels.py. Затем нажмите клавишу F5 и запусти- те программу. Если при выполнении программы возникают ошибки, сравните код, который вы на- брали, с оригинальным кодом с помощью онлайн- инструмента на сайте inventwithpython.com/diff/.
    Make sure you’re using Python 3, not Python 2!
    УБЕ ДИТЕСЬ,
    ЧТО ИСПО ЛЬЗУЕТЕ
    PY THON 3,
    А НЕ PY THON 2!

    194
    Глава 11
    bagels.py
    1. import random
    2.
    3. NUM_DIGITS = 3 4. MAX_GUESS = 10 5.
    6. def getSecretNum():
    7. # Возвращает строку уникальных случайных цифр, длина которой составляет NUM_DIGITS.
    8. numbers = list(range(10))
    9. random.shuffle(numbers)
    10. secretNum = ''
    11. for i in range(NUM_DIGITS):
    12. secretNum += str(numbers[i])
    13. return secretNum
    14.
    15. def getClues(guess, secretNum):
    16. # Возвращает строку с подсказками пользователю "Тепло", "Горячо" и "Холодно".
    17. if guess == secretNum:
    18. return 'Вы угадали!'
    19.
    20. clues = []
    21. for i in range(len(guess)):
    22. if guess[i] == secretNum[i]:
    23. clues.append('Горячо')
    24. elif guess[i] in secretNum:
    25. clues.append('Тепло')
    26. if len(clues) == 0:
    27. return 'Холодно'
    28.
    29. clues.sort()
    30. return ' '.join(clues)
    31.
    32. def isOnlyDigits(num):
    33. # Возвращает значение True, если num - строка, состоящая только из цифр. В противном случае возвращает False.
    34. if num == '':
    35. return False
    36.
    37. for i in num:
    38. if i not in '0 1 2 3 4 5 6 7 8 9'.split():

    Дедуктивная игра «Холодно-горячо»
    1   ...   14   15   16   17   18   19   20   21   ...   39


    написать администратору сайта