Книга Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 6: Программирование на Visual Basic искусственного интеллекта. Продолжение 2 - читать онлайн бесплатно, автор Валерий Алексеевич Жарков. Cтраница 2
bannerbanner
Вы не авторизовались
Войти
Зарегистрироваться
Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 6: Программирование на Visual Basic искусственного интеллекта. Продолжение 2
Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 6: Программирование на Visual Basic искусственного интеллекта. Продолжение 2
Добавить В библиотекуАвторизуйтесь, чтобы добавить
Оценить:

Рейтинг: 0

Добавить отзывДобавить цитату

Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 6: Программирование на Visual Basic искусственного интеллекта. Продолжение 2





Рис. 20.9. Команды меню Game. Рис. 20.10. Команды меню Help.

В панели Properties в свойстве Text в имени каждой команды меню MenuStrip перед соответствующей буквой записываем оператор &, после чего на форме эта буква станет подчёркнутой. Напомним, что в режиме выполнения, после нажатия клавиши Alt вместе с клавишей с подчёркнутой буквой (английского алфавита) в команде меню Game или Help, выполняется соответствующая команда.

С панели инструментов Toolbox размещаем на форме основной графический элемент управления PictureBox для поля игры. За маркеры увеличиваем размеры поля, чтобы в панели Properties в свойстве Size были значения 300; 375, а в свойстве BackColor вместо заданного по умолчанию серого цвета Control выбираем белый цвет Window.

Размещаем на форме панель Panel, за её маркеры увеличиваем размеры Size до значений 175; 96.

На этой панели Panel размещаем 5 элементов управления PictureBox с размерами Size (24; 67). В панели Properties в свойстве BackColor для всех этих элементов выбираем белый цвет Window, а в свойстве Name изменяем имена этих 5 элементов на следующие (справа налево):

ones – единицы,

tens – десятки,

hundreds – сотни,

thousands – тысячи,

tenthousands – десятки тысяч.

Ниже на форме размещаем элемент управления PictureBox с заданными по умолчанию размерами Size (100; 50). Чтобы на этом элементе разместить рисунок, в панели Properties щёлкаем свойство Image, в появившейся панели Select Resource выбираем переключатель Local resource и щёлкаем кнопку Imports (рис. 20.11). В панели Open находим (например, в папке с загруженными из Интернета файлами) графический файл new.bmp (рис. 20.12) и щёлкаем кнопку Open, после чего этот рисунок мы увидим в панели Select Resource, на которой щёлкаем OK. Окончательно, этот рисунок new.bmp разместится в панели Properties в свойстве Image и на форме на поле данного элемента PictureBox.

Аналогично ниже размещаем на форме ещё один элемент управления PictureBox с заданными по умолчанию размерами Size (100; 50), на который добавляем рисунок exit.bmp.

Рис. 20.11. В панели Select Resource щёлкаем Imports. Рис. 20.12. В панели Open находим файл.

Аналогично ниже размещаем на форме ещё один элемент управления PictureBox, увеличиваем его размеры Size до 128; 50 и добавляем на него рисунок option.bmp.

С панели инструментов Toolbox переносим на форму компонент типа списка рисунков ImageList, который, как компонент, размещается ниже формы. В панели Properties в свойстве Name изменяем его имя на numbers (цифры для подсчёта очков), а в свойстве ImageSize увеличиваем цифры до размеров 26; 67. Чтобы этот компонент заполнить цифрами для подсчёта очков, в панели Properties щёлкаем свойство Images, в появившейся панели Images Collection Editor щёлкаем кнопку Add (рис. 20.13). В приведённой выше панели Open находим (например, в папке с загруженными из Интернета файлами) графический файл 0.bmp и щёлкаем кнопку Open, после чего этот рисунок мы увидим в панели Images Collection Editor. Аналогично в список рисунков ImageList добавляем остальные цифры 1, 2, 3, …, 9.

Чтобы программа периодически через Interval времени дополняла поле игры новыми разноцветными кругами (взамен выбитых игроком кругов), с панели инструментов Toolbox переносим на форму (точнее, ниже формы) первый таймер Timer1. В панели Properties (для этого таймера) в свойстве Enabled оставляем заданное по умолчанию значение False, т.к. мы включим этот таймер в программе в нужном месте при помощи строки (Timer1.Enabled = True). А в свойстве Interval вместо заданных по умолчанию 100 миллисекунд задаём, например, значение 7000 миллисекунд (равное 7 секундам).

