How do I Store an Array Variable Inside of Another Array Variable?
This lesson describes how to create two dimensional arrays in the context of a simple board game. Data extraction and visualization examples are provided as part of the sample code.
Introduction
Data storage is a critical consideration when writing and running software. There are many ways to store data, ranging from single item variables to large scale multi-node database applications. The fashion by which data is stored and retrieved depends on a number of factors that are beyond the scope of this lesson.
Refer to: Data Grid for information on a more complex data representation in LiveCode.
This lesson describes how to arrange data in two dimensional arrays.
Let us assume we want to create a memory representation for a simple game like tic tac toe. This game has a 3X3 grid of squares that can each store one of three possible states. These states are: "O" (nought), "X" (cross) and " " (empty).
The most intuitive representation of the 3X3 grid is possibly to use an equal mapping in memory. This is a 3X3 memory storage grid representing the 3X3 game grid. We can create such a memory representation by using an array of arrays.
There are two fundamental ways by which to create two dimensional arrays in LiveCode:
1. First create a number of arrays that each stores one dimensional data, then store these arrays in a new array to create the second dimension.
2. Create a two dimensional array directly and store the data in that.
Creating an Array of Arrays
The following example shows you how to create a two dimensional array that is constructed by inserting one dimensional array data into another array. You have to create an array for each line of the board representation. You also have to create an array that holds the arrays that store individual board representation lines.
# declare the arrays we are going to populate
local tLineArray1, tLineArray2, tArrayInArray
# populate the one dimensional arrays tLineArray1 and tLineArray2
put "O" into tLineArray1[1]
put "X" into tLineArray1[2]
put " " into tLineArray2[1]
put "O" into tLineArray2[2]
# store the one dimensional arrays in tArrayInArray to create the two dimensional array
put tLineArray1 into tArrayInArray[1]
put tLineArray2 into tArrayInArray[2]
Note: We use this scaled down 2X2 example of the normal 3X3 tic tac toe representation for illustration purposes only. The next step uses the full 3X3 representation.
Creating a Two Dimensional Array
This example shows you how to create a two dimensional array by storing the board data directly in the array. There is no need to create more than one array structure.
# declare the array we are going to populate
local tMultiArray
# populate the two dimensional array tMultiArray with the relevant data
put "O" into tMultiArray[1][1]
put "X" into tMultiArray[1][2]
put " " into tMultiArray[1][3]
put " " into tMultiArray[2][1]
put "O" into tMultiArray[2][2]
put "X" into tMultiArray[2][3]
put "X" into tMultiArray[3][1]
put " " into tMultiArray[3][2]
put "O" into tMultiArray[3][3]
Retrieving Array Data
Once data is stored in a two dimensional array, it is useful to have a means of reading the data again. As we are using a grid-like mapping between the board representation and the array storage representation, it would be nice to print the data in a grid-like fashion. We can do so by traversing the rows and columns of the array in two nested loops.
The following code implements a generic printing algorithm that can produce a printable string for a wide range of two dimensional arrays. This algorithm can be used with both of the arrays that we created earlier in this lesson.
function displayArray @pArray
# create variables that point to the line and column of the array
local tLineItem, tColumnItem
# create a variable that stores the output for printing
local tPrintLine
put empty into tPrintLine
# loop through each row of the array
repeat for each element tLineItem in pArray
# loop through each column of the array
repeat for each element tColumnItem in tLineItem
# write content of the array to tPrintLine
put " " & tColumnItem after tPrintLine
end repeat
# insert a return after each row we have written to tPrintLine
put return after tPrintLine
end repeat
return tPrintLine
end displayArray
Note: It is common practice to use nested loops to process multi-dimensional array structures.
Printing the Board State to the Message Box
The following code prints the array tMultiArray to the LiveCode message box. As you can see, the columns are not properly aligned. This is because the font prints characters proportionally to their individual width. A space takes up less horizontal space than the O and X. This does not lend itself for easy reading.
-- this creates the output in the standard message box
-- notice how the output is not properly aligned
put displayArray (tMultiArray) into message
Printing the Board State to a Text Field
An alternative is to create a text field in LiveCode and use a font that prints every character at an identical width, such as the font Courier. As you can see in this example, the characters are now perfectly aligned.
The last thing we are missing are lines between the characters on the board. We can update our string generation function to provide this extra formatting.
-- create a text output field and set the font to Courier
-- this will allow your output to be aligned properly along the horizontal axis
put displayArray (tMultiArray) into field "OutField"
Note: This code requires you to create a text field in LiveCode with the name OutField.
Retrieving Formatted Array Data
This function builds on the previous data retrieval function. The code is fundamentally the same, with the addition of some extra code that creates lines between each grid of the board. This function is also generic and can process a number of different two dimensional arrays.
function displayArrayFormatted @pArray
# create variables that point to the line and column of the array
local tLineItem, tColumnItem
# create variables that store the horizontal separation line and the output for printing
local tSeparatorLine, tPrintLine
# create a variable that ensures we create the separation line only once
local tFirstCall
put empty into tPrintLine
put "+" into tSeparatorLine
put true into tFirstCall
# loop through each row of the array
repeat for each element tLineItem in pArray
# loop through each column of the array
repeat for each element tColumnItem in tLineItem
# write content of the array to tPrintLine
put "|" & tColumnItem after tPrintLine
# create tSeparatorLine with a length relative
# to the length of the first row in the array
if tFirstCall then put "-+" after tSeparatorLine
end repeat
# we would have created tSeparatorLine by now,
# so ensure we do not create it again
if tFirstCall then put false into tFirstCall
# append tSeparatorLine and a return to tPrintLine
put "|" & return & tSeparatorLine & return after tPrintLine
end repeat
# add tSeparatorLine to the front of tPrintLine
put tSeparatorLine & return before tPrintLine
return tPrintLine
end displayArrayFormatted
Printing the Formatted Board State to a Text Field
Now that the string generation function is updated, we can print a tic tac toe grid that is properly aligned and has dividing lines.
-- create a text output field and set the font to Courier
-- this will allow your output to be aligned properly along the horizontal axis
put displayArray (tMultiArray) into field "OutField"
Note: This code requires you to create a text field in LiveCode with the name OutField.
Paddy
can you read from a file into a multi-dimentional array?
Hanson Schmidt-Cornelius
Hi Paddy,
it very much depends on how you represent the data in the source file and how you want that data to be stored in the array.
For example, if you create a file that consists of lines of data and each line of data contains data entries that are separated by commas, then you could create a loop that creates a new array entry for each line.
In each new array entry you could create a new array that contains the comma separated elements of each line. You can use "split" to convert lists into arrays.
Have a look at the dictionary. You should find the following entries useful: "open file", "read from file", "close file" and "split".
Kind Regards,
Hanson