RSS    

   Реферат: VB, MS Access, VC++, Delphi, Builder C++ принципы(технология), алгоритмы программирования

@Рис. 8.1. Фрагмент дерева игры в крестики‑нолики

========188

@Рис. 8.2. Быстрое окончание игры

Минимаксный поиск

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

Для каждого игрока, можно присвоить позиции один из четырех весов. Если вес равен 4, то это значит, что игрок в этой позиции выигрывает. Если вес равен 3, то из текущего положения на доске неясно, кто из игроков выиграет в конце концов. Вес, равный 2, означает, что позиция приводит к ничьей. И, наконец, вес, равный 1, означает, что выигрывает противник.

Для поиска дерева методом полного перебора можно использовать минимаксную (minimax) стратегию, при которой делается попытка минимизировать максимальный вес, который может иметь позиция для противника после следующего хода. Это можно сделать, определив максимально возможный вес позиции для противника после каждого из своих возможных ходов, и затем выбрав ход, который дает позицию с минимальным весом для противника.

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

Для определения веса позиции на доске процедура BoardValue рекурсивно вызывает себя до тех пор, пока не произойдет одно из трех событий. Во‑первых, она может дойти до позиции, в которой игрок выигрывает. В этом случае, она присваивает позиции вес 4, что указывает на выигрыш игрока, совершившего последний ход.

======189

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

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

На рис. 8.3 показано дерево игры в крестики‑нолики в конце партии. Ходит игрок, играющий крестиками, и у него есть три возможных хода. Чтобы выбрать наилучший ход, процедура BoardValue рекурсивно проверяет каждый из трех возможных ходов. Первый и третий возможные ходы (левая и правая ветви дерева) приводят к выигрышу противника, поэтому их вес для противника равен 4. Второй возможный ход приводит к ничьей, и его вес для противника равен 2. Процедура BoardValue выбирает этот ход, так как он имеет наименьший вес для противника.

@Рис. 8.3. Нижняя часть дерева игры

Private Sub BoardValue(best_move As Integer, best_value As Integer, pl1 As Integer, pl2 As Integer, Depth As Integer)

Dim pl As Integer

Dim i As Integer

Dim good_i As Integer

Dim good_value As Integer

Dim enemy_i As Integer

Dim enemy_value As Integer

    DoEvents       ' Не занимать 100% процессорного времени.

    ' Если глубина рекурсии слишком велика, результат неизвестен.

    If Depth >= SkillLevel Then

        best_value = VALUE_UNKNOWN

        Exit Sub

    End If

    ' Если игра завершается, то результат известен.

    pl = Winner()

    If pl <> PLAYER_NONE Then

        ' Преобразовать вес для победителя pl в вес для игрока pl1.

        If pl = pl1 Then

           best_value = VALUE_WIN

        ElseIf pl = pl2 Then

           best_value = VALUE_LOSE

        Else

           best_value = VALUE_DRAW

        End If

        Exit Sub

    End If

    ' Проверить все допустимые ходы.

    good_i = -1

    good_value = VALUE_HIGH

    For i = 1 To NUM_SQUARES

        ' Проверить ход, если он разрешен правилами.

        If Board(i) = PLAYER_NONE Then

           ' Найти вес полученного положения для противника.

           If ShowTrials Then _

               MoveLabel.Caption = _

                   MoveLabel.Caption & Format$(i)

           ' Сделать ход.

           Board(i) = pl1

           BoardValue enemy_i, enemy_value, pl2, pl1, Depth + 1

           ' Отменить ход.

           Board(i) = PLAYER_NONE

           If ShowTrials Then _

               MoveLabel.Caption = _

                   Left$(MoveLabel.Caption, Depth)

           ' Меньше ли этот вес, чем предыдущий.

           If enemy_value < good_value Then

               good_i = i

               good_value = enemy_value

               ' Если мы выигрываем, то лучшего решения нет,

               ' поэтому выбирается этот ход.

               If good_value <= VALUE_LOSE Then Exit For

           End If

        End If     ' End if Board(i) = PLAYER_NONE ...

    Next i

    ' Преобразовать вес позиции для противника в вес для игрока.

    If good_value = VALUE_WIN Then

        ' Противник выигрывает, мы проиграли.

        best_value = VALUE_LOSE

    ElseIf enemy_value = VALUE_LOSE Then

        ' Противник проиграл, мы выиграли.

        best_value = VALUE_WIN

    Else

        ' Вес ничьей или неопределенной позиции

        ' одинаков для обоих игроков.

        best_value = good_value

    End If

    best_move = good_i

End Sub

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

Если не выбрана команда Show Test Moves (Показывать проверяемые ходы) из меню Options (Опции), то производительность программы будет намного выше. Если выбрана эта опция, то программа выводит каждый анализируемый ход. Постоянное обновление экрана занимает намного больше времени, чем действительный поиск в дереве.

Другие команды в меню Options позволяют вам, выбрать уровень мастерства программы (максимальную глубину рекурсии) и выбрать игру крестиками или ноликами. При высоком уровне мастерства первый ход занимает намного больше времени.

=====192

Сдача

Подпрограмма BoardValue имеет интересный побочный эффект. Если она находит два одинаково хороших хода, то она выбирает из них первый попавшийся. Иногда это приводит к странному поведению программы. Например, если программа определяет, что при любом своем ходе она проигрывает, то она выбирает первый из них. Иногда этот ход может показаться человеку глупым. Может создаться впечатление, что компьютер выбрал случайный ход и сдается. В какой то степени это действительно так.

Например, запустим программу TicTac с третьим уровнем мастерства. Перенумеруем клетки так, как показано на рис. 8.4. Сделаем первых ход в клетку 6. Программа выберет клетку 1. Выберем клетку 3, программа ответит ходом на клетку 9. Теперь, если занять клетку 5, то наступает выигрыш, если следующим ходом пойти на клетку 4 или 7.

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

Программа же считает, что противник играет безошибочно и также знает о своем выигрыше. Так как ни один ход не приводит к победе, то программа выбирает первый попавшийся ход, в данном случае занимает клетку 2. Этот ход кажется глупым, так как он не блокирует ни одного из возможных выигрышных ходов, и не делает попытку выиграть на следующем ходу. При этом кажется, что компьютер сдается. Эта игра показана на рис. 8.5.

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

Улучшение поиска в дереве игры

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

@Рис. 8.4. Нумерация клеток доски игры в крестики‑нолики

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82


Новости


Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

                   

Новости

© 2010.