Чтобы в верхней части формы (на синей полоске для свойства Text) после начала игры шел отсчёт времени (Time), на форму переносим второй таймер Timer2. В панели Properties (для этого второго таймера) в свойстве Enabled изменяем заданное по умолчанию значение False на True (включаем таймер), в свойстве Interval вместо заданных по умолчанию 100 миллисекунд задаём значение 1000 (равное 1 секунде), чтобы шел посекундный отсчёт времени.

Если в игре применяются звуковые файлы, то их целесообразно разместить в одной папке с именем, например, Resources. Для добавления в проект этой папки, в панели Solution Explorer выполняем правый щелчок по имени проекта, в контекстном меню выбираем Add, New Folder, в поле появившегося значка папки записываем имя папки и нажимаем клавишу Enter.

Добавляем в эту папку первый звуковой файл Windows XP Balloon.wav по стандартной схеме: выполняем правый щелчок по имени этой папки, в контекстном меню выбираем Add, Existing Item, в панели Add Existing Item в окне “Files of type” выбираем “All Files”, в центральном окне находим (например, в папке с загруженными из Интернета файлами) и выделяем имя файла и щёлкаем кнопку Add (или дважды щёлкаем по имени файла). В панели Solution Explorer мы увидим этот файл.

Аналогично добавляем в проект второй файл win.wav.

Напомним, что добавлять в проект указанные выше файлы можно как по одному, так и все сразу (после их выделения или только одной мышью, или мышью с нажатой клавишей Shift – для выделения всех соседних файлов, или мышью с нажатой клавишей Ctrl – для выделения всех файлов в различных местах).



Рис. 20.13. В панели Images Collection Editor щёлкаем кнопки Add и OK.

Для ввода в проект новой формы (для таблицы с результатами игры) в меню Project выбираем Add Windows Form, в панели Add New Item оставляем заданные по умолчанию параметры и щёлкаем кнопку Add. В ответ VS выводит новую форму Form2 и добавляет в панель Solution Explorer новый пункт Form2.vb. Аналогично, как первую, проектируем вторую форму (рис. 20.14), за маркеры увеличиваем форму до размеров Size (436; 223) и вводим на форму элементы управления: сетку DataGridView с размерами Size (288; 104), кнопку Button с заголовком Reset (в свойстве Text) и флажок CheckBox, для которого в свойстве Name записываем имя isSoundOn, а в свойстве Checked выбираем значение True (устанавливаем флажок). Свойства этих элементов управления можно стандартно изменять, как описано ранее.



Рис. 20.14. Форма Form2 для таблицы с результатами игры.

20.4. Код программы


Открываем файл Form1.vb (например, по схеме: File, Open, File) и в классе Form1 нашего проекта записываем следующие переменные и методы.

Листинг 20.1. Переменные и методы.

Dim matrix As Grid

Dim score As Integer = 0

Dim mouseOffset As Point

Dim paused As Boolean = False

Dim isSoundOn As Boolean = True

Private Sub BlockClick(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs)

' Play the sound.

If isSoundOn Then

'Исправляем ошибку в оригинале:

My.Computer.Audio.Play( _

"..\..\Resources\Windows XP Balloon.wav", _

AudioPlayMode.WaitToComplete) 'Ждем окончания мелодии.

End If

' Update the matrix and compute the new score.

Dim count As Integer = matrix.Click(New Point(e.X, e.Y))

score += 10 * count

' Draw the new grid.

matrix.Draw(Me.PictureBox1.CreateGraphics(), _

Me.PictureBox1.BackColor)

' Write the score on the screen.

Dim images() As PictureBox = { _

Me.tenthousands, Me.thousands, _

Me.hundreds, Me.tens, Me.ones}

Dim scoreString As String = score.ToString().PadLeft(5)

Dim digits() As String = { _

scoreString.Chars(0), _

scoreString.Chars(1), _

scoreString.Chars(2), _

scoreString.Chars(3), _

scoreString.Chars(4)}

For index As Integer = 0 To 4

If digits(index) <> " " Then

images(index).Image = _

numbers.Images(CInt(digits(index)))

Else

images(index).Image = Nothing

End If

Next

End Sub

Private Sub StartNewGame()

' If a game is already running, check for a new high score.

If Not matrix Is Nothing Then

Me.Timer1.Enabled = False

HighScores.UpdateScores(score)

End If

