Question How to add more values to a 2D array

Mynotoar

Active member
Joined
Sep 27, 2012
Messages
28
Location
England
Programming Experience
Beginner
Hey again! I know I keep asking questions but you guys are so wonderful and I need some help ^^'.

I'm trying to make a program where you can move around a cursor on a 15x20 grid (the size can change dynamically,) and place coloured blocks (█) in any way you like to make a basic ASCII picture. I have a grid stored as a 2D array that runs on a loop: every time it first writes a blank grid full of empty spaces (-), then it defines a cursor which you use to place blocks, and then it waits for a keypress. If you press A or D it changes the colour of the cursor, if you press the arrowkeys it moves the cursor around, and I want it to place blocks when I press space - but I'm having trouble with it.


I have an array initialised, and every time it writes the grid it reads from that array and if there are any coordinates defined in it then it will place a block there. The declaration looks like this:
Dim PixelData(,) As Integer = {{3, 4, 6}, {7, 8, 1}}
It's a 2D array and it reads every block in the braces, using the first two numbers to work out the coordinates of where to place a block, and the third number is the colour, so {3, 4, 6} will place a block three down, four across, and the colour purple (ConsoleColor = 6.)


This works fine when initialising, but I don't want to initalise, I want to add to it, so that every time I press space a new set of braces is created using the two Cursor position values and the Colour value. I tried to figure out how to use ReDim, but I couldn't work out the syntax, and if I can I want to use something that doesn't eat up so much of my CPU.


Can anyone help me figure out the best way to add more values to the array? Someone mentioned using ArrayLists, which would be interesting, only I'd have to change everything to accommodate and I don't know how to use ArrayLists.

I'll post the code below, with some hazy comments.


VB.NET:
Sub ConsolePaint()
        Dim BorderColour As ConsoleColor = 1
        Dim BGColour As ConsoleColor = 0
        Dim BlankColour As ConsoleColor = 15
        Dim CursorColour As ConsoleColor = 1
        'Defines the colour of the border, background, blank spaces, and the cursor.


        Dim GridHeight As Integer = Console.WindowHeight - 5
        Dim GridWidth As Integer = Console.WindowWidth - 2
        'Normally defines the Grid at around 78x20...
        GridHeight = 15 : GridWidth = 20
        'But here I wanted a 15x20 grid.


        Dim GridData() As Integer = {GridHeight, GridWidth}
        'Defines the ColourGrid array according to the height and width values.
        Dim PixelData(,) As Integer = {{3, 4, 5}}
        'Fills the grid with pre-defined pixels. The first number is the down coordinate,
        'The second number is the across coordinate, and the third number is the colour.
        Dim ColourGrid(GridData(0), GridData(1)) As String
        'Creates the Grid itself.


        Dim BlankPixel As String = "-"
        Dim Block As String = "█"
        Dim CursorPixel As String = "█"
        'Defines the Blank Spaces as a hyphen, and for Pixels and the Cursor to be a Block.
        Dim CursorPos() As Integer = {0, 0}
        'The starting position of the Cursor.
        Dim Keypress As ConsoleKey
        Dim ValidKey As Boolean
        Do
            Console.Clear()
            For i = 1 To 5
                For j = 0 To 15
                    Console.ForegroundColor = j
                    Console.Write(Block)
                    'This creates a pretty multi-coloured border at the top.
                Next
            Next
            Console.ResetColor()
            Console.BackgroundColor = ConsoleColor.White
            Console.ForegroundColor = ConsoleColor.Black
            Console.Write("ConsolePaint")
            Console.Write(" - ←↑↓→: move cursor - A/D: change colour - M: Menu - Space: Place  ")
            Console.ResetColor()
            Console.Write("Colour: ")
            Console.ForegroundColor = CursorColour
            Console.Write(Block)
            'This highlights the current colour selected.
            Console.ResetColor()
            Console.Write(" [")
            Console.WriteLine(CursorColour & "]")
            Console.WriteLine()
            Console.ResetColor()
            For i = 0 To GridHeight
                For j = 0 To GridWidth
                    ColourGrid(i, j) = BlankPixel
                    'This fills the Grid with Blank Spaces.
                Next
            Next
            ColourGrid(CursorPos(0), CursorPos(1)) = CursorPixel
            'This creates the Cursor at the starting position.
            For i = 0 To GridWidth + 2
                Console.Write(Block)
                'This creates a top border two wider than the Grid.
            Next
            For i = 0 To GridHeight
                For j = 0 To GridWidth
                    If j = 0 Then
                        Console.WriteLine()
                        Console.Write(Block)
                        'This puts a block at the left of every row.
                    End If
                    Console.BackgroundColor = BGColour
                    If PixelData.GetLength(1) > 0 Then
                        If i = PixelData(0, 0) And j = PixelData(0, 1) Then
                            Console.ForegroundColor = PixelData(0, 2)
                            ColourGrid(PixelData(0, 0), PixelData(0, 1)) = Block
                            'This writes pre-defined blocks.
                        End If
                    End If
                    If i = CursorPos(0) And j = CursorPos(1) Then
                        Console.ForegroundColor = CursorColour
                        'This sets the colour of the cursor.
                    End If
                    Console.Write(ColourGrid(i, j))
                    'This is the actual thing that writes out everything.
                    Console.ResetColor()
                    If j = GridWidth Then
                        Console.Write(Block)
                        'This writes a block at the end of every line.
                    End If
                Next
            Next
            For i = 0 To GridWidth + 2
                If i = 0 Then
                    Console.WriteLine()
                End If
                Console.Write(Block)
                'This puts a block border at the bottom.
            Next
            Do
                'This do loop waits for user input, and based on the keypress,
                'moves the cursor around the grid. If the cursor cannot move,
                'it does nothing. If an invalid key is pressed, it does nothing.
                Keypress = Console.ReadKey(True).Key
                If Keypress = ConsoleKey.UpArrow Then
                    If CursorPos(0) - 1 < 0 Then
                        ValidKey = False
                    Else
                        CursorPos(0) -= 1
                        ValidKey = True
                    End If
                ElseIf Keypress = ConsoleKey.DownArrow Then
                    If CursorPos(0) + 1 > GridHeight Then
                        ValidKey = False
                    Else
                        CursorPos(0) += 1
                        ValidKey = True
                    End If
                ElseIf Keypress = ConsoleKey.LeftArrow Then
                    If CursorPos(1) - 1 < 0 Then
                        ValidKey = False
                    Else
                        CursorPos(1) -= 1
                        ValidKey = True
                    End If
                ElseIf Keypress = ConsoleKey.RightArrow Then
                    If CursorPos(1) + 1 > GridWidth Then
                        ValidKey = False
                    Else
                        CursorPos(1) += 1
                        ValidKey = True
                    End If
                ElseIf Keypress = ConsoleKey.A Then
                    If CursorColour - 1 < 0 Then
                        CursorColour = 15
                    Else
                        CursorColour -= 1
                    End If
                    ValidKey = True
                ElseIf Keypress = ConsoleKey.D Then
                    If CursorColour + 1 > 15 Then
                        CursorColour = 0
                    Else
                        CursorColour += 1
                    End If
                    ValidKey = True
                ElseIf Keypress = ConsoleKey.Spacebar Then
                    'THIS IS THE PROBLEM AREA WHERE I HAVEN'T WORKED OUT WHAT TO DO.
                Else
                    ValidKey = False
                End If
            Loop Until ValidKey = True
        Loop
    End Sub

