Создаём проект по обычной схеме: в VS в панели New Project в окне Project types выбираем тип проекта Visual Basic, Windows, в окне Templates выделяем шаблон Windows Forms Application, в окне Name записываем имя проекта Line и щёлкаем OK. Создаётся проект, появляется форма Form1 в режиме проектирования (рис. 21.9). Оставляем по умолчанию или проектируем форму, как подробно описано в параграфе “Методика проектирования формы”. За маркер увеличиваем размеры формы таким образом, чтобы в панели Properties (для Form1) в свойстве Size были значения, например, 880; 630. Устанавливаем белый цвет Window для фона формы в свойстве BackColor.
Для задания режимов и управления игрой воспользуемся каким-либо элементом управления или компонентом. Как и выше, с панели инструментов Toolbox переносим на форму элемент управления MenuStrip и щёлкаем по нему (ниже формы в режиме проектирования). На форме Form1 появляются окна с надписью Type Here (Печатайте здесь), в которые записываем команды сначала на английском языке:
File, New Game, Save, Load, Exit;
Score, Show Score, Calculate Avg;
Help, Help, About.
Теперь в панели Properties (для каждой команды) в свойстве Text изменяем английские команды на соответствующие русские:
Игра, Новая, Сохранить, Загрузить, Выход;
Очки, Показать, Рассчитать средние;
Помощь, Справка, О программе (рис. 21.10 – 21.12).
Рис. 21.9. Форма Form1 в режиме проектирования.
Рис. 21.10. Команды меню Игра. Рис. 21.11. Команды меню Очки. Рис. 21.12. Меню Помощь.
С панели инструментов Toolbox переносим на форму первую надпись Label. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 430; 124, в свойстве Name изменяем имя на lblName, в свойстве Font увеличиваем размер шрифта до 28, в свойстве Text записываем “Имя:”.
Правее на этой же горизонтали размещаем вторую надпись Label. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 568; 124, в свойстве Name изменяем имя на lblNameShow, в свойстве Font увеличиваем размер шрифта до 28, в свойстве Text записываем “игрока”.
Ниже размещаем третью надпись Label. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 430; 212, в свойстве Name изменяем имя на lblScore, в свойстве Font увеличиваем размер шрифта до 28, в свойстве Text записываем “Очки: ” (с пробелами для вывода очков в эти пробелы).
Ниже размещаем четвёртую надпись Label. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 430; 302, в свойстве Name изменяем имя на lblTime, в свойстве Font увеличиваем размер шрифта до 28, в свойстве Text записываем “Время: ” (с пробелами для вывода секунд, минут и часов в эти пробелы).
Ниже размещаем пятую надпись Label. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 430; 392, в свойстве Name изменяем имя на lblBallPreview, в свойстве Font увеличиваем размер шрифта до 28, в свойстве Text записываем “Следующие мячи:”.
Ниже размещаем первый графический элемент управления PictureBox. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 453; 477, в свойстве Size устанавливаем размеры 52; 52, в свойстве Name изменяем имя на picBallPre1.
Правее размещаем второй элемент PictureBox. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 510; 477, в свойстве Size устанавливаем размеры 52; 52, в свойстве Name изменяем имя на picBallPre2.
Правее размещаем третий элемент PictureBox. В панели Properties (для этого элемента) в свойстве Location устанавливаем координаты верхнего левого угла элемента 568; 477, в свойстве Size устанавливаем размеры 52; 52, в свойстве Name изменяем имя на picBallPre3.
Чтобы программа периодически через Interval времени дополняла поле игры новыми разноцветными мячами, с панели инструментов Toolbox переносим на форму (точнее, ниже формы) первый таймер Timer. В панели Properties (для этого таймера) в свойстве Name записываем имя tmr1, в свойстве Enabled оставляем заданное по умолчанию значение False, т.к. мы включим этот таймер в программе в нужном месте при помощи строки (Timer1.Enabled = True). А в свойстве Interval вместо заданных по умолчанию 100 миллисекунд задаём, например, значение 150 миллисекунд.
Чтобы после начала игры на форме шел отсчёт времени (Time), на форму переносим второй таймер Timer. В панели Properties (для этого таймера) в свойстве Name записываем имя tmr2, в свойстве Enabled оставляем заданное по умолчанию значение False, а в свойстве Interval задаём 1000 миллисекунд (равные 1 секунде).
Если в игре применяются звуковые файлы, то их целесообразно разместить в одной папке с именем, например, Sounds. Для добавления в проект этой папки, в панели Solution Explorer выполняем правый щелчок по имени проекта, в контекстном меню выбираем Add, New Folder, в поле появившегося значка папки записываем имя папки и нажимаем клавишу Enter.
Добавляем в эту папку звуковые файлы drumpad-crash.wav и win.wav по стандартной схеме: выполняем правый щелчок по имени этой папки, в контекстном меню выбираем Add, Existing Item, в панели Add Existing Item в окне “Files of type” выбираем “All Files”, в центральном окне находим (например, в папке с загруженными из Интернета файлами) и с нажатой клавишей Ctrl выделяем имена файлов и щёлкаем кнопку Add. В панели Solution Explorer мы увидим эти файлы (рис. 21.13). В панели Properties свойства этих файлов оставляем заданными по умолчанию.
Рис. 21.13. Панель Solution Explorer. Рис. 21.14. Панель Properties.
Добавляем в проект графические файлы по стандартной схеме: в панели Solution Explorer выполняем правый щелчок по имени проекта, в контекстном меню выбираем Add, Existing Item (или Project, Add Existing Item), в панели Add Existing Item в окне “Files of type” выбираем “All Files”, в центральном окне находим (например, в папке с загруженными из Интернета файлами) и с нажатой клавишей Ctrl выделяем имена файлов и щёлкаем кнопку Add. В панели Solution Explorer мы увидим эти файлы (рис. 21.13). В панели Properties свойства этих файлов оставляем заданными по умолчанию (рис. 21.14).
Для ввода в проект новой формы (для таблицы с результатами игры) в меню Project выбираем Add Windows Form, в панели Add New Item оставляем заданные по умолчанию параметры и щёлкаем кнопку Add. В ответ VS выводит новую форму Form2 и добавляет в панель Solution Explorer новый пункт Form2.vb. Эта форма Form2, которая должна выводиться после выбора команды Показать в меню Очки, будет проектироваться программно согласно приведённому далее коду.
С панели инструментов Toolbox переносим на форму Form2 (точнее, ниже формы) первый таймер Timer. В панели Properties (для этого таймера) в свойстве Enabled оставляем заданное по умолчанию значение False, т.к. мы включим этот таймер в программе в нужном месте при помощи строки (Timer1.Enabled = True). А в свойстве Interval вместо заданных по умолчанию 100 миллисекунд задаём, например, значение 20 миллисекунд.
Аналогично переносим на форму Form2 второй таймер Timer. В панели Properties (для этого таймера) в свойстве Enabled оставляем заданное по умолчанию значение False, а в свойстве Interval задаём 40 миллисекунд.
Аналогично добавляем в проект третью форму Form3, которая будет выводиться после выбора команды Справка в меню Помощь. На форме Form3 размещаем какой-либо элемент управления, например, TextBox, в который записываем справочную информацию, например, правила игры по описанной ранее методике.
Аналогично добавляется и проектируется следующая форма, которая должна выводиться после выбора команды “О программе” в меню Помощь.
Свойства всех элементов управления можно стандартно изменять, как описано ранее.
Открываем файл Form1.vb (например, так: File, Open, File) и вверху записываем директиву для подключения требуемого пространства имен:
Imports System.IO 'Для класса StreamWriter.
Напомним, что эту строку можно и не записывать, но тогда нам придётся перед каждым классом записывать это пространство имён.
Теперь в классе Form1 нашего проекта записываем следующие переменные и методы.
Листинг 21.1. Переменные и методы.
Const intBaseX As Integer = 10
Const intBaseY As Integer = 120
Dim Rand As New Random
'***
Dim playerName As String
Dim playerScore As Double
Dim playerTime As Integer
Dim DDScore As New DPaint
Dim DDTime As New DPaint
'***
Dim intFlag As Integer = -1
Dim flagMadeNew = 0
Dim posMoveTo As Integer
Dim MPBoxes(80) As MotionPic
Dim ThreeBI(2) As Integer
Dim ThreeBP(2) As Integer
Dim prePic(2) As PictureBox
Private Sub InitBoard(ByVal plName As String, _
ByVal plScore As Double, ByVal plTime As Integer)
playerName = plName
playerScore = plScore
playerTime = plTime
If flagMadeNew = 0 Then
Dim i As Integer
Dim intX = intBaseX + 2
Dim intY = intBaseY + 2
For i = 0 To 80
Dim MP As New MotionPic(New Size(36, 36), _
New Point(intX, intY))
MP.SizeMode = PictureBoxSizeMode.StretchImage
intX += 45
If (i + 1) Mod 9 = 0 Then
intY += 45
intX = intBaseX + 2
End If
AddHandler MP.Click, AddressOf Ball_Click
MPBoxes(i) = MP
Next
Me.Controls.AddRange(MPBoxes)
DDScore.width = lblScore.Height / 2 – 6
DDScore.thick = DDScore.width / 4
DDScore.position = New Point(lblScore.Width – _
(DDScore.width + 2) * 9, lblScore.Height / 2)
DDTime.width = lblTime.Height / 2 – 6
DDTime.thick = DDTime.width / 4
DDTime.position = New Point(lblTime.Width – _
(DDTime.width + 2) * 9, lblTime.Height / 2)
AddHandler lblScore.Paint, AddressOf LabelScore_Paint
lblScore.Refresh()
AddHandler lblTime.Paint, AddressOf LabelTime_Paint
lblTime.Refresh()
For i = 0 To 2
prePic(i) = New PictureBox
prePic(i).SizeMode = PictureBoxSizeMode.StretchImage
prePic(i).Size = New Size(16, 16)
prePic(i).Visible = False
Me.Controls.Add(prePic(i))
AddHandler prePic(i).Click, AddressOf PrePic_Click
prePic(i).BringToFront()
Next
Else
ResetBoard()
End If
lblNameShow.Text = playerName
If playerName.Length > 8 Then
lblNameShow.Text += " "
tmr1.Enabled = True
End If
tmr2.Enabled = True
DDScore.number = plScore
lblScore.Refresh()
DDTime.number = plTime
lblTime.Refresh()
PreShow()
End Sub
Private Sub FindSol(ByVal i As Integer)
If MPBoxes(i).Tag <> "" Or MPBoxes(i).Tag = "Here" Then
Return
Else
MPBoxes(i).Tag = "Here"
End If
Select Case TestABox(i)
Case 1
FindSol(1)
FindSol(9)
Case 2
FindSol(7)
FindSol(17)
Case 3
FindSol(71)
FindSol(79)
Case 4
FindSol(63)
FindSol(73)
Case 5
FindSol(i + 1)
FindSol(i + 9)
FindSol(i – 1)
Case 6
FindSol(i – 9)
FindSol(i – 1)
FindSol(i + 9)
Case 7
FindSol(i – 1)
FindSol(i – 9)
FindSol(i + 1)
Case 8
FindSol(i – 9)
FindSol(i + 1)
FindSol(i + 9)
Case Else
FindSol(i – 9)
FindSol(i + 9)
FindSol(i + 1)
FindSol(i – 1)
End Select
End Sub
Private Sub ResetAllTag()
For Each Pic As MotionPic In MPBoxes
If Pic.Tag = "Here" Then
Pic.Tag = ""
End If
Next
End Sub
Private Function TestABox(ByVal val As Integer)
Select Case val
Case 0 : Return 1
Case 8 : Return 2
Case 80 : Return 3
Case 72 : Return 4
Case 1 To 7 : Return 5
Case 73 To 79 : Return 7
Case 17, 26, 35, 44, 53, 62, 71 : Return 6
Case 9, 18, 27, 36, 45, 54, 63 : Return 8
Case Else : Return 0
End Select
End Function
'Serious trouble happened – think more
Private Function GiveThreeBalls() As Boolean
If ThreeBI(1) = -1 Then 'Review for Game over
Return False
Else
For i As Integer = 0 To 2
If ThreeBI(i) = -1 Then
Exit For
Else
If MPBoxes(ThreeBP(i)).MPState = BallState. _
NO_BALL And ThreeBP(i) <> posMoveTo Then
MPBoxes(ThreeBP(i)).Init(ThreeBI(i))
CalWin(ThreeBP(i))
End If
End If
Next
End If
RandomThreeBalls()
PreShow()
Return True
End Function
Private Function IsFullBoard() As Boolean
Dim i As Integer
For Each Pic As PictureBox In MPBoxes
If MPBoxes(i).MPState <> BallState.NO_BALL Then
i += 1
End If
Next
If i = 81 Then
Return True
Else
Return False
End If
End Function
Private Sub RandomThreeBalls()
Dim ArrL As New ArrayList
Dim i As Integer
Dim pos As Integer
Dim ind As Integer
For i = 0 To 80
If MPBoxes(i).MPState = BallState.NO_BALL Or _
MPBoxes(i).MPState = BallState.DESTROYING_BALL Then
ArrL.Add(i)
End If
Next
For i = 0 To IIf(ArrL.Count > 2, 2, ArrL.Count – 1)
pos = Rand.Next(0, ArrL.Count)
pos = CInt(ArrL(pos))
ArrL.Remove(pos)
ThreeBP(i) = pos
ind = Rand.Next(0, 12)
ind = (ind \ 2) * 2
ThreeBI(i) = ind
Next
For j As Integer = i To 2
ThreeBI(j) = -1
ThreeBP(j) = -1
Next
End Sub
'#Region "Check for Calculate Score"
Private Function CheckHor(ByVal pos As Integer) As Integer
Dim type As Integer = MPBoxes(pos).MPIndex
Dim i As Integer = (pos \ 9) * 9
Dim count As Integer
Dim startpos As Integer = i
Dim endpos As Integer = i
While i < (pos \ 9) * 9 + 9
If MPBoxes(i).MPIndex = type Then
endpos += 1
count = endpos – startpos
Else
If count > 4 Then
While MPBoxes(pos).MPState = _
BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j).Destroy()
Next
Return count
End If
If i >= (pos \ 9) * 9 + 5 Then
Return count
End If
startpos = i + 1
endpos = i + 1
End If
i += 1
End While
If count > 4 Then
While MPBoxes(pos).MPState = BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j).Destroy()
Next
Return count
End If
End Function
Private Function CheckVer(ByVal pos As Integer) As Integer
Dim type As Integer = MPBoxes(pos).MPIndex
Dim i As Integer = pos Mod 9
Dim count As Integer
Dim startpos As Integer = i
Dim endpos As Integer = i
While i < (pos Mod 9) + 73
If MPBoxes(i).MPIndex = type Then
endpos += 9
count = (endpos – startpos) / 9
Else
If count > 4 Then
While MPBoxes(pos).MPState = _
BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j * 9).Destroy()
Next
Return count
End If
If i >= (pos Mod 9) + 36 Then
Return count
End If
startpos = i + 9
endpos = i + 9
End If
i += 9
End While
If count > 4 Then
While MPBoxes(pos).MPState = BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j * 9).Destroy()
Next
Return count
End If
End Function
Private Function CheckLR(ByVal pos As Integer) As Integer
If pos = 5 Or pos = 6 Or pos = 7 Or pos = 8 Or pos = 15 _
Or pos = 16 Or pos = 17 _
Or pos = 25 Or pos = 26 Or pos = 35 Or pos = 45 _
Or pos = 54 Or pos = 55 _
Or pos = 63 Or pos = 64 Or pos = 65 Or pos = 72 _
Or pos = 73 Or pos = 74 Or pos = 75 Then
Return 0
End If
Dim type As Integer = MPBoxes(pos).MPIndex
Dim i As Integer = pos Mod 10
i = IIf(i = 8, 18, IIf(i = 7, 27, IIf(i = 6, 36, i)))
Dim count As Integer
Dim startpos As Integer = i
Dim endpos As Integer = i
Dim tempi As Integer = i + 1
Dim temp As Integer
If i < 9 Then
temp = 9 – i
Else
temp = 9 – (i \ 9)
End If
While i < tempi + (temp – 1) * 10
If MPBoxes(i).MPIndex = type Then
endpos += 10
count = (endpos – startpos) \ 10
Else
If count > 4 Then
While MPBoxes(pos).MPState = _
BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j * 10).Destroy()
Next
Return count
End If
If i >= pos + 40 Then
Return count
End If
startpos = i + 10
endpos = i + 10
End If
i += 10
End While
If count > 4 Then
While MPBoxes(pos).MPState = BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j * 10).Destroy()
Next
Return count
End If
End Function
Private Function CheckRL(ByVal pos As Integer) As Integer
If pos = 0 Or pos = 1 Or pos = 2 Or pos = 3 Or pos = 9 _
Or pos = 10 Or pos = 11 _
Or pos = 18 Or pos = 19 Or pos = 27 Or pos = 53 _
Or pos = 61 Or pos = 62 _
Or pos = 69 Or pos = 70 Or pos = 71 Or pos = 77 _
Or pos = 78 Or pos = 79 Or pos = 80 Then
Return 0
End If
Dim type As Integer = MPBoxes(pos).MPIndex
Dim i As Integer = pos Mod 8
If i = 0 Then
i = 8
ElseIf i < 4 Then
i = (i + 1) * 8 + i
ElseIf pos \ 8 >= 5 Then
i = 45
End If
Dim count As Integer
Dim startpos As Integer = i
Dim endpos As Integer = i
Dim tempi As Integer = i + 1
Dim temp As Integer
If i < 9 Then
temp = i + 1
Else
temp = 9 – (i \ 8)
End If
While i < tempi + temp * 8
If MPBoxes(i).MPIndex = type Then
endpos += 8
count = (endpos – startpos) \ 8
Else
If count > 4 Then
While MPBoxes(pos).MPState = _
BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j * 8).Destroy()
Next
Return count
End If
If i >= pos + 32 Then
Return count
End If
startpos = i + 8
endpos = i + 8
End If
i += 8
End While
If count > 4 Then
While MPBoxes(pos).MPState = BallState.ZOOMING_BALL
Application.DoEvents()
End While
For j As Integer = 0 To count – 1
MPBoxes(startpos + j * 8).Destroy()
Next
Return count
End If
End Function
Private Function CalWin(ByVal pos As Integer) As Integer
Dim point As Integer = CheckHor(pos)
If point < 4 Then
point = CheckVer(pos)
End If
If point < 4 Then
point = CheckLR(pos)
End If
If point < 4 Then
point = CheckRL(pos)
End If
If point > 4 Then
Dim dpoint As Double = point * 100 + (dpoint \ 6) * 100
Dim n As Double = DDScore.number + dpoint
For i As Double = DDScore.number To n Step 10
DDScore.number = i
lblScore.Refresh()
Next
DDScore.number = n
Return point
Else
Return 0
End If
End Function
'#Region "Ball Event And Paint Board"
Private Sub Ball_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
CType(sender, MotionPic).Jump()
If CType(sender, MotionPic).MPState <> _
BallState.NO_BALL Then
If intFlag <> -1 Then
MPBoxes(intFlag).Jump()
End If
'intFlag = MPBoxes.IndexOf(MPBoxes, sender)
'Исправляем предупреждение:
intFlag = Array.IndexOf(MPBoxes, sender)
ElseIf intFlag <> -1 Then
Dim tempS As String = MPBoxes(intFlag).Tag
MPBoxes(intFlag).Tag = ""
FindSol(intFlag)
If sender.tag = "Here" Then
'posMoveTo = MPBoxes.IndexOf(MPBoxes, sender)
'Исправляем предупреждение:
posMoveTo = Array.IndexOf(MPBoxes, sender)
If posMoveTo = ThreeBP(0) Then
prePic(0).SendToBack()
ElseIf posMoveTo = ThreeBP(1) Then
prePic(1).SendToBack()
ElseIf posMoveTo = ThreeBP(2) Then
prePic(2).SendToBack()
End If
CType(sender, MotionPic).Init(MPBoxes(intFlag). _
MPIndex)
MPBoxes(intFlag).Destroy()
While MPBoxes(intFlag).MPState = _
BallState.DESTROYING_BALL
Application.DoEvents()
End While
If CalWin(posMoveTo) = 0 Then
If GiveThreeBalls() = False Then
playerScore = DDScore.number
Dim frm As Form2 = New Form2
frm.AddPlayer() = _
New Player(playerName, playerScore)
frm.Show()
frm.PlashScreen()
frm.drawTable()
ResetBoard()
End If
End If
PreShow()
intFlag = -1
Else
MPBoxes(intFlag).Tag = tempS
End If
ResetAllTag()
End If
End Sub
Private Sub ResetBoard()
ThreeBI(0) = -1
tmr1.Enabled = False
tmr2.Enabled = False
playerScore = 0
playerTime = 0
DDScore.number = 0
DDTime.number = 0
Me.Refresh()
PreShow()
lblNameShow.Text = ""
О проекте
О подписке