Timer1.Enabled = False

matrix = New Grid(6)

score = 0

matrix.Draw(Me.PictureBox1.CreateGraphics(), _

Me.PictureBox1.BackColor)

Timer1.Enabled = True

AddHandler PictureBox1.MouseDown, AddressOf BlockClick

'Обнуляем счётчик секунд:

secondCounter = 0

End Sub

' To pause the game, turn off the timer.

Private Sub Pause()

Timer1.Enabled = False

Me.PauseToolStripMenuItem.Visible = False

Me.RestartToolStripMenuItem.Visible = True

RemoveHandler PictureBox1.MouseDown, AddressOf BlockClick

paused = True

End Sub

Private Sub ShowOptions()

'Dim optionsForm As New Options

Dim optionsForm As New Form2

optionsForm.SoundOn = isSoundOn

optionsForm.ShowDialog()

isSoundOn = optionsForm.SoundOn

optionsForm.Dispose()

End Sub

Private Sub Restart()

Timer1.Enabled = True

Me.PauseToolStripMenuItem.Visible = True

Me.RestartToolStripMenuItem.Visible = False

AddHandler PictureBox1.MouseDown, AddressOf BlockClick

paused = False

End Sub

Private Sub EndGame()

' Get top scores so far.

Me.Timer1.Enabled = False

HighScores.UpdateScores(score)

Me.Close()

End Sub

В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события Load (Загрузка). Появившийся шаблон метода Form1_Load после записи нашего кода принимает следующий вид.

Листинг 20.2. Метод для загрузки объектов.

Private Sub Form1_Load(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

PointTranslator.Graphics = Me.PictureBox1.CreateGraphics()

Me.PictureBox1.Width = Block.BlockSize * 12

Me.PictureBox1.Height = Block.BlockSize * 15

HighScores.SetUpHighScores()

' Setup the background color and the starting score.

Me.BackColor = Color.White

Me.ones.Image = Me.numbers.Images(0)

Me.tens.Image = Me.numbers.Images(0)

Me.hundreds.Image = Me.numbers.Images(0)

Me.Menu = Nothing

End Sub

Дважды щёлкаем по команде New Game для элемента управления MenuStrip. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.3. Метод-обработчик выбора команды.

Private Sub NewGameToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles NewGameToolStripMenuItem.Click

StartNewGame()

End Sub

Дважды щёлкаем по команде Pause для элемента управления MenuStrip. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.4. Метод-обработчик выбора команды.

Private Sub PauseToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles PauseToolStripMenuItem.Click

Me.Pause()

End Sub

Дважды щёлкаем по команде Restart для элемента управления MenuStrip. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.5. Метод-обработчик выбора команды.

Private Sub RestartToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles RestartToolStripMenuItem.Click

Restart()

End Sub

Дважды щёлкаем по команде Options для элемента управления MenuStrip. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.6. Метод-обработчик выбора команды.

Private Sub OptionsToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles OptionsToolStripMenuItem.Click

Dim optionsForm As New Form2

optionsForm.ShowDialog()

End Sub

Дважды щёлкаем по команде Exit для элемента управления MenuStrip. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.7. Метод-обработчик выбора команды.

Private Sub ExitToolStripMenuItem_Click( _

ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles ExitToolStripMenuItem.Click

Me.EndGame()

End Sub

Дважды щёлкаем по элементу управления PictureBox с рисунком new.bmp (или в панели Properties для этого элемента на вкладке Events дважды щёлкаем по имени события Click). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.8. Метод-обработчик щелчка по элементу.

Private Sub newGame_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles newGame.Click

StartNewGame()

End Sub

Дважды щёлкаем по элементу управления PictureBox с рисунком exit.bmp (или в панели Properties для этого элемента на вкладке Events дважды щёлкаем по имени события Click). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.9. Метод-обработчик щелчка по элементу.

Private Sub exitGame_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles exitGame.Click

EndGame()

End Sub

Дважды щёлкаем по элементу управления PictureBox с рисунком options.bmp (или в панели Properties для этого элемента на вкладке Events дважды щёлкаем по имени события Click). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.10. Метод-обработчик щелчка по элементу.

Private Sub options_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles options.Click

ShowOptions()

End Sub

Для управления игрой мышью, в панели Properties (для формы Form1) на вкладке Events дважды щёлкаем по имени события MouseDown. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.11. Метод-обработчик нажатия кнопки мыши.

Private Sub Form1_MouseDown(ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) _

Handles MyBase.MouseDown

mouseOffset = New Point(-e.X, -e.Y)

End Sub

Для управления игрой мышью, в панели Properties (для формы Form1) на вкладке Events дважды щёлкаем по имени события MouseMove. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.12. Метод-обработчик перемещения мыши.

Private Sub Form1_MouseMove(ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) _

Handles MyBase.MouseMove

If e.Button = Windows.Forms.MouseButtons.Left Then

Dim mousePos As Point = Control.MousePosition

mousePos.Offset(mouseOffset.X, mouseOffset.Y)

Location = mousePos

End If

End Sub

Для управления игрой клавишами клавиатуры, в панели Properties (для формы Form1) на вкладке Events дважды щёлкаем по имени события KeyPress. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.13. Метод-обработчик нажатия клавиши.

Private Sub Form1_KeyPress(ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.KeyPressEventArgs) _

Handles MyBase.KeyPress

Select Case e.KeyChar

Case "p"c, "P"c

If paused Then

Restart()

Else

Pause()

End If

Case "m"c, "M"c

If Me.FormBorderStyle = _

Windows.Forms.FormBorderStyle.Fixed3D Then

Me.FormBorderStyle = _

Windows.Forms.FormBorderStyle.None

Me.Menu = Nothing

Else

Me.FormBorderStyle = _

Windows.Forms.FormBorderStyle.Fixed3D

'Me.Menu = Me.MainMenu1

End If

Case Else

' Do nothing.

End Select

End Sub

Чтобы программа периодически через Interval времени дополняла поле игры новыми разноцветными кругами (взамен выбитых игроком кругов), ниже формы дважды щёлкаем по значку для первого таймера Timer1 (или в панели Properties для этого компонента на вкладке Events дважды щёлкаем по имени события Tick). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.14. Метод, вызываемый через Interval времени.

Private Sub Timer1_Tick(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Timer1.Tick

' Add another row to the grid and update the screen.

matrix.AddRow()

matrix.Draw(Me.PictureBox1.CreateGraphics(), _

Me.PictureBox1.BackColor)

End Sub

Чтобы в верхней части формы (на синей полоске для свойства Text) после начала игры шел отсчёт времени (Time), ниже формы дважды щёлкаем по значку для второго таймера Timer2 (или в панели Properties для этого компонента на вкладке Events дважды щёлкаем по имени события Tick). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.

Листинг 20.15. Метод, вызываемый через Interval времени.

'Счётчик секунд, который обнуляем в начале каждой игры

'в методе StartNewGame:

Dim secondCounter As Integer

'Время окончания игры:

Dim EndGameTime As Integer = 60

Private Sub Timer2_Tick(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Timer2.Tick

secondCounter = secondCounter + 1

Me.Text = "Time : " & secondCounter.ToString()

'Мелодия окончания игры:

If secondCounter = EndGameTime Then

My.Computer.Audio.Play( _

"..\..\Resources\win.wav", _

AudioPlayMode.Background)

End If

End Sub

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

Мы закончили написание программы в главный класс Form1 (для формы Form1 с пользовательским интерфейсом игры).

Теперь в наш проект добавляем новые файлы (для программирования соответствующих игровых действий). Добавить в проект файл можно по двум вариантам.

По первому варианту, добавляем в проект нужный файл по обычной схеме: в панели Solution Explorer выполняем правый щелчок по имени проекта, в контекстном меню выбираем Add, Existing Item, в панели Add Existing Item в окне “Files of type” выбираем “All Files”, в центральном окне находим (например, в папке компьютера файл, скопированный из Интернета), выделяем имя этого файла и щёлкаем кнопку Add (или дважды щёлкаем по имени этого файла).

По второму варианту, в панели Solution Explorer выполняем правый щелчок по имени проекта и в контекстном меню выбираем Add, New Item, в панели Add New Item выделяем шаблон Code File, в окне Name записываем имя Block.vb и щёлкаем кнопку Add. В проект (и в панель Solution Explorer) добавляется этот файл, открывается пустое окно редактирования кода, в которое записываем код со следующего листинга.

Листинг 20.16. Новый файл.

Imports System.Drawing.Drawing2D

'''

''' This class represents one of the balls in the game grid.

'''

'''

Public Class Block

Public Const BlockSize As Integer = 25

Private colorValue As Color

Private deletionValue As Boolean = False

Private Shared rand As New Random

Public Property Color() As Color

Get

Return colorValue

End Get

Set(ByVal Value As Color)

colorValue = Value

End Set

End Property

Public Property MarkedForDeletion() As Boolean

Get

Return deletionValue

End Get

Set(ByVal Value As Boolean)

deletionValue = Value

End Set

End Property

Public Sub New(ByVal newColor As Color)

colorValue = newColor

End Sub

Public Sub New(ByVal colors() As Color)

Dim ncolors As Integer = colors.Length

Dim pickedColor As Integer

pickedColor = rand.Next(0, ncolors)

colorValue = colors(pickedColor)

End Sub

Public Sub Draw(ByVal graphics As Graphics, ByVal point As Point)

Dim brush As System.Drawing.Drawing2D.LinearGradientBrush = _

CreateTheBrush(point)

DrawTheCircle(graphics, brush, point)

End Sub

Private Sub DrawTheCircle(ByVal graphics As Graphics, _

ByVal brush As LinearGradientBrush, ByVal location As Point)

Dim topleft As Point = location

Dim bottomright As Point = New Point(location.X + _

BlockSize, location.Y + BlockSize)

Dim transTopLeft As Point = PointTranslator.TranslateToBL( _

topleft)

Dim transBottomRight As Point = _

PointTranslator.TranslateToBL(bottomright)

Dim transwidth As Integer = transBottomRight.X – transTopLeft.X

Dim transheight As Integer = _

transBottomRight.Y – transTopLeft.Y

graphics.FillEllipse(brush, New Rectangle(transTopLeft, _

New Size(transwidth, transheight)))

End Sub

Private Function CreateTheBrush(ByVal location As Point) As _

LinearGradientBrush

Dim transLocation As Point = _

PointTranslator.TranslateToBL(location)

Dim brushpt1 As Point = transLocation

Dim brushpt2 As New Point(transLocation.X + Block.BlockSize _

+ 4, transLocation.Y – BlockSize – 4)

Dim brush As New LinearGradientBrush(brushpt1, _

brushpt2, Me.Color, System.Drawing.Color.White)

Return brush

End Function

End Class

По второму варианту, в панели Solution Explorer выполняем правый щелчок по имени проекта и в контекстном меню выбираем Add, New Item, в панели Add New Item выделяем шаблон Code File, в окне Name записываем имя Grid.vb и щёлкаем кнопку Add. В проект (и в панель Solution Explorer) добавляется этот файл, открывается пустое окно редактирования кода, в которое записываем код со следующего листинга.

Листинг 20.17. Новый файл.

'''

''' This class represents the grid of blocks. It handles most of

''' the game play.

'''

'''

Public Class Grid

' The grids is 12 columns and 15 rows of Block objects.

Dim matrix(11, 14) As Block

'''

''' Creates a few rows of blocks to start the game.

''' Game starts with Red, Blue, and Green blocks.

'''

''' Number of rows of blocks to create

''' to start the game.

'''

Public Sub New(ByVal nrows As Integer)

If nrows > matrix.GetLength(0) Then

Throw New Exception("Must start with " & _

matrix.GetLength(0) & " or fewer rows.")

End If

Dim row As Integer

Dim column As Integer

For row = 0 To nrows – 1

For column = 0 To matrix.GetLength(1) – 1

matrix(row, column) = New Block( _

New Color() {Color.Red, Color.Blue, Color.Green})

Next

Next

For row = nrows To matrix.GetLength(0) – 1

For column = 0 To matrix.GetLength(1) – 1

matrix(row, column) = Nothing

Next

Next

End Sub

'''

''' A new row may be added at any time. New rows have Gray

''' blocks in addition

''' to Red, Blue, and Green. This makes the game more difficult.

'''

'''

Public Sub AddRow()

Dim column As Integer

' Add a new block to each column.

For column = 0 To matrix.GetLength(1) – 1

Dim newBlock As New Block(New Color() _

{Color.Red, Color.Blue, Color.Green, Color.Gray})

' Add the new block at the botttom of the column,


' and push the rest of the

' blocks up one column.

For row As Integer = matrix.GetLength(0) – 1 To 1 Step -1

matrix(row, column) = matrix(row – 1, column)

Next

matrix(0, column) = newBlock

Next

End Sub

'''

''' Draw the grid of blocks

'''

'''

'''

'''

Public Sub Draw(ByVal graphics As Graphics, _

ByVal backColor As Color)