Microsoft Small Basic

Program Listing: FCL390
'***************************************************************************************
'Sample program to demonstate the use of arrays
'An array is a list of related data that can be added to, deleted from, modified and accessed to perform a task
'***************************************************************************************
TextWindow.Show()
'
'An array of numbers, we want to store odd raddom numbers
'
'The hard way without arrays
num1 = 1+2*Math.GetRandomNumber(100)
num2 = 1+2*Math.GetRandomNumber(100)
num3 = 1+2*Math.GetRandomNumber(100)
num4 = 1+2*Math.GetRandomNumber(100)
num5 = 1+2*Math.GetRandomNumber(100)
output = "Five random odd numbers stored the hard way"
comment()
TextWindow.WriteLine(num1)
TextWindow.WriteLine(num2)
TextWindow.WriteLine(num3)
TextWindow.WriteLine(num4)
TextWindow.WriteLine(num5)
next()
'The easy way with arrays
For i = 1 To 10
num[i] = 1+2*Math.GetRandomNumber(100)
EndFor
output = "Ten random odd numbers stored the easy way"
comment()
For i = 1 To 10
TextWindow.WriteLine(num[i])
EndFor
next()
'
'The number of elements in an array may be changing or not known, we can see how many there are
'
TextWindow.Clear()
For i = 1 To 10+Math.GetRandomNumber(10)
val[i] = Math.GetRandomNumber(100)
EndFor
output = "We have stored "+Array.GetItemCount(val)+" random numbers between 1 and 100"
comment()
TextWindow.WriteLine("Index Value")
For i = 1 To Array.GetItemCount(val)
TextWindow.Write(i+" ") ' we break the write into 2 statements to prevent it reporting i+val[i]
TextWindow.WriteLine(val[i])
EndFor
next()
avg = 0
For i = 1 To Array.GetItemCount(val)
avg = avg+val[i]
EndFor
avg = 0.01*Math.Floor(100*avg/Array.GetItemCount(val)+0.5) ' rounded to nearest (hence the +0.5) 2 decimal places
TextWindow.WriteLine("Their average value is "+avg)
TextWindow.WriteLine("")
'
'We can see if the array contains a value or not
'
output = "Enter a number to see if it is in the array"
comment()
num = TextWindow.ReadNumber()
If (Array.ContainsValue(val,num) = "True") Then
TextWindow.WriteLine(num+" is in the array")
Else
TextWindow.WriteLine(num+" is not in the array")
EndIf
next()
'
'We can delete entries in the array - delete the even numbers here
'
count = Array.GetItemCount(val) ' We set this variable first because we are change the number of elements in the array inside the loop
For i = 1 To count
If (Math.Remainder(val[i],2) = 0) Then
val[i] = ""
EndIf
EndFor
output = "There are "+Array.GetItemCount(val)+" odd numbers left in the array"
comment()
TextWindow.WriteLine("")
'
'We have deleted the even numbers but the indexes of the remaining odd numbers have not changed
'
output = "The array now has empty deleted indexes"
comment()
TextWindow.WriteLine("Index Value")
For i = 1 To count
TextWindow.Write(i+" ")
If (Array.ContainsIndex(val,i)) Then
TextWindow.WriteLine(val[i])
Else
TextWindow.WriteLine("Deleted")
EndIf
EndFor
next()
'
'We need to reorder the array to change the array indexes to be sequetial
'This is not obvious, so be careful deleting array values, without remembering that the indexes are unchanged
'If the indices are just numbers, the use the code below
'
i = 1 'Index of unshuffled (original) array
j = 1 'New index values for shuffled up array
While (j <= Array.GetItemCount(val))
If (Array.ContainsIndex(val,i) = "True") Then
val[j] = val[i]
If (i <> j) Then
val[i] = ""
EndIf
j = j+1
EndIf
i = i+1
EndWhile
output = "The full odd number array after re-ordering indexes sequentially"
comment()
TextWindow.WriteLine("Index Value")
For i = 1 To Array.GetItemCount(val)
TextWindow.Write(i+" ")
TextWindow.WriteLine(val[i])
EndFor
next()
'
'Arrays indexed by strings
'These have the advantage that we don't have to worry about indexing when we add and delete values,
'but we cannot use inedexed loops (For i =1 To...) to access them
'
TextWindow.Clear()
age["Fred"] = 21
age["Mary"] = 28
age["David"] = 36
output = "Unindexed string arrays are easy to use, but less powerful"
comment()
TextWindow.WriteLine("Mary is "+age["Mary"]+" years old")
TextWindow.WriteLine("Fred is "+age["Fred"]+" years old")
TextWindow.WriteLine("David is "+age["David"]+" years old")
next()
'Multi-dimesional string arrays with indexing (more powerful but awkward to delete and maintain sequetial indexing)
'Name
contact[1]["name"] = "Fred"
contact[2]["name"] = "Mary"
contact[3]["name"] = "David"
contact[4]["name"] = "Sam"
contact[5]["name"] = "Helen"
'Age
contact[1]["age"] = 21
contact[2]["age"] = 28
contact[3]["age"] = 36
contact[4]["age"] = 42
contact[5]["age"] = 18
'City
contact[1]["city"] = "Paris"
contact[2]["city"] = "Prague"
contact[3]["city"] = "New York"
contact[4]["city"] = "Mombia"
contact[5]["city"] = "Johannesburg"
'We store the data in the array contact (like a database)
'And access the data using the index
output = "String arrays with some index are easier to use"
comment()
For i = 1 To Array.GetItemCount(contact)
TextWindow.WriteLine(contact[i]["name"]+" is "+contact[i]["age"]+" years old and lives in "+contact[i]["city"])
EndFor
next()
'Add some entries
newindex = Array.GetItemCount(contact)+1
contact[newindex]["name"] = "Rolf"
contact[newindex]["age"] = 73
contact[newindex]["city"] = "Melbourne"
newindex = Array.GetItemCount(contact)+1
contact[newindex]["name"] = "Bruce"
contact[newindex]["age"] = 51
contact[newindex]["city"] = "Hong Kong"
output = "Some added entries"
comment()
For i = 1 To Array.GetItemCount(contact)
TextWindow.WriteLine(contact[i]["name"]+" is "+contact[i]["age"]+" years old and lives in "+contact[i]["city"])
EndFor
next()
'Delete some entries
count = Array.GetItemCount(contact) 'we use count here because we are deleteing more than 1 entry and Array.GetItemCount(contact) is changing inside the loop
For i = 1 To count
If (contact[i]["name"] = "Mary" Or contact[i]["name"] = "Bruce") Then
contact[i] = ""
EndIf
EndFor
'shuffle indexes to run from 1 to number of entries in array (sequential indexing)
i = 1
j = 1
While (j <= Array.GetItemCount(contact))
If (Array.ContainsIndex(contact,i) = "True") Then
contact[j] = contact[i]
If (i <> j) Then
contact[i] = ""
EndIf
j = j+1
EndIf
i = i+1
EndWhile
output = "Delete Mary and Bruce"
comment()
For i = 1 To Array.GetItemCount(contact)
TextWindow.WriteLine(contact[i]["name"]+" is "+contact[i]["age"]+" years old and lives in "+contact[i]["city"])
EndFor
next()
'
'Sort by name alphabetically
'
var = "name"
sortString()
output = "Sorted by name alphabetically"
comment()
For i = 1 To Array.GetItemCount(contact)
TextWindow.WriteLine(contact[i]["name"]+" is "+contact[i]["age"]+" years old and lives in "+contact[i]["city"])
EndFor
next()
'
'Sort by city alphabetically
'
var = "city"
sortString()
output = "Sorted by city alphabetically"
comment()
For i = 1 To Array.GetItemCount(contact)
TextWindow.WriteLine(contact[i]["name"]+" is "+contact[i]["age"]+" years old and lives in "+contact[i]["city"])
EndFor
next()
'
'Sort by age
'
var = "age"
sortNumber()
output = "Sorted by age"
comment()
For i = 1 To Array.GetItemCount(contact)
TextWindow.WriteLine(contact[i]["name"]+" is "+contact[i]["age"]+" years old and lives in "+contact[i]["city"])
EndFor
next()
'
'Back to something simpler : 2D number arrays
'An array of squares in a graphics window - 'Pairs'
'
TextWindow.Hide()
GraphicsWindow.BackgroundColor = "LightBlue"
nrow = 2*2 'must be even number of boxes - it is PAIRS
ncol = 2*2
size = 50
For i = 1 To nrow
For j = 1 To ncol
Xbox[i][j] = 1.5*size*i
Ybox[i][j] = 1.5*size*j
Cbox[i][j] = -1 ' unset colour just now
found[i][j] = 0 'flag for found pairs
EndFor
EndFor
'Set pairs of boxes (cards) with the same random colour
For i1 = 1 To nrow
For j1 = 1 To ncol
If (Cbox[i1][j1] < 0) Then
'i1,j1 isel not set so set it
Cbox[i1][j1] = GraphicsWindow.GetRandomColor()
'find another random box i2,j2 not already set
i2 = Math.GetRandomNumber(nrow)
j2 = Math.GetRandomNumber(ncol)
While (Cbox[i2][j2] >= 0)
i2 = Math.GetRandomNumber(nrow)
j2 = Math.GetRandomNumber(ncol)
EndWhile
Cbox[i2][j2] = Cbox[i1][j1]
EndIf
EndFor
EndFor
'
'Change colour of selected box (delete and recreate it)
'See graphics demo for mouse event control
'
GraphicsWindow.MouseDown = OnMouseDown
Sub OnMouseDown
mx = GraphicsWindow.MouseX
my = GraphicsWindow.MouseY
clicked = 1
EndSub

