Игра «Пятнашки» (MS Excel, VBA)
Напишем очень простую игру «Пятнашки». Язык - VBA, среда разработки MS Excel.Описание игры: есть поле размером 4х4 ячейки, на котором располагаются фишки с номерами от 1 до 15. Одна ячейка свободна. В начале игры фишки перемешаны случайным образом. Необходимо выстроить их по порядку от 1 до 15. Перемещать фишку можно только на свободное место.
Выделим на листе Excel диапазон из 16 ячеек и присвоим ему имя, например Pole. Сделаем обводку границ и установим жирный шрифт. Роль фишек будут играть числа в ячейках.
Что нам нужно сделать?
Во-первых, создать процедуру перемешивания ячеек.
Во-вторых, создать процедуру хода, то есть передвижения фишки.
В-третьих, наконец, нужна функция проверки на выигрыш, которая будет определять, все ли фишки выстроены в нужном порядке.
Добавим на лист кнопку, назовем BStart и присвоим ей процедуру нажатия (BStart_Click).
В процедуре нужно сначала очистить все ячейки диапазона, затем в цикле получать случайные числа и записывать их в ячейки. Перед занесением нужно проверить, не внесено ли такое число ранее. Поскольку такую проверку нужно выполнять очень часто, то вынесем ее в отдельную функцию. Она будет принимать значение числа и возвращать 1, если такое число уже было, и 0, если оно встречается впервые.
Функция Checking(number)
Function Checking(number As Integer) As IntegerВ цикле перебираем все ячейки диапазона. Если ячейка содержит такое число, то возвращаем 1. Иначе возвращаем 0.
Dim r As Integer, c As Integer
For r = 1 To 4
For c = 1 To 4
If Range("Pole").Cells(r, c).Value = number Then
Checking = 1
Exit Function
End If
Next c
Next r
Checking = 0
End Function
Процедура перемешивания:
Private Sub BStart_Click()Сначала проводим инициализацию счетчика случайных чисел с помощью функции Randomize.
Dim r As Integer, c As Integer, num As Integer
Randomize
For r = 1 To 4
For c = 1 To 4
Range("Pole").Cells(r, c).Value = 100
Next c
Next r
For r = 1 To 4
For c = 1 To 4
num = Int(16 * Rnd)
Do While Checking(num)
num = Int(16 * Rnd)
Loop
Range("Pole").Cells(r, c).Value = num
Next c
Next r
For r = 1 To 4
For c = 1 To 4
If Range("Pole").Cells(r, c).Value = 0 Then
Range("Pole").Cells(r, c).Value = ""
End If
Next c
Next r
End Sub
Затем присваиваем всем ячейкам какое-нибудь число вне диапазона, например, 100. Затем в цикле перебираем ячейки диапазона и каждой присваиваем случайное значение от 0 до 15. Используем функцию Rnd(). Эта функция возвращает значение меньше единицы, но большее или равное нулю.
Синтаксис функции
Int((upperbound - lowerbound + 1) * Rnd + lowerbound)Где upperbound – это наибольшая граница, а lowerbound – наименьшая граница диапазона. Нам нужно число от 0 до 15, значит используем int((15-0+1)*Rnd + 0. То есть 16 * Rnd.
Затем проверяем число на совпадение. Повторяем случайный выбор, пока функция Cheking() не вернет 0.
В конце еще раз перебираем ячейки, чтобы заменить 0 на пустую ячейку.
Каждый ход проверяем на победу. Текст функции:
Public Function WinCheck() As IntegerПеременную i увеличиваем от 1 до 16 и сравниваем каждую ячейку. Если число в ячейке не совпадает с i или ячейка пустая, то возвращаем 0. Дополнительное условие – i не должно быть равно 16, так как это последняя ячейка, и в случае выигрыша она должна быть пустой.
Dim r As Integer, c As Integer, i As Integer
i = 1
For r = 1 To 4
For c = 1 To 4
If (Range("Pole").Cells(r, c).Value <> i Or Range("Pole").Cells(r, c).Value = "") And i <> 16 Then
WinCheck = 0
Exit Function
End If
i = i + 1
Next c
Next r
WinCheck = 1
End Function
Последняя функция – ход игрока. Для хода нужно нажать правой кнопкой мыши на ячейку, которую нужно передвинуть. Если рядом есть свободное место, то число передвинется туда, а ячейка станет пустой.
Используем процедуру BeforeRightClick, то есть обработка перед нажатием правой кнопки.
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)Сначала определяем, где находился курсор в момент нажатия. Если вне пределов диапазона, то ничего не делаем. Если внутри, то определяем строку и столбец нажатой ячейки и ищем свободную ячейку рядом. Если ячейка найдена, то устанавливаем там число, а текущую ячейку очищаем.
Dim row1 As Integer, col1 As Integer
If ActiveCell.Row > 2 And ActiveCell.Row < 7 And ActiveCell.Column > 1 And ActiveCell.Column < 7 Then
row1 = ActiveCell.Row
col1 = ActiveCell.Column
If row1 > 3 Then
If Cells(row1 - 1, col1).Value = "" Then
Cells(row1 - 1, col1).Value = ActiveCell.Value
ActiveCell.Value = ""
End If
End If
If row1 < 6 Then
If Cells(row1 + 1, col1).Value = "" Then
Cells(row1 + 1, col1).Value = ActiveCell.Value
ActiveCell.Value = ""
End If
End If
If col1 > 2 Then
If Cells(row1, col1 - 1).Value = "" Then
Cells(row1, col1 - 1).Value = ActiveCell.Value
ActiveCell.Value = ""
End If
End If
If col1 < 5 Then
If Cells(row1, col1 + 1).Value = "" Then
Cells(row1, col1 + 1).Value = ActiveCell.Value
ActiveCell.Value = ""
End If
End If
Cancel = True
If WinCheck() Then
MsgBox "Вы победили!"
End If
End If
End Sub
Чтобы не появлялось контекстное мене, делаем “Cancel = true”.
После хода вызываем функцию проверки на победу. Если функция вернула нуль (то есть истину), то показываем сообщение о победе.
Результат:
