На этом шаге мы рассмотрим основные моменты создания указанного приложения.
В редакторе форм создадим диалоговое окно Крестики — нолики (рисунок 1).
Рис.1. Диалоговое окно Крестики — нолики в редакторе форм
Поле игры будут образовывать девять элементов управления Caption (Надпись). Для видимости границ элементов управления Caption установите свойство BorderStyle равным fmBorderStyleSingle.
В данной игре запрограммируем только более сложную для компьютера ситуацию, когда первым ходит игрок. В этой ситуации компьютеру надо умело обороняться, создавая ситуации для внезапных атак. Играющему первым игроку достаточно все время атаковать, поэтому его стратегия для программирования более легкая. Общий случай, когда в параметрах игры устанавливается, кто ходит первым компьютер или человек, будет оставлен в качестве хорошего самостоятельного задания.
Итак, в нашей игре первый ход за пользователем. Ход осуществляется двойным щелчком по игровому полю. Если игровое поле пусто, то в нем отображается крестик. Компьютер мгновенно отвечает на ход игрока, постановкой нолика в другое игровое поле и т. д. О результате игры компьютер информирует пользователя. При желании сыграть еще одну игру с компьютером, нажмите кнопку Переиграть, которая очистит игровые поля. На рисунке 2 приведен вид партии в Крестики — нолики после второго шага игры.
Рис.2. Пример партии игры в Крестики — нолики после второго шага игры
Крестик и нолик, которые выводятся на игровом поле, содержатся в файлах cross.bmp и ou.bmp, а их образы можно создать при помощи любого графического редактора.
В связи с небольшим числом возможных стратегий в этой игре, составляя программу можно пойти по пути наименьшего сопротивления: а именно, применить подход простого перебора вариантов возможных действий. Если бы в игре было большое число стратегий, то этот подход был бы неприменим, т.к. программа не смогла бы играть в режиме реального времени.
Стратегия компьютера в игре Крестики — нолики очень проста:
Обсудим, как приведенная ниже программа решает описанную задачу и что в ней происходит.
Если нет, то компьютер делает свой ответный ход. Проверяет, привел ли ход компьютера к его победе, если да, то выдается соответствующее сообщение (рисунок 1) и игра завершается.
Рис.3. Пример сообщения о результате игры
Приведем полный текст приложения.
' Переменные уровня модуля Dim Поле(1 To 3, 1 To 3) As Object Dim Статус(1 To 3, 1 To 3) As Integer Dim k As Integer Dim i As Integer Dim j As Integer Dim Su(0 To 4, 0 To 4) As Integer Private Sub CommandButton1_Click() ' Процедура переигрывания НачальноеСостояние End Sub Private Sub CommandButton2_Click() ' Закрытие диалогового окна UserForm1.Hide End Sub Private Sub Label1_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(1, 1) = 0 Then Поле(1, 1).Picture = LoadPicture("cross.bmp") Статус(1, 1) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label2_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(1, 2) = 0 Then Поле(1, 2).Picture = LoadPicture("cross.bmp") Статус(1, 2) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label3_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(1, 3) = 0 Then Поле(1, 3).Picture = LoadPicture("cross.bmp") Статус(1, 3) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label4_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(2, 1) = 0 Then Поле(2, 1).Picture = LoadPicture("cross.bmp") Статус(2, 1) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label5_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(2, 2) = 0 Then Поле(2, 2).Picture = LoadPicture("cross.bmp") Статус(2, 2) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label6_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(2, 3) = 0 Then Поле(2, 3).Picture = LoadPicture("cross.bmp") Статус(2, 3) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label7_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(3, 1) = 0 Then Поле(3, 1).Picture = LoadPicture("cross.bmp") Статус(3, 1) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label8_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(3, 2) = 0 Then Поле(3, 2).Picture = LoadPicture("cross.bmp") Статус(3, 2) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Private Sub Label9_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Dim Inf As Boolean If Статус(3, 3) = 0 Then Поле(3, 3).Picture = LoadPicture("cross.bmp") Статус(3, 3) = 1 k = k + 1 Проверка Inf If Inf = True Then Exit Sub Strategy Проверка Inf If Inf = True Then Exit Sub End If End Sub Sub UserForm_Initialize() Set Поле(1, 1) = Label1 Set Поле(1, 2) = Label2 Set Поле(1, 3) = Label3 Set Поле(2, 1) = Label4 Set Поле(2, 2) = Label5 Set Поле(2, 3) = Label6 Set Поле(3, 1) = Label7 Set Поле(3, 2) = Label8 Set Поле(3, 3) = Label9 НачальноеСостояние End Sub Sub Strategy() Dim flag As Boolean ' Стратегия первого хода If k = 1 Then Strategy_1 Exit Sub End If If k = 2 And Su(0, 0) = 12 And Статус(2, 2) = 1 Then Поле(1, 3).Picture = LoadPicture("ou.bmp") Статус(1, 3) = 10 Exit Sub End If If k = 2 And Статус(2, 2) = 10 And (Su(0, 0) = 12 Or Su(0, 4) = 12) Then Поле(1, 2).Picture = LoadPicture("ou.bmp") Статус(1, 2) = 10 Exit Sub End If If k = 2 And Статус(2, 2) = 10 And Su(0, 0) = 11 And _ (Статус(3, 2) = 1 Or Статус(2, 1) = 1) Then Поле(3, 1).Picture = LoadPicture("ou.bmp") Статус(3, 1) = 10 Exit Sub End If Состояние Диагональ1 20, 10, flag If flag = True Then Exit Sub Диагональ2 20, 10, flag If flag = True Then Exit Sub For j = 1 To 3 Бок 20, 10, j, flag If flag = True Then Exit Sub Next j For i = 1 To 3 Верх 20, 10, i, flag If flag = True Then Exit Sub Next i Диагональ1 2, 10, flag If flag = True Then Exit Sub Диагональ2 2, 10, flag If flag = True Then Exit Sub For j = 1 To 3 Бок 2, 10, j, flag If flag = True Then Exit Sub Next j For i = 1 To 3 Верх 2, 10, i, flag If flag = True Then Exit Sub Next i Диагональ1 10, 10, flag If flag = True Then Exit Sub Диагональ2 10, 10, flag If flag = True Then Exit Sub For j = 1 To 3 Бок 10, 10, j, flag If flag = True Then Exit Sub Next j For i = 1 To 3 Верх 10, 10, i, flag If flag = True Then Exit Sub Next i For i = 1 To 3 For j = 1 To 3 If Статус(i, j) = 0 Then Поле(i, j).Picture = LoadPicture("ou.bmp") Статус(i, j) = 10 Exit Sub End If Next j Next i End Sub Sub Strategy_1() If Статус(2, 2) = 0 Then Поле(2, 2).Picture = LoadPicture("ou.bmp") Статус(2, 2) = 10 Else Поле(1, 1).Picture = LoadPicture("ou.bmp") Статус(1, 1) = 10 End If End Sub Sub Проверка(ByRef Inf As Boolean) ' Процедура проверяет, не выиграл ли кто-то ' Если аргумент Inf равен True, то выигравший есть ' Если аргумент Inf равен False, то пока выигравшего нет Inf = False Состояние If Su(0, 0) = 3 Or Su(0, 0) = 30 Then Сообщение Su(0, 0) Inf = True Exit Sub End If If Su(0, 4) = 3 Or Su(0, 4) = 30 Then Сообщение Su(0, 4) Inf = True Exit Sub End If For j = 1 To 3 If Su(0, j) = 3 Or Su(0, j) = 30 Then Сообщение Su(0, j) Inf = True Exit Sub End If Next j For i = 1 To 3 If Su(i, 0) = 3 Or Su(i, 0) = 30 Then Сообщение Su(i, 0) Inf = True Exit Sub End If Next i ' Проверка, не завершилась ли игра For i = 1 To 3 For j = 1 To 3 If Статус(i, j) = 0 Then Exit Sub Next j Next i MsgBox "Пока фифти-фифти", vbExclamation, "Крестики-Нолики" Inf = True End Sub Sub Сообщение(Inf As Integer) ' Возможные сообщения о победителе ' Если Inf=3, то поздравления принимает игрок ' Если Inf=30, то поздравления принимает компьютер If Inf = 3 Then MsgBox "Поздравляю с выигрышем", vbExclamation, "Крестики-Нолики" Exit Sub End If If Inf = 30 Then MsgBox "Компьютер пока сильнее", vbExclamation, "Крестики-Нолики" Exit Sub End If End Sub Sub НачальноеСостояние() ' Обнуление данных и очистка картинок For i = 1 To 3 For j = 1 To 3 Поле(i, j).Caption = "" Поле(i, j).Picture = LoadPicture("") Поле(i, j).BorderStyle = fmBorderStyleSingle Статус(i, j) = 0 Next j Next i k = 0 For i = 0 To 4 For j = 0 To 4 Su(i, j) = 0 Next j Next i End Sub Sub Состояние() Su(0, 0) = 0 For i = 1 To 3 Su(0, 0) = Su(0, 0) + Статус(i, i) Next i Su(0, 4) = 0 For i = 1 To 3 Su(0, 4) = Su(0, 4) + Статус(i, 4 - i) Next i For j = 1 To 3 Su(0, j) = 0 For i = 1 To 3 Su(0, j) = Su(0, j) + Статус(i, j) Next i Next j For i = 1 To 3 Su(i, 0) = 0 For j = 1 To 3 Su(i, 0) = Su(i, 0) + Статус(i, j) Next j Next i End Sub Sub Диагональ1(ByRef p, ByRef q, ByRef flag As Boolean) flag = False If Su(0, 0) = p Then For i = 1 To 3 If Статус(i, i) = 0 Then Поле(i, i).Picture = LoadPicture("ou.bmp") Статус(i, i) = q flag = True Exit Sub End If Next i End If End Sub Sub Диагональ2(ByRef p, ByRef q, ByRef flag As Boolean) flag = False If Su(0, 4) = p Then For i = 1 To 3 If Статус(i, 4 - i) = 0 Then Поле(i, 4 - i).Picture = LoadPicture("ou.bmp") Статус(i, 4 - i) = q flag = True Exit Sub End If Next i End If End Sub Sub Бок(ByRef p, ByRef q, ByRef j, ByRef flag As Boolean) flag = False If Su(0, j) = p Then For i = 1 To 3 If Статус(i, j) = 0 Then Поле(i, j).Picture = LoadPicture("ou.bmp") Статус(i, j) = q flag = True Exit Sub End If Next i End If End Sub Sub Верх(ByRef p, ByRef q, ByRef i, ByRef flag As Boolean) flag = False If Su(i, 0) = p Then For j = 1 To 3 If Статус(i, j) = 0 Then Поле(i, j).Picture = LoadPicture("ou.bmp") Статус(i, j) = q flag = True Exit Sub End If Next j End If End Sub
На следующем шаге мы продолжим разработку приложений.