'Draw intial view of coloured squares (pairs), show for 5 sec, then turn to blank side
For i = 1 To nrow
For j = 1 To ncol
GraphicsWindow.BrushColor = Cbox[i][j]
Sbox[i][j] = Shapes.AddRectangle(size,size)
Shapes.Move(Sbox[i][j],Xbox[i][j],Ybox[i][j])
EndFor
EndFor
Program.Delay(5000)

back = "White"
GraphicsWindow.BrushColor = back
For i = 1 To nrow
For j = 1 To ncol
Shapes.Remove(Sbox[i][j])
Sbox[i][j] = Shapes.AddRectangle(size,size)
Shapes.Move(Sbox[i][j],Xbox[i][j],Ybox[i][j])
EndFor
EndFor

clicked = 0
nclicked = 0
nfound = 0
While (nfound < nrow*ncol)
If (clicked = 1) Then
For i = 1 To nrow
For j = 1 To ncol
'Only consider unfound boxes
If (mx >= Xbox[i][j] And mx <= Xbox[i][j]+size And my >= Ybox[i][j] And my <= Ybox[i][j]+size) Then
If (found[i][j] = 0 And nclicked < 2) Then
Sound.PlayClickAndWait()
'Turn over a card to the coloured side and note its location in isel,jsel
Shapes.Remove(Sbox[i][j])
GraphicsWindow.BrushColor = Cbox[i][j]
Sbox[i][j] = Shapes.AddRectangle(size,size)
Shapes.Move(Sbox[i][j],Xbox[i][j],Ybox[i][j])
nclicked = nclicked+1
isel[nclicked] = i
jsel[nclicked] = j
Else
'Don't click an already found pair
Sound.PlayBellRingAndWait()
EndIf
EndIf
EndFor
EndFor
'Two turned over - leave them showing if they are the same, otherwise wait 2 sec and turn then back over
If (nclicked = 2) Then
If (Cbox[isel[1]][jsel[1]] <> Cbox[isel[2]][jsel[2]]) Then
Program.Delay(2000)
For k = 1 To 2
i = isel[k]
j = jsel[k]
Shapes.Remove(Sbox[i][j])
GraphicsWindow.BrushColor = back
Sbox[i][j] = Shapes.AddRectangle(size,size)
Shapes.Move(Sbox[i][j],Xbox[i][j],Ybox[i][j])
EndFor
Else
For k = 1 To 2
i = isel[k]
j = jsel[k]
found[i][j] = 1
EndFor
nfound = nfound+2
EndIf
nclicked = 0
EndIf
clicked = 0
EndIf
EndWhile
Program.Delay(2000)
'
'Finish up
'
GraphicsWindow.Clear()
GraphicsWindow.BackgroundColor = "Black"
gw = GraphicsWindow.Width
gh = GraphicsWindow.Height
GraphicsWindow.FontSize = 80
While (clicked = 0)
For i = 1 To 100 ' Do 100 of these for every update of the black text to speed it up
GraphicsWindow.SetPixel(Math.GetRandomNumber(gw),Math.GetRandomNumber(gh),GraphicsWindow.GetRandomColor())
EndFor
GraphicsWindow.BrushColor = "Black"
GraphicsWindow.DrawBoundText(20,20,gw-20,"All Done with ARRAYS. Click to EXIT.")
EndWhile

Program.End()
'
'Utility to output a comment
'
Sub comment
TextWindow.ForegroundColor = "Yellow"
TextWindow.WriteLine(output)
TextWindow.ForegroundColor = "White"
EndSub
'
'Utility subroutine to move on in the TextWindow
'
Sub next
TextWindow.ForegroundColor = "Red"
TextWindow.WriteLine("")
TextWindow.Read()
TextWindow.ForegroundColor = "White"
EndSub
'
'Sort contacts array alphabetically
'
Sub sortString
For i = 1 To Array.GetItemCount(contact)-1
For j = i+1 To Array.GetItemCount(contact)
iVar = contact[i][var]
jVar = contact[j][var]
iValue = 0
jValue = 0
char = 0
While (iValue = jValue)
char = char+1
iValue = Text.GetCharacterCode(Text.GetSubText(iVar,char,1))
jValue = Text.GetCharacterCode(Text.GetSubText(jVar,char,1))
EndWhile
If (jValue < iValue) Then
store = contact[i]
contact[i] = contact[j]
contact[j] = store
EndIf
EndFor
EndFor
EndSub
'
'Sort contacts array by number
'
Sub sortNumber
For i = 1 To Array.GetItemCount(contact)-1
For j = i+1 To Array.GetItemCount(contact)
iVar = contact[i][var]
jVar = contact[j][var]
If (jVar < iVar) Then
store = contact[i]
contact[i] = contact[j]
contact[j] = store
EndIf
EndFor
EndFor
EndSub