Skip to content

Instantly share code, notes, and snippets.

@awesmubarak
Last active November 11, 2017 18:53
Show Gist options
  • Save awesmubarak/b6181a647f0dfd0b3a561783d8e410b7 to your computer and use it in GitHub Desktop.
Save awesmubarak/b6181a647f0dfd0b3a561783d8e410b7 to your computer and use it in GitHub Desktop.
Notes for 2017 AS-Level Computer Science Skeleton program (VB)

Notes for 2017 AS-Level Computer Science Skeleton program (VB)

Table of contents

  1. Flowchart
  2. Prerelease commentary
  3. Key components
  4. Important snippets
  5. Advice
  6. Example tasks
  7. Credits
  8. Further reading

Prerelease files:

  1. EAD
  2. Raw data
  3. Syntax hiighlighted program
  4. Raw program
  5. Teacher notes
  6. Usage advice
  7. Usage guide

Flowchart

+────────────────────────────────────────────────────────────────────+
|                                                                    |
|                             +------+                               |
|                             | Main |                               |
|                             +---+--+                               |
|                                 |                                  |
|                          +------v-----+                            |
|                          | Simulation |                            |
|                          +------+-----+                            |
|  +-----------------+            |                                  |
|  | GetHowLongToRun +------------>                                  |
|  +-----------------+            |               +----------+       |
|                                 |            +--+ ReadFile |       |
|                        +--------v--------+   |  +----------+       |
|                        | InitializeField <---+                     |
|                        +--------+--------+   |  +----------------+ |
|                                 |            +--+ CreateNewField | |
|                                 |               +----------------+ |
|                        +--------v--------+                         |
|                        | SimulateOneYear <--------------------+    |
|                        +--------+--------+                    |    |
|                                 |                             |    |
|                                 |                             |    |
|                        +--------v-------+                     |    |
|                   +----> SimulateSpring |                     |    |
| +-------------+   |    +----------------+                     |    |
| | CountPlants +---+            |-------------+                |    |
| +-------------+   |    +-------v--------+    |                |    |
|                   +----> SimulateSummer |    |                |    |
|                        +----------------+    |   +---------+  |    |
|                                |-----------------> Display |  |    |
|   +-----------+        +-------v--------+    |   +---------+  |    |
|   | SeedLands +--------> SimulateAutumn |    |                |    |
|   +-----------+        +----------------+    |                |    |
|                                |-------------+                |    |
|                        +-------v--------+                     |    |
|                        | SimulateWinter |                     |    |
|                        +-------+--------+                     |    |
|                                |                              |    |
|                                +------------------------------+    |
|                                                                    |
+────────────────────────────────────────────────────────────────────+

Prerelease commentary

The program without comments can be found [here][pre-files-highlighted program].

System.IO allows access to files. Importaion occurs before the main module begins. To use reasonable indentaion for the rest of the document the End Module statement is also shown.

Imports System.IO

Module Module1
    ' [Rest of the code shown below]
End Module

Global constants will retain their value throughout the program. The first four are the characters that represent possible cell contents. The last two represent the size of the field.

Global constants are used because using literals can result in hard to read code. They result in numbers and symbols scattered around the program, and make maintanance harder because it's easy to forget what each symbol or number means. Global constants avoid these problems twofold: symbols change occurs in a single location and the value's representation is clear.

Const SOIL As Char = "."
Const SEED As Char = "S"
Const PLANT As Char = "P"
Const ROCKS As Char = "X"
Const FIELDLENGTH As Integer = 20
Const FIELDWIDTH As Integer = 35

The user can choose how long they want to run the simulation for. A prompt asks the user to select a number between 0 and 5, but no validation is present. The function returns years as an integer, and simulation() has to decide what to do with the year.

Function GetHowLongToRun() As Integer
    Dim Years As Integer
    Console.WriteLine("Welcome to the Plant Growing Simulation")
    Console.WriteLine()
    Console.WriteLine("You can step through the simulation a year at a time")
    Console.WriteLine("or run the simulation for 0 to 5 years")
    Console.WriteLine("How many years do you want the simulation to run?")
    Console.Write("Enter a number between 0 and 5, or -1 for stepping mode: ")
    Years = Console.ReadLine()
    Return Years
End Function

If the user chooses not to load their field from a file in InitialiseField() or if the file they select in ReadFile() is not an accesible a new field is generated. An array called Field stores the field as chars. The array contains many other arrays, making it two dimentsional. A visualisation of the array's two dimensional nature follows:

[
    [ ..P.......  ]
    [ .S...S....  ]
    [ ....P..X..  ]
    [ .P....S...  ]
    [ ...X...P..  ]
]

The earlier global constants determine the size of the array; the length determines the number of second-level arrays (y-axis) and the width determines the size of each second-level array (x-axis). Initially, every item in the array has the value SOIL. The central location is determined by floor dividing the field size by two. The central location then determines the initial seed location.

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Field(Row, Column) = SOIL
        Next
    Next
    Row = FIELDLENGTH \ 2
    Column = FIELDWIDTH \ 2
    Field(Row, Column) = SEED
    Return Field
End Function

If the user wants to load an existing file this function asks them to enter the file location, and attempts to read the file. If a file is not found or if the file is not accesible a new file is generated using the CreateNewField() sub. The user is not informed if a new field is created. If a file is found it is stored in an array called Field, as explained earlier.

Function ReadFile() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim FileName As String
    Dim FieldRow As String
    Dim FileHandle As IO.StreamReader
    Console.Write("Enter file name: ")
    FileName = Console.ReadLine()
    Try
        FileHandle = New IO.StreamReader(FileName)
        For Row = 0 To FIELDLENGTH - 1
            FieldRow = FileHandle.ReadLine
            For Column = 0 To FIELDWIDTH - 1
                Field(Row, Column) = FieldRow(Column)
            Next
        Next
        FileHandle.Close()
    Catch
        Field = CreateNewField()
    End Try
    Return Field
End Function

A prompt asks the user if they want to load an already existing file. If they choose not to, a new field is generated.

Function InitialiseField() As Char(,)
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim Response As String
    Console.Write("Do you want to load a file with seed positions? (Y/N): ")
    Response = Console.ReadLine()
    If Response = "Y" Then
        Field = ReadFile()
    Else
        Field = CreateNewField()
    End If
    Return Field
End Function

Shows information about the current state of the simulation. The information shown is the:

  • Current Season
  • Current Year
  • Field with row numbers

