VB.Net OOP Conway's Game of Life
Overview
"The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.
The "game" is a zero-player game, meaning that its evolution is determined by its initial state, requiring no further input. One interacts with the Game of Life by creating an initial configuration and observing how it evolves, or, for advanced "players", by creating patterns with particular properties. This is a simplified version allowing 3 distinct seeds, a diamond shape, a square, and a cross shape.
* *
"The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, alive or dead, or "populated" or "unpopulated". Every cell interacts with its eight neighbors, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:
- Any live cell with fewer than two live neighbors dies, as if caused by under-population.
- Any live cell with two or three live neighbors lives on to the next generation.
- Any live cell with more than three live neighbors dies, as if by over-population.
- Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
The initial pattern constitutes the seed of the system. The first generation is created by applying the above rules simultaneously to every cell in the seed—births and deaths occur simultaneously, and the discrete moment at which this happens is sometimes called a tick (in other words, each generation is a pure function of the preceding one). The rules continue to be applied repeatedly to create further generations." [Wikipedia]
The GUI Form
The Form is very simple, providing just an interface for the core Animation class, which is where the action takes place.
The Form contains a ComboBox for selecting a seed pattern, an extended DataGridView which displays the animation, and a Button to initiate the animation...
The gui exDGV (Extended DataGridView)
The exDGV restricts any form of user interaction, as it is intended purely for display purposes. There were though, two reasons for doing this. By default, a DataGridView is an input control, allowing a user to enter text, and also to select cells and ranges of cells. That was undesirable, because it would ruin the animation effect, but also restricting those characteristics lets the DataGridView render faster.
''' <summary>
''' Extended DataGridView
''' DoubleBuffered. Restricts user selection of cells to facilitate seamless highlighting line drawing.
''' </summary>
''' <remarks></remarks>
Public Class exDGV
Inherits DataGridView
Dim WM_LBUTTONDOWN As Integer = &H201
Dim WM_LBUTTONDBLCLK As Integer = &H203
Dim WM_KEYDOWN As Integer = &H100
Public Sub New()
Me.DoubleBuffered = True
End Sub
Protected Overrides Sub OnRowPrePaint(ByVal e As System.Windows.Forms.DataGridViewRowPrePaintEventArgs)
e.PaintParts = e.PaintParts And Not DataGridViewPaintParts.Focus
MyBase.OnRowPrePaint(e)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_LBUTTONDBLCLK OrElse m.Msg = WM_KEYDOWN OrElse m.Msg = WM_LBUTTONDOWN Then
Return
End If
MyBase.WndProc(m)
End Sub
End Class
The core Animation class
A new instance of the Animation class is initiated on creation of Form1, and this instance is used throughout the application.
The class contains two public methods and several private helper methods. The setSeed method is invoked when the ComboBox_SelectedIndexChanged fires. The animate method is invoked in a background thread, when the Button is clicked. The animation continues until there is no space left to grow, or the user changes the seed by selecting in the ComboBox.
Imports System.Threading
Public Class Animation
Private gridControl As exDGV
Private cellValues(99)() As Integer
Public cancelled As Boolean = False
Public Sub New(dgv As exDGV)
Me.gridControl = dgv
For r As Integer = 0 To 99
ReDim cellValues(r)(99)
Next
End Sub
Private Sub clear()
For r As Integer = 0 To 99
For c As Integer = 0 To 99
cellValues(r)(c) = 0
Next
Next
End Sub
Private Sub repaint()
If cancelled Then Return
For r As Integer = 0 To 99
For c As Integer = 0 To 99
If cellValues(r)(c) > 0 Then
gridControl.Rows(r).Cells(c).Style.BackColor = Color.Black
Else
gridControl.Rows(r).Cells(c).Style.BackColor = Color.White
End If
Next
Next
End Sub
Public Sub setSeed(ByVal x As Integer)
cancelled = True
clear()
Select Case x
Case 1 'diamond
For r As Integer = 47 To 48
For c As Integer = 49 To 50
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 49 To 50
For c As Integer = 49 To 50
cellValues(r)(c) = -1
Next c
Next r
For r As Integer = 49 To 50
For c As Integer = 51 To 52
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 51 To 52
For c As Integer = 49 To 50
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 49 To 50
For c As Integer = 47 To 48
cellValues(r)(c) = 1
Next c
Next r
Case 2 'square
For r As Integer = 48 To 51
For c As Integer = 48 To 51
cellValues(r)(c) = 1
Next c
Next r
Case 3 'cross
For r As Integer = 47 To 48
For c As Integer = 47 To 48
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 47 To 48
For c As Integer = 51 To 52
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 49 To 50
For c As Integer = 49 To 50
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 51 To 52
For c As Integer = 47 To 48
cellValues(r)(c) = 1
Next c
Next r
For r As Integer = 51 To 52
For c As Integer = 51 To 52
cellValues(r)(c) = 1
Next c
Next r
End Select
cancelled = False
repaint()
cancelled = True
End Sub
Public Sub animate(ByVal index As Integer)
cancelled = False
Dim l As Integer = 0
Dim t As Integer = 0
Dim r As Integer = 0
Dim b As Integer = 0
Select Case index
Case 1, 3
t = 47
b = 52
l = 47
r = 52
Case 2
t = 48
b = 51
l = 48
r = 51
End Select
Dim g As Integer = 2
Do While Not cancelled
For y As Integer = t To b
For x As Integer = l To r
If cancelled Then
Return
End If
If cellValues(y)(x) > 0 AndAlso cellValues(y)(x) < g Then
grow(g, y, x)
End If
Next x
Next y
'Pause for 50 milliseconds
Thread.Sleep(50)
For y As Integer = t To b
For x As Integer = l To r
If cancelled Then
Return
End If
If cellValues(y)(x) > 0 AndAlso cellValues(y)(x) < g Then
Dim count As Integer = surrounding(y, x)
If count < 2 Then
cellValues(y)(x) = -1
ElseIf count > 3 Then
cellValues(y)(x) = -1
End If
End If
Next x
Next y
'Pause for 50 milliseconds
Thread.Sleep(50)
For y As Integer = t To b
For x As Integer = l To r
If cancelled Then
Return
End If
If cellValues(y)(x) = -1 Then
Dim count As Integer = surrounding(y, x)
If count = 3 Then
cellValues(y)(x) = 1
End If
End If
Next x
Next y
'Pause for 50 milliseconds
Thread.Sleep(50)
t -= 1
l -= 1
b += 1
r += 1
g += 1
If t < 0 OrElse l < 0 Then
cancelled = True
End If
repaint()
Loop
End Sub
Private Sub grow(ByVal g As Integer, ByVal r As Integer, ByVal c As Integer)
If r > 0 Then
If cellValues(r - 1)(c) = 0 Then
cellValues(r - 1)(c) = g
End If
If c > 0 Then
If cellValues(r - 1)(c - 1) = 0 Then
cellValues(r - 1)(c - 1) = g
End If
End If
If c < 99 Then
If cellValues(r - 1)(c + 1) = 0 Then
cellValues(r - 1)(c + 1) = g
End If
End If
End If
If c > 0 Then
If cellValues(r)(c - 1) = 0 Then
cellValues(r)(c - 1) = g
End If
End If
If c < 99 Then
If cellValues(r)(c + 1) = 0 Then
cellValues(r)(c + 1) = g
End If
End If
If r < 99 Then
If cellValues(r + 1)(c) = 0 Then
cellValues(r + 1)(c) = g
End If
If c > 0 Then
If cellValues(r + 1)(c - 1) = 0 Then
cellValues(r + 1)(c - 1) = g
End If
End If
If c < 99 Then
If cellValues(r + 1)(c + 1) = 0 Then
cellValues(r + 1)(c + 1) = g
End If
End If
End If
End Sub
Private Function surrounding(ByVal r As Integer, ByVal c As Integer) As Integer
Dim count As Integer = 0
If r > 0 Then
If cellValues(r - 1)(c) > 0 Then
count += 1
End If
If c > 0 Then
If cellValues(r - 1)(c - 1) > 0 Then
count += 1
End If
End If
If c < 99 Then
If cellValues(r - 1)(c + 1) > 0 Then
count += 1
End If
End If
End If
If c > 0 Then
If cellValues(r)(c - 1) > 0 Then
count += 1
End If
End If
If c < 99 Then
If cellValues(r)(c + 1) > 0 Then
count += 1
End If
End If
If r < 99 Then
If cellValues(r + 1)(c) > 0 Then
count += 1
End If
If c > 0 Then
If cellValues(r + 1)(c - 1) > 0 Then
count += 1
End If
End If
If c < 99 Then
If cellValues(r + 1)(c + 1) > 0 Then
count += 1
End If
End If
End If
Return count
End Function
End Class
Conclusion
This is an example of OOP Programming which uses an instance of the core code object, and a graphical object (the exDGV), along with a Form.
Through simple coding, the DataGridView is rendered completely read-only. The Form contains only some GUI setup code and some eventhandlers. The Animation class can work with any seed (pattern) you choose to add to the three seeds that are provided.
Other Resources
Download (VB/C#) at: https://code.msdn.microsoft.com/Conways-Game-of-Life-75508f8f
Articles related to game programming
VB.Net - WordSearch
VB.Net - Vertex
VB.Net - Perspective
VB.Net - MasterMind
VB.Net - OOP BlackJack
VB.Net - Numbers Game
VB.Net - HangMan
Console BlackJack - VB.Net | C#
TicTacToe - VB.Net | C#
OOP Sudoku - VB.Net | C#
OctoWords VB.Net | C#