Главная страница «Первого сентября»Главная страница журнала «Информатика»Содержание №8/2008


В мир информатики
Моделирование

Моделирование бросания игральной кости в электронной таблице Microsoft Excel

Окончание. Начало см. “В мир информатики” № 106 / “Информатика” № 6/2008

Напомним, что в разрабатываемом проекте происходит моделирование средствами электронной таблицы Microsoft Excel многократного бросания игральной кости (кубика) с подсчетом количества выпадения того или иного числа на грани кости и представлением результатов подсчета в виде диаграммы. Проект получается очень эффектным, если предварить выпадение того или иного числа вращением кубика.

Для этого найдем в Интернете (Можно также подготовить 7 изображений кубика, о которых пойдет речь далее, самостоятельно. — Прим. ред.) соответствующий анимированный рисунок в формате gif (http://www.sura.ru/dikov/Mybooks/stuff.htm). В языке программирования VBA (на котором написаны все наши процедуры), к сожалению, не предусмотрена возможность непосредственной работы с анимированными изображениями. Но зато на листе Excel можно использовать элементы управления Рисунок (Image), в которые можно помещать изображение. Этим мы и воспользуемся — вращение кубика будем имитировать путем последовательного показа отдельных кадров анимированного gif-изображения:

Отдельные изображения-кадры можно получить из общего gif-рисунка с помощью, например, программы Adobe ImageReady CS. Допустим, что получилось 7 файлов-картинок (как на рисунке чуть выше). Создадим на листе электронной таблицы 7 экземпляров объекта Рисунок (с помощью кнопки на панели инструментов Элементы управления). В качестве значения свойства Picture укажем путь к соответствующему файлу-рисунку, тем самым мы загрузим в наш проект рисунки, и они в последующем будут храниться в одном файле вместе с таблицей. Установим значения свойств BackStyle, BorderStyle равными нулю, убрав таким образом фон и граничную линию. Значение свойства Visible у всех рисунков, кроме одного, изменим на False, чтобы сделать их невидимыми. Напишем процедуру, которая будет имитировать на экране вращение кубика, “включая” ненадолго скрытые картинки последовательно друг за другом и снова делая их невидимыми:

Private Sub Бросить_кость()

DIM i As Integer

For i = 1 To p2

Image2.Visible = True

Image2.Visible = False

Image3.Visible = True

Image3.Visible = False

Image4.Visible = True

Image4.Visible = False

Image5.Visible = True

Image5.Visible = False

Image6.Visible = True

Image6.Visible = False

Image7.Visible = True

Image7.Visible = False

Image8.Visible = True

Image8.Visible = False

For j = 1 To p1

Next j

Next i

End Sub

Переменная p2 задает число повторений анимационной последовательности, переменная p1 — задержку времени между показом каждой последовательности. Так как процедура Бросить_кость не является процедурой обработки события, то мы сами должны вызвать окно редактора кода (нажав одновременно клавиши Alt.gif (663 bytes)и F11) и написать текст процедуры, в т.ч. ее заголовок и завершающую конструкцию End Sub.

Вызов процедуры Бросить_кость разместим в начале созданной ранее процедуры Бросить_1_раз_Click():

Private Sub Бросить_1_раз_Click()

Бросить_кость

Randomize

'Моделируем бросание кубика

Здесь возникает проблема, связанная со следующим. Так как процедура Бросить_кость вызывается еще и через процедуру Бросить_1000_раз_Click, желательно для последней уменьшить значения времени ожидания p1 и числа повторений анимации p2, чтобы не ждать окончания процесса тысячекратного “бросания” кубика с его вращением. Решить ее можно так.

Введем переменную сколько_раз, фиксирующую факт вызова процедуры Бросить_кость через процедуру Бросить_1000_раз_Click (в этом случае ее значение примем равным 1000), и в зависимости от ее значения будем задавать значения переменных p1 и p2:

Private Sub Бросить_1_раз_Click()

If сколько_раз = 1000 Then

p1 = 0

p2 = 1

Else

p1 = 300

p2 = 5

End If

Бросить_кость

Значение переменной сколько_раз будем задавать в процедуре Бросить_1000_раз_Click:

Private Sub Бросить_1000_раз_Click()

DIM i As integer

сколько_раз = 1000

For i = 1 To 1000

Чтобы переменная сколько_раз была “видна” в процедуре Бросить_1_раз_Click, а переменные p1 и p2 — в процедуре Бросить_кость, их надо описать как глобальные — со служебным словом Public перед всеми процедурами (этот раздел кода называется General):

Public сколько_раз, p1, p2 As Integer

От редакции. Предлагаем читателям подумать над тем, как сделать так, чтобы глобальной была только одна переменная — сколько_раз, а переменные p1 и p2 описывались бы в процедуре Бросить_кость. Решения присылайте в редакцию.

Для “полноты картины” после вращения будем показывать на листе изображение кубика, соответствующее выпавшему числу:

42-0.gif (12116 bytes)

С этой целью создадим шесть рисунков игральной кости с различными значениями на верхней грани. Для этого найдем в Интернете (http://www.sura.ru/dikov/Mybooks/stuff.htm) рисунок кубика в векторном формате и загрузим его, например, в программу Microsoft PowerPoint. В ней разгруппируем рисунок, после чего путем копирования и перемещения черных кружочков получим еще 5 нужных изображений. Сгруппируем элементы каждого изображения и сохраним рисунки в файле формата emf.

Так же, как и для предыдущих рисунков, создадим на листе шесть экземпляров объекта Рисунок и загрузим туда полученные изображения из файлов. Дадим имена экземплярам g1, g2, …, g6. Установим в 0 значения свойств BackStyle, BorderStyle. Свойству Visible присвоим значением False.

В конструкцию Select Case существующей процедуры Бросить_1_раз_Click добавим строки, “показывающие” изображение кубика, соответствующее выпавшему числу:

Private Sub Бросить_1_раз_Click()

……

Select Case выпало

Case 1

Range("C4").Select

g1.Visible = True

Case 2

Range("C5").Select

g2.Visible = True

Case 3

Range("C6").Select

g3.Visible = True

Case 4

Range("C7").Select

g4.Visible = True

Case 5

Range("C8").Select

g5.Visible = True

Case 6

Range("C9").Select

g6.Visible = True

End Select

Так как мы сделали видимой выпавшую грань игральной кости, то при следующем бросании необходимо ее скрыть. Сделаем это для всех граней в существующей процедуре Бросить_кость путем добавления в начало следующих строчек:

Private Sub Бросить_кость()

g1.Visible = False

g6.Visible = False

Теперь — все!

От редакции. Нет — не все! :) Предлагаем читателям провести эксперимент по моделированию бросания кубика и определить значения общего количества выпадения того или иного числа на грани кости при большом (в несколько тысяч) числе испытаний.

TopList