The PadLeft adds spaces to the left part of the row number. This means the string will always finish in the third column, like this:

  8|
  9|
 10|
 11|

Finishing in the third column allows up to 99 rows to be shown easily.

Sub Display(ByVal Field(,) As Char, ByVal Season As String, ByVal Year As Integer)
    Dim Row As Integer
    Dim Column As Integer
    Console.WriteLine("Season: " & Season & "  Year number: " & Year)
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Console.Write(Field(Row, Column))
        Next
        Console.WriteLine("|" & Str(Row).PadLeft(3))
    Next
    Console.WriteLine()
End Sub

Works out the number of plants in the simulation. It iterates through each item in the field uing a standard field iterator and checks if the item is a plant. If the item is a plant it increments NumberOfPlants. The number of plants is then displayed. The if/then statement makes sure the grammar is correct.

Sub CountPlants(ByVal Field(,) As Char)
    Dim Row As Integer
    Dim Column As Integer
    Dim NumberOfPlants As Integer
    NumberOfPlants = 0
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = PLANT Then
                NumberOfPlants += 1
            End If
        Next
    Next
    If NumberOfPlants = 1 Then
        Console.WriteLine("There is 1 plant growing")
    Else
        Console.WriteLine("There are " & NumberOfPlants & " plants growing")
    End If
End Sub

There are four seasons (#the more you know):

  • Spring: Every seed grows into a plant. If frost occurs every third plant dies.
  • Summer: If drought occurs every second plant dies.
  • Autumn: All plants drop seeds into adjacent cells.
  • Winter: All plants die.

In spring all seeds grown into plants. CountPlants() the displays the number of plants. A random number generator determines the occurance of frost. If frost occurs every third plants dies. A display informs the user about the frost, and CountPlants() displays the number of plants again.

Function SimulateSpring(ByVal Field As Char(,)) As Char(,)
    Dim Frost As Boolean
    Dim PlantCount As Integer
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = SEED Then
                Field(Row, Column) = PLANT
            End If
        Next
    Next
    CountPlants(Field)
    If Int(Rnd() * 2) = 1 Then
        Frost = True
    Else
        Frost = False
    End If
    If Frost Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 3 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a frost")
        CountPlants(Field)
    End If
    Return Field
End Function

A random number generator determines the amount of rainfall. If the amount of rainfall is low every second plant dies and a display shows the occurance of the drought. CountPlants() shows the number of plants. If a drought does not occur the number of plants is not displayed because the field is not affected.

Function SimulateSummer(ByVal Field(,) As Char) As Char(,)
    Dim RainFall As Integer
    Dim PlantCount As Integer
    RainFall = Int(Rnd() * 3)
    If RainFall = 0 Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 2 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a severe drought")
        CountPlants(Field)
    End If
    Return Field
End Function

Creates seeds. The function takes a location and checks if it is on the field. If the location is on the field a seed is placed on the corresponding location on the array.

    Function SeedLands(ByVal Field(,) As Char, ByVal Row As Integer, ByVal Column As Integer) As Char(,)
    If Row >= 0 And Row < FIELDLENGTH And Column >= 0 And Column < FIELDWIDTH Then
        If Field(Row, Column) = SOIL Then
            Field(Row, Column) = SEED
        End If
    End If
    Return Field
End Function

A seed is dropped on every location around a plant. Each location is passed to SeedLands(), which checks if the location is on the field, and plants seeds on on-field locations.

Function SimulateAutumn(ByVal Field(,) As Char) As Char(,)
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If FieldRow, Column) = PLANT Then
                Fiel = SeedLands(Field, Row - 1, Column - 1)
                Fiel = SeedLands(Field, Row - 1, Column)
                Fiel = SeedLands(Field, Row - 1, Column + 1)
                Fiel = SeedLands(Field, Row, Column - 1)
                Fiel = SeedLands(Field, Row, Column + 1)
                Fiel = SeedLands(Field, Row + 1, Column - 1)
                Fiel = SeedLands(Field, Row + 1, Column)
                Fiel = SeedLands(Field, Row + 1, Column + 1)
            End If
        Next
    Next
    Return Field
End Function

Kills all plants.

Function SimulateWinter(ByVal Field As Char(,)) As Char(,)
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = PLANT Then
                Field(Row, Column) = SOIL
            End If
        Next
    Next
    Return Field
End Function

The four season functions together simualte an entire year because a year has four seasons. After each month the Display() sub displays the state of the simulation.

Sub SimulateOneYear(ByVal Field(,) As Char, ByVal Year As Integer)
    Field = SimulateSpring(Field)
    Display(Field, "spring", Year)
    Field = SimulateSummer(Field)
    Display(Field, "summer", Year)
    Field = SimulateAutumn(Field)
    Display(Field, "autumn", Year)
    Field = SimulateWinter(Field)
    Display(Field, "winter", Year)
End Sub

Main function of the simulation. A prompt asks the user to input how long to run the simulation. The sub initializes the field if YearsToRun is not 0. Initialization occurs by asking the user if they want to generate a new field or use an existing one. If the field they choose nonexistant or invalid a new field is generated anyway. If the YearsToRun is not -1 the simulation runs however many times. The simulation enters stepping mode if YearsToRun is -1. The simulation goes one year at a time until the user chooses to exit using "x" or "X". The user informed when the simulation finished.

Sub Simulation()
    Dim YearsToRun As Integer
    Dim Continuing As Boolean
    Dim Response As String
    Dim Year As Integer
    Dim Field(FIELDWIDTH, FIELDLENGTH) As Char
    YearsToRun = GetHowLongToRun()
    If YearsToRun <> 0 Then
        Field = InitialiseField()
        If YearsToRun >= 1 Then
            For Year = 1 To YearsToRun
                SimulateOneYear(Field, Year)
            Next
        Else
            Continuing = True
            Year = 0
            While Continuing
                Year += 1
                SimulateOneYear(Field, Year)
                Console.Write("Press Enter to run simulation for another Year, Input X to stop: ")
                Response = Console.ReadLine()
                If Response = "x" Or Response = "X" Then
                    Continuing = False
                End If
            End While
        End If
        Console.WriteLine("End of Simulation")
    End If
    Console.ReadLine()
End Sub

Main procedure. Reseeds random number generator to provide different numbers each time and starts Simulation(), which handles the simulations.

Sub Main()
    Randomize()
    Simulation()
End Sub

Key components

Global constants

