Читать «Программирование на Python. Том 1» онлайн - страница 648

Марк Лутц

PP4E\Ai\TieTaeToe\tietaetoe.py

Сценарий оболочки верхнего уровня PP4E\Ai\TieTaeToe\tietaetoe_lists.py Основная реализация

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

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

def clearBoard(self):

for row, col in self.label.keys(): self.board[row][col] = Empty self.label[(row, col)].config(text=’ ‘)

Аналогично выбор хода, по крайней мере, в случайном режиме, заключается в том, чтобы найти пустую ячейку в массиве, представляющем игровое поле, и записать метку компьютера в нее и передать в графический интерфейс (атрибут degree хранит размер игрового поля):

def machineMove(self):

row, col = self.pickMove() self.board[row][col] = self.machineMark self.label[(row, col)].config(text=self.machineMark)

def pickMove(self): empties = [] for row in self.degree: for col in self.degree:

if self.board[row][col] == Empty: empties.append((row, col)) return random.choice(empties)

Наконец, проверка состояния конца игры сводится к просмотру строк, колонок и диагоналей по следующей схеме:

def checkDraw(self, board=None): board = board or self.board for row in board: if Empty in row: return 0

return 1    # не пусто: ничья или победа

def checkWin(self, mark, board=None): board = board or self.board for row in board:

if row.count(mark) == self.degree: # проверка горизонтали return 1

for col in range(self.degree):

for row in board:    # проверка вертикали

if row[col] != mark: break else:

return 1

for row in range(self.degree):    # проверка первой диагонали

col = row # row == col

if board[row][col] != mark: break else:

return 1

for row in range(self.degree):    # проверка второй диагонали

col = (self.degree-1) - row    # row+col = degree-1

if board[row][col] != mark: break else:

return 1

def checkFinish(self):

if self.checkWin(self.userMark): outcome = "You’ve won!” elif self.checkWin(self.machineMark): outcome = ‘I win again :-)’ elif self.checkDraw():

outcome = ‘Looks like a draw’

Другой программный код, связанный с выбором хода, в основном просто проводит другие виды анализа структуры данных игрового поля или генерирует новые состояния для поиска в дереве ходов и контрхо-дов.

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