Thank you!
 
Arrays are fixed-size so you can't arbitrarily add elements to them. You can "resize" an array by creating a new array of the new size and copying the elements from the old array but that is something that should be generally avoided.

I would definitely recommend using a collection but definitely not an ArrayList. No new code written in .NET 2.0 or later should be using an ArrayList. The first thing you should do is define a type that represents one "row" in your array, e.g.
Friend Class Pixel
    Public Property X() As Integer
    Public Property Y() As Integer
    Public Property ConsoleColor() As Integer
End Class
You can then use a List(Of T), where T is your type, to store an arbitrary number of items of that type. The List can be initialised and/or it can grow and shrink dynamically as you Add and Remove items, e.g.
Dim pixels As New List(Of Pixel) From {New Pixel With {.X = 3, .Y = 4, .ConsoleColor = 6},
                                       New Pixel With {.X = 7, .Y = 8, .ConsoleColor = 1}}

'...

pixels.Add(New Pixel With {.X = 4, .Y = 2, .ConsoleColor = 5})
Accessing and setting existing items is just like for a 1D array.

Note that you also add a constructor to that class to make instantiation less verbose.
 
Hey guys - I found a solution, but it was sort of cheating, really. In any case, it works and I'm happy with it. Instead of creating a new value in the existing array, I used a second array with the same number of values as the first, that stored colour information for each pixel. It wrote the BackgroundColor of each pixel in the original array using those colours as reference. I'll show you a short snippet as the bulk of the code is still far too long to make anybody read.

VB.NET:
For i = 0 To GridHeight
            For j = 0 To GridWidth
                HiddenDataGrid(i, j) = 16
            Next
Next
'This first For loop fills the hidden grid with numbers set to 16. It'll only read colour information if it's between 0 and 15.
For i = 0 To GridHeight
                For j = 0 To GridWidth
                    ColourGrid(i, j) = BlankPixel
                    'This fills the Grid with Blank Spaces.
                Next
            Next
            ColourGrid(CursorPos(0), CursorPos(1)) = CursorPixel
            'This creates the Moveable Cursor at the starting position.
            Console.ForegroundColor = BorderColour
            For i = 0 To GridWidth + 2
                Console.Write(Block)
                'This creates a top border two wider than the Grid.
            Next
            Console.ResetColor()
            For i = 0 To GridHeight
                Console.ForegroundColor = BorderColour
                Console.WriteLine()
                Console.Write(Block)
                Console.ResetColor()
                For j = 0 To GridWidth
                    Console.BackgroundColor = BGColour
                    If HiddenDataGrid(i, j) <> 16 Then
                        Console.BackgroundColor = HiddenDataGrid(i, j)
                    End If
                    If i = CursorPos(0) And j = CursorPos(1) Then
                        Console.ForegroundColor = CursorColour
                        'This sets the colour of the cursor.
                    End If
                    Console.Write(ColourGrid(i, j))
                    'This is the actual thing that writes out everything.
                    Console.ResetColor()
                Next
                Console.ForegroundColor = BorderColour
                Console.Write(Block)
                Console.ResetColor()
            Next
 
Back
Top