Name Type Description
SOIL Char Stores the character to represent soil: "."
SEED Char Stores the character to represent seeds: "S"
PLANT Char Stores the character to represent plants: "P"
ROCKS Char Stores the character to represent rocks: "X"
FIELDLENGTH Integer Stores length the of the field, which is 20 by default
FIELDWIDTH Integer Stores width the of the field, which is 35 by defualt

Local variables

I have not included location of decleration for these variables because the program may declare them in multiple routines.

Variable name Type Description
Column Integer Used to hold a selected column, often within a field iterator
Continuing Boolean Indicates continuation within Simulation()
Field(,) 2-D Char array Holds the field. Every entry is a seperate cell on the field
FieldName String Holds the name of the field when reading it in ReadFile
FieldRow String Stores each line read in from ReadFile
Frost Boolean Describes if a frost has occured
NumberOfPlants Integer Counts the number of plants on the field
PlantCount Integer Used in SimulateSummer() and SimulateWinter() to effect every n-th plant
Rainfall Integer Models ammount of rain in SimulateSummer()
Response String Holds user response to questions
Row Integer Used to hold a selected row, often within a field iterator
Year Integer Holds the year of simulation
Years Integer Holds the total number of years to run
YearsToRun Integer Holds the total number of years to run

Routines

Name Type Description
CountPlants procedure Counts and diplays the number of plants on the field
CreateNewField function Creates a new field, with only a seed at the center
Display procedure Displays the field along wiht key statistics
GetHowLongToRun function Asks the user for how long to run the simulation
InitialiseField function Generate new field or read from file
Main function Reseeds random number generator and calls other subs
ReadFile function Reads field from file
SeedLands function Plants seeds in given locations
SimulateAutumn function Simulates autumn
SimulateOneYear procedure Simulates a year by calling other simulators
SimulateSpring function Simulates spring
SimulateSummer function Simulates summer
SimulateWinter function Simulates winter
Simulation procedure Does everything

Table giving important details about each function:

Name Type Recieves Returns Called from
CountPlants Procedure Field(,) SimulateSpring, SimulateSummer
CreateNewField Function Field(,) Readfile, InitialiseField
Display Procedure Field(,), Season, Year SimulateOneYear
GetHowLongToRun Function Years Simulation
InitialiseField Function Field(,) Simulations
Main Function N/A
ReadFile Function Field(,) InitialiseField
SeedLands Function Field, Row, Column Field(,) SimulateAutumn
SimulateAutumn Function Field(,) Field(,) SimulateOneYear
SimulateOneYear Procedure Field(,), Year Simulation
SimulateSpring Function Field(,) Field(,) SimulateOneYear
SimulateSummer Function Field(,) Field(,) SimulateOneYear
SimulateWinter Function Field(,) Field(,) SimulateOneYear
Simulation Procedure Main

Important Snippets

Thisi s a collection of code snippets that may help during the exam.

The field iterator

This iterates through every cell in the field. The standard field iterator iterates through every cell by using the literal 0 and the size constants.

For Row = 0 To FIELDLENGTH - 1
    For Column = 0 To FIELDWIDTH - 1
        ' Some code
    Next
Next

Reusing the code allows a row iterator to iterate through rows:

Row = 17
For Column = 0 To FIELDWIDTH - 1
    ' Some code, may include Field(Row, Column)
Next

A column iterator can be made in the same way:

Column = 17
For Row = 0 To FIELDLENGTH - 1
    ' Some code, may include Field(Row, Column)
Next

The adjacency iterator

This goes through every cell around an origin cell.

For CheckRow = Row - 1 To Row + 1
    For CheckRow = Column - 1 To Column + 1
        ' [Some code]
    Next
Next

Note that this will iterate through the origin cell. To avoid this compare the location with the origin location, and do the code inside if they do not match.

For CheckRow = Row - 1 To Row + 1
    For CheckRow = Column - 1 To Column + 1
        If Field(Row, Column) <> Field(CheckRow, CheckRow) Then
            ' [Some code]
        End If
    Next
Next

Using these methods avoids having chunks of code like SimulateAutumn():

Function SimulateAutumn(ByVal Field(,) As Char) As Char(,)
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = PLANT Then
                Field = SeedLands(Field, Row - 1, Column - 1)
                Field = SeedLands(Field, Row - 1, Column)
                Field = SeedLands(Field, Row - 1, Column + 1)
                Field = SeedLands(Field, Row, Column - 1)
                Field = SeedLands(Field, Row, Column + 1)
                Field = SeedLands(Field, Row + 1, Column - 1)
                Field = SeedLands(Field, Row + 1, Column)
                Field = SeedLands(Field, Row + 1, Column + 1)
            End If
        Next
    Next
    Return Field
End Function

This iterator can also go through cells two cells near the origin:

For CheckRow = Row - 2 To Row + 2
    For CheckRow = Column - 2 To Column + 2
        ' [Some code]
    Next
Next

Always use field bounds validator to avoid outOfBounds errors.

The field bounds validator

I stole this snippet from SeedLands():

If Row >= 0 And Row < FIELDLENGTH And Column >= 0 And Column < FIELDWIDTH Then
    ' [Code goes here]
End If

This can simplified to eease unserstanding:

Dim ConditionRow as Boolean = Row >= 0 And Row < FIELDLENGTH
Dim ConditionColumn as Boolean = Column >= 0 And Column < FIELDWIDTH
If ConditionRow And ConditionColumn Then
    ' [Code goes here]
End If

Advice

White terminal

The windows command line is black by default. This may make it difficult to read command line content after printing the EAD. Making the command line's background white reduces the problem.

  1. Add a simple Console.Readline to the source code to prevent the terminal window from closing.

  2. Open a terminal window using f5.

  3. Right click on the title bar. The title bar is the top part of the window:

    +----------------------------------------------------+
    |            This section is the title bar        _X |
    +----------------------------------------------------+
    |                                                    |
    | This is the window's content.                      |
    |                                                    |
    |                                                    |
    |                                                    |
    |                                                    |
    |                                                    |
    |                                                    |
    |                                                    |
    +----------------------------------------------------+
    
  4. From the menu that now appears select properties. A new window should appear. Select the last tab, called colors. Change the background colour to white and the text colour to black.

Case select

Useselect case statements rather than if/then statements. This results in much cleaner code. Declare th statement using Select Case [variableBeingCompared].

Compare the following if/then statement:

If UserEnteredNumber = "one" Then
    ActualNumber = 1
Else If UserEnteredNumber = "two" Then
    ActualNumber = 2
