다음을 통해 공유


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:

  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population.
  4. 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...

↑ Back to top

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

 
↑ Back to top

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

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#