Else If UserEnteredNumber = "three" Then
    ActualNumber = 3
Else If UserEnteredNumber = "four" Then
    ActualNumber = 4
Else If UserEnteredNumber = "five" Then
    ActualNumber = 5
Else If UserEnteredNumber = "six" Then
    ActualNumber = 6
Else If UserEnteredNumber = "ten" Then
    ActualNumber = 10
Else
    ActualNumber = 0

With this case/select statement equivilant:

Case Select UserEnteredNumber
    Case "one"
        ActualNumber = 1
    Case "two"
        ActualNumber = 2
    Case "three"
        ActualNumber = 3
    Case "four"
        ActualNumber = 4
    Case "five"
        ActualNumber = 5
    Case "six"
        ActualNumber = 6
    Case Else
        ActualNumber = 0
End Select

The case select statement is easier to read, and would be easier to maintain in the exam.

Variable names

Visual basic uses the UpperCamelCase (PascalCase) convetion. This involves joining strings of words into compound words, where each word starts with a capital letter.

This convention exists as comilers and interperators may consider spaces as seperators between tokens. Early languages including Lisp and COBOL allowed dashes (-) between words of identifiers (kebab-case). However, this was not acceptable in mathematical languages like FORTRAN where the hyphen is the subtraction symbol. The problems were exagerated by punchcards often supporting only capital letters and no symbols. In the late 1960s ASCII became more common, and terminals made writing code easier and more flexible. This allowed programmers to use uppercase and lowercase letters together. It also introduced the underscorce character (_). Some languages like C (and now C-influenced languages like Perl and Python) chose to seperate words using snake_case because the underscores look like whitespace, and this made code easier to read. Other programmers chose to use camelCase or UpperCamelCase, as they did not want what could be confused for whitespace in their variable names. Constants are often identified by their all-caps nature. Here are some examples of the same code in different languages with different conventions:

Python with snake_case.

def find_identifier_from_list(text_argument):
    # Example of snake_case in python:
    the_important_list = [1, 2, 3, 4, 5]
    print(text_argument)
    identifier_we_want = input("What identifier do you want to look for?")
    if identifier_we_want in the_important_list:
        identifier_in_list = True
    else:
        identifier_in_list = False
    return identifier_in_list

VisualBasic with PascalCase.

Function FindIdentifierFromList(ByVal TextArgument As String)
    ' Example of UpperCamelCase in visualBasic:
    Dim TheImportantList As Integer = [1, 2, 3, 4, 5] ' TODO: make this work.
    Dim IdentifierWeWant As String
    Dim IdentifierInList As Boolean
    Console.Writeline(TextArgument)
    Console.Writeline("What identifier do you want to look for?")
    IdentifierWeWant = Console.Readline()
    If TheImportantList.Contains(IdentifierWeWant) Then
        IdentifierInList = True
    Else
        IdentifierInList = False
    End If
    Return IdentifierInList
End Function

JavaScript with camelCase.

// Example of camelCase in JavaScript:
function findIdentifierFromList(textArgument) {
    var theImportantList = [1, 2, 3, 4, 5];
    console.log(textArgument);
    console.log("What identifier do you want to look for?");
    var identifierWeWant = readline();
    if (theImportantList.indexOf(identifierWeWant) >= 0) {
        identifierInList = true;
    } else {
        identifierInList = false;
    };
    return identifierInList;
}

Lisp with kebab-case (this is not the greatest example but lisp is a functional language).

(member (read-string "What identifier do you want to look for?") '(1 2 3 4 5))

Choosing which variable naming scheme to use is largely down to convention. Following a language's convention is important as it allows multiple developers to work on the same code with minimal friction. In the exam all variables, subs and functions should be in UpperCamelCase because the code was orignally written with in UpperCamelCase.

Incrementing

Incrementing a variable involves increasing its value by 1. It ma be used in a counter, for example to count the number of coccurances of a thing. There are two ways to increment a value.

The proper way looks as follows:

Dim NumberOfIterations As Integer
For i = 1 to 10
    NumberOfIterations += 1
Next

The wrong way looks like this:

Dim NumberOfIterations As Integer
For i = 1 to 10
    NumberOfIterations = NumberOfIterations + 1
Next

Using the proper incrementing method allows easier maintainance and makes debugging easier. Decrementation works in the same way using the -= operator.

Example tasks

These are my solutions to questions that may appear in the exams. They may not be perfect.

Short tasks

These tasks concern question 8 (6 marks) and question 9 (3 marks).

Generate rocks when creating a new field

This will randomly generate rocks when creating the field. It functions by generating a random number for each cell. The number is then multiplied by 15 and converted into an integer (effectively rounding it). The value can be modified to increase or reduce the chance of rocks. If the rounded value is a 0 the function places a rock, otherwise it places soil.

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim ChanceOfRock As Integer
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            ChanceOfRock = Int(Rnd() * 15)
            If ChanceOfRock = 0 Then
                Field(Row, Column) = ROCKS
            Else
                Field(Row, Column) = SOIL
            End If
        Next
    Next
    Row = FIELDLENGTH \ 2
    Column = FIELDWIDTH \ 2
    Field(Row, Column) = SEED
    Return Field
End Function

An alterantive method is to generate the field first, then iterate through each cell sperateley (but y dou?).

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim ChanceOfRock As Integer
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Field(Row, Column) = SOIL
        Next
    Next
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            ChanceOfRock = Int(Rnd() * 15)
            If ChanceOfRock = 0 Then
                Field(Row, Column) = ROCKS
            End If
        Next
    Next
    Row = FIELDLENGTH \ 2
    Column = FIELDWIDTH \ 2
    Field(Row, Column) = SEED
    Return Field
End Function

Show error message if file is not found

The exception handler already handles missing files. Adding code to the exception handler allows displaying a message when errors occur.

Function ReadFile() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim FileName As String
    Dim FieldRow As String
    Dim FileHandle As IO.StreamReader
    Console.Write("Enter file name: ")
    FileName = Console.ReadLine()
    Try
        FileHandle = New IO.StreamReader(FileName)
        For Row = 0 To FIELDLENGTH - 1
            FieldRow = FileHandle.ReadLine
            For Column = 0 To FIELDWIDTH - 1
                Field(Row, Column) = FieldRow(Column)
            Next
        Next
        FileHandle.Close()
    Catch
        Console.WriteLine("File not found, generating new field.")
        Field = CreateNewField()
    End Try
    Return Field
End Function

Allow user to choose disaster occurance

For summer, we can ask the user about the amount of rainfall.

Function SimulateSummer(ByVal Field(,) As Char) As Char(,)
    Dim RainFall As Integer
    Dim PlantCount As Integer
    Console.Writeline("How much rainfall has there been?")
    RainFall = Console.Readline
    If RainFall = 0 Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 2 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a severe drought")
        CountPlants(Field)
    End If
    Return Field
End Function

We can also directly ask about disaster occurance and save the response as a boolean.

Function SimulateSummer(ByVal Field(,) As Char) As Char(,)
    Dim Drought As Boolean
    Dim PlantCount As Integer
    Console.Writeline("Has there been a drought?")
    Drought = Console.Readline
    If Drought = True Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 2 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a severe drought")
        CountPlants(Field)
    End If
    Return Field
End Function

Frost is done in a similar way:

Function SimulateSpring(ByVal Field As Char(,)) As Char(,)
    Dim Frost As Boolean
    Dim PlantCount As Integer
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = SEED Then
                Field(Row, Column) = PLANT
            End If
        Next
    Next
    Console.writeline("Has there been frost?")
    Frost = Console.Readline
    If Frost Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 3 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a frost")
        CountPlants(Field)
    End If
    Return Field
End Function

Validate number of years to run

The number of years should be between -1 and 5 with appropriate error message. A Do...Loop ends when Years is a valid number of years. The do loop will display its contents at least once. The message is displayed if the number of years is not valid. The if statement will display a message if the number of years entered is not valid.

Function GetHowLongToRun() As Integer
    Dim Years As Integer
    Console.WriteLine("Welcome to the Plant Growing Simulation")
    Console.WriteLine()
    Console.WriteLine("You can step through the simulation a year
at a time")
    Console.WriteLine("or run the simulation for 0 to 5 years")
    Do
        Console.WriteLine("How many years do you want the simulation to run?")
        Console.Write("Enter a number between 0 and 5, or -1 for stepping mode: ")
        Years = Console.ReadLine()
        If 0 > Years Or Years > 5 Then
            Console.WriteLine("Please enter a number between -1 and 5")
        End If
    Loop Until -1 <= Years And Years <= 5
    Return Years
End Function

A simplified version can only validate the number of years being bellow 6:

Function GetHowLongToRun() As Integer
    Dim Years As Integer
    Console.WriteLine("Welcome to the Plant Growing Simulation")
    Console.WriteLine()
    Console.WriteLine("You can step through the simulation a year at a time")
    Console.WriteLine("or run the simulation for 0 to 5 years")
    Do
        Console.WriteLine("How many years do you want the simulation to run?")
        Console.Write("Enter a number between 0 and 5, or -1 for stepping mode: ")
        Years = Console.ReadLine()
        If 0 > Years Or Years > 5 Then
            Console.WriteLine("Please enter a number between -1 and 5")
        End If
    Loop Until Years <= 5
    Return Years
End Function

Change the size of the field

Since global constants control the field size changing their values on decleration will affect all instances. The constants retain their value throughout the program since the constants have a global scope.

Const FIELDLENGTH As Integer = 3
Const FIELDWIDTH As Integer = 1337

Allow the user to choose the first seed location

This example prompts the user to enter the row and column to plant the seed on. A plants is the planted on the field location corresponding to the input.

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Field(Row, Column) = SOIL
        Next
    Next
    Console.WriteLine("Please enter row to plants seed on")
    Row = Console.ReadLine
    Console.WriteLine("Please enter column to plant seed on")
    Column = Console.ReadLine
    Field(Row, Column) = SEED
    Return Field
End Function

The following examples adapts the above code to validate the input. The loop terminates once the input row and column are valid.

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Field(Row, Column) = SOIL
        Next
    Next
    Do
        Console.WriteLine("Please enter row to plants seed on")
        Row = Console.ReadLine
        Console.WriteLine("Please enter column to plant seed on")
        Column = Console.ReadLine
        If 0 > Years Or Years > 5 Then
            Console.WriteLine("Please enter a number between -1 and 5")
        End If
    Loop Until 0 <= Row <= FIELDLENGTH And 0 <= Column <= FIELDWIDTH
    Field(Row, Column) = SEED
    Return Field
End Function

This example will ask the user to choose if they want to choose the start location.

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim SeedLocationChoice As String
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Field(Row, Column) = SOIL
        Next
    Next
    Console.Write("Would you like to choose your initial seed location? (Y/N)")
    SeedLocationChoice = Console.ReadLine
    If SeedLocationChoice = "Y" Then
        Do
            Console.WriteLine("Please enter row to plants seed on")
            Row = Console.ReadLine
            Console.WriteLine("Please enter column to plant seed on")
            Column = Console.ReadLine
        Loop Until 0 <= Row <= FIELDLENGTH And 0 <= Column <= FIELDWIDTH
    Else
        Row = FIELDLENGTH \ 2
        Column = FIELDWIDTH \ 2
    End If
    Field(Row, Column) = SEED
    Return Field
End Function

Add file extention of file name without user input

The only modification in this case is FileName = Console.ReadLine() + ".txt". This will append .txt to the end of the end of the entered file name.

Function ReadFile() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim FileName As String
    Dim FieldRow As String
    Dim FileHandle As IO.StreamReader
    Console.Write("Enter file name: ")
    FileName = Console.ReadLine() + ".txt"
    Try
        FileHandle = New IO.StreamReader(FileName)
        For Row = 0 To FIELDLENGTH - 1
            FieldRow = FileHandle.ReadLine
            For Column = 0 To FIELDWIDTH - 1
                Field(Row, Column) = FieldRow(Column)
            Next
        Next
        FileHandle.Close()
    Catch
        Console.WriteLine("That's not a valid file")
        Field = CreateNewField()
    End Try
    RunLengthString(Field)
    Return Field
End Function

Modifying the message for the user will simplif their lives.

Function ReadFile() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim FileName As String
    Dim FieldRow As String
    Dim FileHandle As IO.StreamReader
    Console.Write("Enter file name (without .txt): ")
    FileName = Console.ReadLine() + ".txt"
    Try
        FileHandle = New IO.StreamReader(FileName)
        For Row = 0 To FIELDLENGTH - 1
            FieldRow = FileHandle.ReadLine
            For Column = 0 To FIELDWIDTH - 1
                Field(Row, Column) = FieldRow(Column)
            Next
        Next
        FileHandle.Close()
    Catch
        Console.WriteLine("That's not a valid file")
        Field = CreateNewField()
    End Try
    RunLengthString(Field)
    Return Field
End Function

Lowercase acceptance

InitialiseField() will reject lowercase ys. The easiest way to avoid this is to turn the input into all caps using the .ToUpper method.

Function InitialiseField() As Char(,)
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim Response As String
    Console.Write("Do you want to load a file with seed positions? (Y/N): ")
    Response = Console.ReadLine().ToUpper()
    If Response = "Y" Then
        Field = ReadFile()
    Else
        Field = CreateNewField()
    End If
    Return Field
End Function

The if then statement can also be modified to compare Response to both the uppercase and lowercase y.

Function InitialiseField() As Char(,)
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim Response As String
    Console.Write("Do you want to load a file with seed positions? (Y/N): ")
    Response = Console.ReadLine()
    If Response = "Y" Or Response = "y" Then
        Field = ReadFile()
    Else
        Field = CreateNewField()
    End If
    Return Field
End Function

The same techniques can be used for CreateNewField() aswell.

Function CreateNewField() As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim Field(FIELDLENGTH, FIELDWIDTH) As Char
    Dim SeedLocationChoice As String
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Field(Row, Column) = SOIL
        Next
    Next
    Console.Write("Would you like to choose your initial seed location? (Y/N)")
    SeedLocationChoice = Console.ReadLine.ToUpper()
    If SeedLocationChoice = "Y" Then
        Do
            Console.WriteLine("Please enter row to plants seed on")
            Row = Console.ReadLine
            Console.WriteLine("Please enter column to plant seed on")
            Column = Console.ReadLine
        Loop Until 0 <= Row <= FIELDLENGTH And 0 <= Column <= FIELDWIDTH
    Else
        Row = FIELDLENGTH \ 2
        Column = FIELDWIDTH \ 2
    End If
    Field(Row, Column) = SEED
    Return Field
End Function

Successful summer

Some summers are good. If RainFall is high the plants will be able to drop more seeds. I reused SimulateAutumn() as it already does this. Every seed then grows into a plant.

Function SimulateSummer(ByVal Field(,) As Char) As Char(,)
    Dim RainFall As Integer
    Dim PlantCount As Integer
    RainFall = Int(Rnd() * 3)
    If RainFall = 0 Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 2 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a severe drought")
        CountPlants(Field)
    ElseIf RainFall = 2 Then
        Field = SimulateAutumn(Field)
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = SEED Then
                    Field(Row, Column) = PLANT
                End If
            Next
        Next
        Console.WriteLine("There has been a successful summer")
    End If
    Return Field
End Function

Using this mod alongside the overpopulation simulation mod reuslts in all plants dying. Like capitalists, the plants will grow until they can't sustain themselves, and then they all die.

One way to avoid these problems is to limit opourtunity for most plants, and only allow the priveleged plants to grow.

Function SimulateSummer(ByVal Field(,) As Char) As Char(,)
    Dim RainFall As Integer
    Dim PlantCount As Integer
    RainFall = Int(Rnd() * 3)
    If RainFall = 0 Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 2 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a severe drought")
        CountPlants(Field)
    ElseIf RainFall = 2 Then
        PlantCount = 0
        Field = SimulateAutumn(Field)
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = SEED Then
                    PlantCount += 1
                    If PlantCount Mod 4 = 0 Then
                        Field(Row, Column) = PLANT
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a successful summer")
    End If
    Return Field
End Function

Simulate a flood if there is high rainfall in the summer

If the RainFall is 2, the program informs the user there has been a flood. Every 4th plant turns back in to soil. By expanding the if/then statement we can check if Rainfall is 2. The code within the block is mostly the same as the first code block. The modulo operation on PlantCount uses 4 instead of 2 to kill every fourth plant instead of second, and the message for the user informs them about a flood rather than a drought.

Function SimulateSummer(ByVal Field(,) As Char) As Char(,)

    Dim RainFall As Integer
    Dim PlantCount As Integer
    RainFall = Int(Rnd() * 3)
    If RainFall = 0 Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 2 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a severe drought")
        CountPlants(Field)
    ElseIf RainFall = 2 Then
        PlantCount = 0
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    PlantCount += 1
                    If PlantCount Mod 4 = 0 Then
                        Field(Row, Column) = SOIL
                    End If
                End If
            Next
        Next
        Console.WriteLine("There has been a flood")
        CountPlants(Field)
    End If
    Return Field
End Function

Long tasks

These tasks concern question 10 (11 marks) and question 11 (13 marks).

Create an option to run length encode part of the field.

It will start by asking the user for what row they want to encode. The variable currentCharacter is then given the value of the first item in the row. A do loop that will terminate when the last column is reached is used to iterate through each cell. An if/then statement will check if the current cell is the same as the currentCharacter, and wiill iterate numberOfCharacter if true. The column is then also iterated by one. If the character is different The previous number of the previous sequence of chacters is displayed alongside the character. The numberOfCharacter is reset to 0, and the currentCharacter is set to whichever character is now the subject. Call this sub is called when the user loads the field from a text file.

Sub RunLengthString(ByVal Field(,) As Char)
    Dim row As Integer
    Dim column As Integer = 0
    Dim currentCharacter As String
    Dim numberOfCharacter As Integer = 0
    Console.WriteLine("Which row would you like to encode?")
    row = Console.ReadLine
    currentCharacter = Field(row, column)
    Do
        If Field(row, column) = currentCharacter Then
            numberOfCharacter += 1
            column += 1
        Else
            Console.Write(currentCharacter & numberOfCharacter)
            numberOfCharacter = 0
            currentCharacter = Field(row, column)
        End If
    Loop Until column = FIELDWIDTH - 1
    Console.Write(currentCharacter & numberOfCharacter)
    Console.WriteLine()
End Sub

Create a sub to show the number of plants, rocks, seeds, soil.

The first 6 lines initialize variables. A standard field iterator iterates through every cell on the field. A select case statement check each cell's type, and iterates a counter for that type. The number of each value is then displayed. Call this sub at the end of the Display() using DisplayStatistics(Field).

Sub DisplayStatistics(ByVal Field(,) As Char)
    Dim Row As Integer
    Dim Column As Integer
    Dim NumberOfRocks As Integer = 0
    Dim NumberOfPlants As Integer = 0
    Dim NumberOfSoil As Integer = 0
    Dim NumberOfSeeds As Integer = 0
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Select Case Field(Row, Column)
                Case ROCKS
                    NumberOfRocks += 1
                Case PLANT
                    NumberOfPlants += 1
                Case SEED
                    NumberOfSeeds += 1
                Case SOIL
                    NumberOfSeeds += 1
            End Select
        Next
    Next
    Console.WriteLine("Statistics:")
    Console.WriteLine("  Number of plants: " & NumberOfPlants)
    Console.WriteLine("  Number of rocks: " & NumberOfRocks)
    Console.WriteLine("  Number of soils: " & NumberOfSoil)
    Console.WriteLine("  Number of seeds: " & NumberOfSeeds)
    Console.WriteLine()
End Sub

Simulate a bird flying down every winter and eating a row

The bird will then eat all the seed in a user-selected row. The program prompts the user to select a row for the bird to eat. A row iterator then iterates through all user-selected rows. All seeds are then turned into soil. NumberOfSeedsEaten iterates every time the bird eats a seed. Call this function after SimulateWinter but before Display in SimulateOneYear.

Function BirdFeeds(ByVal Field As Char(,)) As Char(,)
    Dim row As Integer
    Dim NumberOfSeedsEaten As Integer = 0
    Console.WriteLine("Which row does the bird eat?")
    row = Console.ReadLine
    For Column = 0 To FIELDWIDTH - 1
        If Field(row, Column) = SEED Then
            Field(row, Column) = SOIL
            NumberOfSeedsEaten += 1
        End If
    Next
    Console.WriteLine("  Number of seeds eaten: " & NumberOfSeedsEaten)
    Return Field
End Function

Simulate a forestfire

This will turn every cell around the origin to soil unless there is rock. The program prompts the user to enter the origin of the forest fire. An adjacency iterator then iterates through two cells around the origin cell. field bounds validator makes sure it is on the field. If the location is on the field and on the field it is brutally killed. Call this after the SimulateSummer call in SimulateOneYear.

Function ForestFire(ByVal Field(,) As Char) As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Console.WriteLine("What Row does the forest fire originate at?")
    Row = Console.ReadLine
    Console.WriteLine("What Column does the forest fire originate at?")
    Column = Console.ReadLine
    For CheckRow = Row - 2 To Row + 2
        For CheckColumn = Column - 2 To Column + 2
            If CheckRow >= 0 And CheckRow < FIELDLENGTH And CheckColumn >= 0 And CheckColumn < FIELDWIDTH Then
                If Field(Row, Column) = PLANT Then
                    Field(Row, Column) = SOIL
                End If
            End If
        Next
    Next
    Return Field
End Function

This modificaion will count the number of plants killed:

Function ForestFire(ByVal Field(,) As Char) As Char(,)
    Dim Row As Integer
    Dim Column As Integer
    Dim NumberOfPlants As Integer
    Console.WriteLine("What Row does the forest fire originate at?")
    Row = Console.ReadLine
    Console.WriteLine("What Column does the forest fire originate at?")
    Column = Console.ReadLine
    For CheckRow = Row - 2 To Row + 2
        For CheckColumn = Column - 2 To Column + 2
            If CheckRow >= 0 And CheckRow < FIELDLENGTH And CheckColumn >= 0 And CheckColumn < FIELDWIDTH Then
                If Field(Row, Column) = PLANT Then
                    Field(Row, Column) = SOIL
                    NumberOfPlants += 1
                End If
            End If
        Next
    Next
    Console.Writeline("A forest fire killed " & NumberOfPlants & " plants.")
    Return Field
End Function

Simulate overpopulation

Growth for the sake of growth is the ideology of a cancer cell - Edward Abbey

In the blistering heat of the late summer resources being to run low. Plants with more than 4 neighbours cannot fight off starvation, and crowds begin to die off in mass starvation.

A seperate function called OverPopulation will takes Field in the standard way. A variable called NumberOfSurroundingPlants will hold the number of plants surrounding each plant in the array. Every cell matches a cell in Field. I've used an extra array because killing plants as they are counted will favour the bottom left.

A standard field iterator is then used to iterate through each cell. If any cell is a plant an adjacency iterator is then introduce to loop through the cells around the plant. A field bounds validator will validate the location. If the location is on the field a an if/then statement checks whether the location is a plant, and iterates NumberOfSurroundingPlants if it is.

Once the loop terminates the program compares each value from NumberOfSurroundingPlants with MaximumNumberOfSurroundingPlants + 1 (the + 1 takes the origin cell into account). If the number of surrounding plants goes over the limit the plant dies.

Call this function at the end of SimulateSummer function using Field = OverPopulation(Field).

Function OverPopulation(ByVal Field(,) As Char) As Char(,)
    Dim NumberOfSurroundingPlants(FIELDLENGTH, FIELDWIDTH) As Integer
    Dim MaximumNumberOfSurroundingPlants As Integer = 4
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = PLANT Then
                For CheckRow = Row - 1 To Row + 1
                    For CheckColumn = Column - 1 To Column + 1
                        If CheckRow >= 0 And Row < FIELDLENGTH And CheckColumn >= 0 And Column < FIELDWIDTH Then
                            If Field(CheckRow, CheckColumn) = PLANT Then
                                NumberOfSurroundingPlants(Row, Column) += 1
                            End If
                        End If
                    Next
                Next
            End If
        Next
    Next
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If NumberOfSurroundingPlants(Row, Column) > MaximumNumberOfSurroundingPlants + 1 Then
                Field(Row, Column) = SOIL
            End If
        Next
    Next
    Return Field
End Function

If the validity was not important, you could kill plants during the standard iterator's function. Plants closer to the top-left postion (0, 0) would be more likely to die.

Function OverPopulation(ByVal Field(,) As Char) As Char(,)
    Dim NumberOfSurroundingPlants As Integer
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            NumberOfSurroundingPlants = 0
            For CheckRow = Row - 1 To Row + 1
                For CheckColumn = Column - 1 To Column + 1
                    If CheckRow >= 0 And Row < FIELDLENGTH And CheckColumn >= 0 And Column < FIELDWIDTH Then
                        If Field(CheckRow, CheckColumn) = PLANT Then
                            NumberOfSurroundingPlants += 1
                        End If
                    End If
                Next
            Next
            If NumberOfSurroundingPlants > 5 Then
                Field(Row, Column) = SOIL
            End If
        Next
    Next
    Return Field
End Function

A simple modification will count the number of plants killed and display that.

Function OverPopulation(ByVal Field(,) As Char) As Char(,)
        Dim NumberOfSurroundingPlants(FIELDLENGTH, FIELDWIDTH) As Integer
        Dim NumberOfPlantCasualties As Integer
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If Field(Row, Column) = PLANT Then
                    For CheckRow = Row - 1 To Row + 1
                        For CheckColumn = Column - 1 To Column + 1
                            If CheckRow >= 0 And Row < FIELDLENGTH And CheckColumn >= 0 And Column < FIELDWIDTH Then
                                If Field(CheckRow, CheckColumn) = PLANT Then
                                    NumberOfSurroundingPlants(Row, Column) += 1
                                End If
                            End If
                        Next
                    Next
                End If
            Next
        Next
        For Row = 0 To FIELDLENGTH - 1
            For Column = 0 To FIELDWIDTH - 1
                If NumberOfSurroundingPlants(Row, Column) > 5 Then
                    Field(Row, Column) = SOIL
                    NumberOfPlantCasualties += 1
                End If
            Next
        Next
        Console.WriteLine("This year " & NumberOfPlantCasualties & " plants died due to overpopulation")
        Return Field
    End Function

The two final if/then statements can be also joined to one line. I did not do this above because it results in a very long line which may wrap badly (as a rule program lines should not be longer than 80 characters. If they are reduce the amount of indentation or split a single line into multiple lines).

Function OverPopulation(ByVal Field(,) As Char) As Char(,)
    Dim NumberOfSurroundingPlants(FIELDLENGTH, FIELDWIDTH) As Integer
    Dim MaximumNumberOfSurroundingPlants As Integer = 4
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = PLANT Then
                For CheckRow = Row - 1 To Row + 1
                    For CheckColumn = Column - 1 To Column + 1
                        If CheckRow >= 0 And Row < FIELDLENGTH And CheckColumn >= 0 And Column < FIELDWIDTH And Field(CheckRow, CheckColumn) = PLANT Then
                            NumberOfSurroundingPlants(Row, Column) += 1
                        End If
                    Next
                Next
            End If
        Next
    Next
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If NumberOfSurroundingPlants(Row, Column) > MaximumNumberOfSurroundingPlants + 1 Then
                Field(Row, Column) = SOIL
            End If
        Next
    Next
    Return Field
End Function

Add moss

Moss can be created to populate rocks. First a new constant for the moss is created. The constant will hold the character representing the moss.

Const SOIL As Char = "."
Const SEED As Char = "S"
Const PLANT As Char = "P"
Const ROCKS As Char = "X"
Const MOSS As Char = "M"
Const FIELDLENGTH As Integer = 20
Const FIELDWIDTH As Integer = 35

A new sub is then created. It will use a standard field iterator to check if any cell is a rock or moss. A random number generator determines the moisture. Moss cannot survive in dry conditions. If the moisture is high enough, the cell rock will have moss grow on it. If the mositure is too low the moss will die. Most of the time the rock is not affected, and the previous conditions will pass along.

Function SimulateMoss(ByVal Field As Char(,)) As Char(,)
    Dim Moisture As Integer
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = ROCKS Or Field(Row, Column) = MOSS Then
                Moisture = Int(Rnd() * 6)
                If Moisture = 5 Or Moisture = 4 Then
                    Field(Row, Column) = MOSS
                ElseIf Moisture = 1 Then
                    Field(Row, Column) = ROCKS
                End If
            End If
        Next
    Next
    Return Field
End Function

You can call this every year by placing a call at the end of Display():

Sub Display(ByVal Field(,) As Char, ByVal Season As String, ByVal Year As Integer)
    Dim Row As Integer
    Dim Column As Integer
    Console.WriteLine("Season: " & Season & "  Year number: " & Year)
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            Console.Write(Field(Row, Column))
        Next
        Console.WriteLine("|" & Str(Row).PadLeft(3))
    Next
    Console.WriteLine()
    Field = SimulateMoss(Field)
End Sub

To simulate moss after only one season modify SimulateOneYear() to call SimulateMoss. This example uses winter.

Field = SimulateSpring(Field)
Display(Field, "spring", Year)
Field = SimulateSummer(Field)
Display(Field, "summer", Year)
Field = SimulateAutumn(Field)
Display(Field, "autumn", Year)
Field = SimulateWinter(Field)
Field = SimulateMoss(Field)
Display(Field, "winter", Year)

This modification will prevent plant death if the plant is around moss. A variable called AroundMoss describes if the plant is around moss or not. It is initially reset to false for every cell. An adjacency iterator is used to check if a plant is around moss or not. If any of the cells around it are moss AroundMoss s set to true. After the adjacency iterator checks every adjacent cell and if/then statement checks the state of AroundMoss and kills the plant if it is false.

Function SimulateWinter(ByVal Field As Char(,)) As Char(,)
    Dim AroundMoss As Boolean
    For Row = 0 To FIELDLENGTH - 1
        For Column = 0 To FIELDWIDTH - 1
            If Field(Row, Column) = PLANT Then
                AroundMoss = False
                For CheckRow = Row - 1 To Row + 1
                    For CheckColumn = Column - 1 To Column + 1
                        If CheckRow >= 0 And CheckRow < FIELDLENGTH And CheckColumn >= 0 And CheckColumn < FIELDWIDTH Then
                            If Field(CheckRow, CheckColumn) = MOSS Then
                                AroundMoss = True
                            End If
                        End If
                    Next
                Next
                If Not AroundMoss Then
                    Field(Row, Column) = SOIL
                End If
            End If
        Next
    Next
    Return Field
End Function

Credits

Skeleton Program for the AQA A1 Summer 2017 examination
this code should be used in conjunction with the Preliminary Material
written by the AQA AS1 Programmer Team
developed in the VB.Net 2008 environment

Stage : Pre
Version Number : 1.0
Original Author : N Barnes
Edited by : S Langfield
Date of edit : 15 January 2017

Thanks to Dr. Smith for teaching me the ways of Visual Basic.

Further reading

Lists of useful stuff, sorted by how much I like each site.

Visual Basic

Programming is slighly important for a programming exam.

Other programming languages

  • Codewars, programming challenges.
  • Free code camp, frontend and backend development course for professional programmers.
  • Codecademy, sets tasks and shows how to solve them.

Prerelease

Prerelease files

These are the OCR-supplied files.

Miscellaneous

Other things.


Creative Commons Licence
Notes for 2017 AS-Level Computer Science Skeleton program (VB) by Awes Mubarak is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment