Can I resize an arry within a function?

BlitzMax Forums/BlitzMax Beginners Area/Can I resize an arry within a function?

Abomination(Posted 2006) [#1]
[edit] resize an ARRAY (of course)
And if I can; HOW?
I don't mind if the content is destroyed or not.
Or do I have to use banks for this purpose?

Is there a way to figure this kind of stuff out (an easy way) without bothering my fellow Blitzers? Some GOOD documentation somewhere?

t.i.a. for all your reactions. :)


Diablo(Posted 2006) [#2]
read about array Slices .. theres a section in the languages ref page, heres the jist of it...
Local a[200]	'initialize a[] to 200 elements
a=a[50..150]	'extract middle 100 elements of a[]
a=a[..50]     	'extract first 50 elements of a[]
a=a[25..]	'extract elements starting from index 25 of a[]
a=a[..]		'copy all elements of a[]
a=a[..200]	'resize a[] to 200 elements



I guess if you want to resize within a functon, just pass the array to the function...


tonyg(Posted 2006) [#3]
Help / Language / Slices in your documentation.
Wiki has some good stuff on arrays as well...
Wiki slices


Abomination(Posted 2006) [#4]
thx, but i'm afraid slices won't do.
I don't want to create a huge array (just in case)when the "user" just needs a small one.
I was thinking more in the line of REDIM, or something.
(i'm getting the feeling i can start rewriting things, using banks) or are there other solutions?


CS_TBL(Posted 2006) [#5]
slices *will* do .. what're you affraid of? :P

local smurf:int[10] ' <- now 10 smurfs
local gargamel:int=1337
smurf=smurf[..gargamel] ' <- now 1337 smurfs
smurf=smurf[..1] ' <- 1 smurf left :(



Abomination(Posted 2006) [#6]
I'm afraid I meant resizing a multi-dimensional array.
I should have been more clear on that point.
Thanks anywho...


Perturbatio(Posted 2006) [#7]
you can't unfortunately use slices on a multi-dimensional array, you can however use them on an Array of Arrays


Byteemoz(Posted 2006) [#8]
If you don't need to keep the content, you can also do that:
Local a:Int[,,] ' array variable for a three-dimensional array
a = New Int[2,2,2] ' create small array
a = New Int[99,99,99] ' replace with big array
a = New Int[2,2,2] ' and small again
-- Byteemoz


FlameDuck(Posted 2006) [#9]
Is there a way to figure this kind of stuff out (an easy way) without bothering my fellow Blitzers?
Try it?


Abomination(Posted 2006) [#10]
Aah, to try and fail miserably! Story of my life!

[edit] (as to not to bump) njagnjag...
@Byteemoz:
That realy works like a charm!
	
Global array:Int[,,]  

resize(1,2,3)
resize(4,5,6)

Function resize(A:int,B:int,C:int)
   array = New Int[A,B,C] 	
End Function



abelian_grape(Posted 2010) [#11]
Since that BlitzWiki link is dead above I thought I'd resurrect this thread since I am looking to do a similar thing.

I am making a map editor, and I read in a thread elsewhere (I think some suggestions on jesse's map editor) that being able to re-size a map on the fly while editing would be helpful since not everyone knows exactly how large their map has to be before they begin creating it.

So the map is basically a 2D array of tiles. I would like it if I could expand the map on the fly by either adding a row or column to the top, bottom, or either side of the map. Now it sounds like slicing works only for 1D arrays, so can anyone explain a relatively painless way to add in a row or column on any edge of the map? It's critical that I be able to add the row or column on ANY side, not just the bottom/right sides where the map would expand naturally if I edited the array size.

-muffins


Czar Flavius(Posted 2010) [#12]
It will be slow but ok for one-off use. Store the map in a temporary variable. Then create the map variable afresh, but with bigger dimensions. Then copy the old map back into the new map. Using Ints for example
'creating the map
Global map_x = 10, map_y = 10
Global map:Int[,] = New Int[map_x, map_y]

'resizing the map
Local temp:Int[,] = map, temp_x = map_x, temp_y = map_y
map_x = 20, map_y = 20 'new map size
map = New Int[map_x, map_y]
'copy old map into new map
For Local x:Int = 0 Until temp_x
	For Local y:Int = 0 Until temp_y
		map[x, y] = temp[x, y]
	Next
Next

To insert rows at the beginning of the map, simply offset the x and y in the loop by an amount.


abelian_grape(Posted 2010) [#13]
This code makes sense, but it generates a runtime error: Unhandled Exception:Can't insert Null object into list.

Here's my code:

	
		''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
		'Function MapResize()
		'Parameters: 
		'Returns: None
		'Expands or shrinks the map in the direction of the arrow key pressed
		''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
		Function MapResize()
			
			Local temp:TTile[,] = map
			Local temp_x:Int = xMap
			Local temp_y:Int = yMap
			
		
		'Expands the map
			If KeyDown(KEY_EQUALS) And KeyDown(KEY_RIGHT)
				xMap:+1
				map = New TTile[xMap, yMap]
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			ElseIf KeyDown(KEY_EQUALS) And KeyDown(KEY_LEFT)
				xMap:+1
				map = New TTile[xMap, yMap]
				For Local x:Int = 1 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			ElseIf KeyDown(KEY_EQUALS) And KeyDown(KEY_UP)
				yMap:+1
				map = New TTile[xMap, yMap]
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 1 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			ElseIf KeyDown(KEY_EQUALS) And KeyDown(KEY_DOWN)
				yMap:+1
				map = New TTile[xMap, yMap]
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
		'Shrinks the map
			ElseIf KeyDown(KEY_MINUS) And KeyDown(KEY_RIGHT)
				xMap:-1
				map = New TTile[xMap, yMap]
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			ElseIf KeyDown(KEY_MINUS) And KeyDown(KEY_LEFT)
				xMap:-1
				map = New TTile[xMap, yMap]
				For Local x:Int = 1 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			ElseIf KeyDown(KEY_MINUS) And KeyDown(KEY_UP)
				yMap:-1
				map = New TTile[xMap, yMap]
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 1 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			ElseIf KeyDown(KEY_MINUS) And KeyDown(KEY_DOWN)
				yMap:-1
				map = New TTile[xMap, yMap]
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x, y]
					Next
				Next
			EndIf
			
		End Function



_Skully(Posted 2010) [#14]
I am making a map editor, and I read in a thread elsewhere (I think some suggestions on jesse's map editor) that being able to re-size a map on the fly while editing would be helpful since not everyone knows exactly how large their map has to be before they begin creating it.


I store my map's as relative references so there is no map boundary or array size issues. Thats non-standard but in your editor environment it removes the "I need more map" problem since you can expand it any time.


Jesse(Posted 2010) [#15]
@muffins
there is no Tlist execution in that code(function) so the problem is some where else not in that specific part of the program. The problem is that you are moving a null object into a Tlist object and is whats causing the error.

you know, I like how you are implement the resizing and I might just apply it in mine. OO makes it so easy to implement and modify code.

[rant]
it is interesting how programmers that know how to do something will tell you that their software or applications can do something but don't show sample code or at least some pseudo code. somehow I understand their worries. if they show someone how to do something, how are they going to make money on their creations when every other coder will become a potential business threat. that is not so bad but what really bothers me is that some programmers here will say, you are doing this wrong, my way is better, but dear not show how they do it. That is not the kind of help us posting in the begginers section need.
Those who post in the beginners section don't want someone to brag about what they can do.
I would rather not have any comments posted in my thread than have someone brag about what they can do and not really help.

note that I only commented this here because muffins brought an interesting point about a comment that wasn't resolve in a thread that was posted for help in debugging and not for criticism.

if I offended somebody here I am sorry, it's not my intention but that's how I feel and if the shoe fits...
[/rant]


abelian_grape(Posted 2010) [#16]
I'll have to agree with Jesse here...while it can be seen as helpful to more advanced programmers that have the capacity to generate the type of code that is being protected, to a beginner, we are no better off than before we posted our concerns. I'm glad this was addressed, and thank you to everyone who takes time out of their day to help or contribute thoughts to these threads, because they truly do make a difference to not only those who needed the help, but to others who come along and find that they, too, have the same issues while learning.

@Jesse
I did find it strange that the issue was related to a TList, but I figured that for some reason BlitzMax treated an array as a sort of "rigid, indexed" TList, so I thought that's what caused the problem. Thankfully, my code (found here: Need help debugging) only invokes one function call of "AddLast" in the entire file, which is where my debugger points me. Specifically, the block of code is in a Type's function (The TTile type's function UpdateTiles() which gets called every iteration of the main game loop). The block looks like this:

			'This function will clear the drawing queue, cycle through the map array and determine what tiles are currently visible,
			'and then add the visible tiles to the drawing queue
			Function UpdateTiles()
				
				
				draw_list.Clear() 'reset the drawing list
				For Local y:Int = 0 To (yMap - 1)		'For every tile
					For Local x:Int = 0 To (xMap - 1)
						If visible(x,y)		'If the tile is visible, then add it to the end of the list so the tiles in the foreground are drawn last
							ListAddLast(draw_list:TList, map[x,y])
						End If
									
					Next
				Next
				
			End Function


Which is peculiar, because it is saying that map[x,y] which is a TTile object is now null. I'm not sure what is becoming Null within the scope of the MapResize() function.


_Skully(Posted 2010) [#17]
it is interesting how programmers that know how to do something will tell you that their software or applications can do something but don't show sample code or at least some pseudo code.


I'm guessing that was directed at me? Anyway, I was just posting a metholodology not a pre-packaged solution. Once could easily state that its interesting how "new" developers want everything handed on a silver platter too. Part of learning to code is learning how to implement an idea since ultimately thats what coding is.

I understand their worries. if they show someone how to do something, how are they going to make money on their creations when every other coder will become a potential business threat

Bah... thats the paranoid coders perceptions only. The coders capable of making their own will do so for their own uses if they see an advantage to the method/idea. Code snippets are no big deal, its when pretty much the whole system needs to be posted to satisfy someone's "questions" that eyebrows raise. And that happens alot... its also a matter of time. Do people working on their own projects have time to post pseudo code? Not always, so they post the concept and leave it to newby coder to ask further questions later on if they can't figure it out.


Jesse(Posted 2010) [#18]

I'm guessing that was directed at me?



not necessarily, you were just the trigger. ;)


Once could easily state that its interesting how "new" developers want everything handed on a silver platter too. Part of learning to code is learning how to implement an idea since ultimately thats what coding is.


not always the case and it sure can make it a lot easier not to have to reinvent the wheel every time one sits down to code. Another thing is that when someone post code or pseudo code I 99% of the time do not use it as is. I get ideas from it and modify it or redesign it for my own needs.

another thing is that one needs to look at how the person in need are coding. I did not see him asking for a free meal as you can see he figured it out by his own means. All he needed was some help figuring out some commands that were not clearly explained in the documentation.
Ideas come a dime a dozen and I am sure he has his share of. the question is, does he really need one more undefined solutions?

so they post the concept and leave it to newby coder to ask further questions later on if they can't figure it out.


if you say so but if thats how I feel I usually let them know. I have seen comments in other threads as well as in mine were programmers come throw a stone and hide, never comeback to really help.

As I said you were just the trigger.


Czar Flavius(Posted 2010) [#19]
Skully did give a link to some more information about his method which is nice of him.


Jesse(Posted 2010) [#20]
:)
you are a good guy Czar.


abelian_grape(Posted 2010) [#21]
bump


abelian_grape(Posted 2010) [#22]
Well I revised my code a bit and for the expansion part of it, this is what I have:



To keep things easy when I thought about this on paper, I restricted myself to an initial 3 tile x 3 tile map and tried to expand it in all directions. This code, in principle, should be able to do that. However, when I actually run this code, only the expansion rightward and expansion downward actually work. Leftward and upward don't work, but if you use them, and then do an expansion downward or rightward, it produces some REAL strange results. Any thoughts?


Jesse(Posted 2010) [#23]
I haven't really looked at your TTile but I think you need to adjust every old TTile x and y position everytime you expand left or up.

this is not too important but I also think you are overthinking the for loops:

				For Local x:Int = 1 Until (temp_x + 1)
					For Local y:Int = 0 Until temp_y
						map[x, y] = temp[x - 1, y]
					Next
				Next

this would be simpler:
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x+1, y] = temp[x, y]
					Next
				Next



abelian_grape(Posted 2010) [#24]
I guess I am not understanding why anything would need to be adjusted for the expansion. For rightward and downward expansion, the original map is staying put, and either an extra column or extra row is being tacked on. In this sense, the old map can be transferred to the new map sequentially beginning at index (0,0) and stopping at the last tile of the original map.

Leftward and upward expansion are a bit more awkward. First, you copy the old map into a temp map. Then what you do is create an entirely new map (one new column if leftward expand, one new row if upward expand). Let's consider leftward expansion.

I want the leftmost column to be blank, and the rest of the map to look like my old map. What I have to do is fill in this new map by first initializing the first column with new, blank tiles (which is why I'm calling my TTile.Create() function before copying over the old map). Then I need to run through the remaining tiles in the new map, whose area should have the same dimensions as my old map. So what my code does is start with the second column in the new map, and copy the first column of the old map into this column. Then it proceeds to the next column, and so on until it reaches the end. So by copying it over how my code is set up, there should be no need to do any "readjustments" because the act of copying the old map over is doing the adjustment in the process of traversing my old 2D array and entering each of the entries into a new entry in the new 2D array.

This picture might help:


So what my program should do is start with the map on the left. (Colors match up with colors in the old and new maps. Let's pretend that each is a perfect square.) Then it should create the left most column of the map on the right, and then it copies over RED, GREEN, BROWN, then ORANGE, BLUE, PINK, then YELLOW, VIOLET, GRAY. Therefore each old tile is in a new position since the For...Next loops automatically readjusted the coordinates.

As for the two bits of code you posted, they are equivalent. It's just a matter of how you think about them. Neither is more "difficult" in the sense that one is doing more work than the other, nor is one more extraneous. One may be more conceptually difficult than other for one person, I just wrote it initially how it made sense to me since that's how I chose to index things, whereas it was more natural for you to index things the other way. It's like changing indexes in a summation or a finitely indexed Cartesian product...two very different looking things can represent the same outcome, it's just a matter of a shift in index.

For example:



Jesse(Posted 2010) [#25]

As for the two bits of code you posted, they are equivalent. It's just a matter of how you think about them....



obviously. I just thought it was something you would want to make easier to understand for someone else to read. Specially someone who is helping you and don't really know anything about your code and simple, we all strive for simplicity. Anyway, no big deal.

I feel as if you are getting a little tense(frustrated maybe) And I feel you are directing the frustration at me. If you don't want me help you no big deal but so far I have been the main one who have been pointing out the things that need to be fixed and so far I have not been wrong and I doubt this is the exception.

I am going to give it a last chance if you don't get it, I'll step aside and let someone else help you.

when you first create the TTile array you assign the first tile x = 0, y = 0 from the For/Next loop.
when you expand to the right, you give the right tile " x= xMap" this is correct but when you expand to the left you move the first tile to the second position but its value is still x=0 and y=0 and this is when the problem starts. When you create the tile to the left you give it the value x=0 and y =0 now as the two tiles next to each other have the same x and y values they are displayed overlaped. if you keep on expanding it to the left or top the values will continue to be stacked and you will see less and less of the map.

I hope this is clear to you, if not, I hope someone else can explain it to you better.


abelian_grape(Posted 2010) [#26]
I'm sorry if I was not polite or appeared to be directing frustration at you. I did not intend to do so and I apologize for the error in communicating it. You've been nothing but helpful to me and I really appreciate the time you have spent helping me :) I certainly am frustrated at the problem itself though, and I will try to use the frustration constructively.

I think I understand what you have said, though my misunderstanding of the problem itself is not allowing me to see where I have made the error. I feel as though when I read through my code it all looks like how it should be even though it isn't, which is the source of my frustration here. Should I be adjusting the x, y coordinates in my TTile.Create() function parameters?


Jesse(Posted 2010) [#27]

Should I be adjusting the x, y coordinates in my TTile.Create() function parameters?


Yes. but only when expanding to the left or top. See if this make sense to you:
			'Expand leftward	
			ElseIf KeyDown(KEY_LEFT)
				FlushKeys()
				xMap:+1
				map = New TTile[xMap, yMap]
				
				For Local i:Int = 0 Until temp_y
					map[0, i] = TTile.Create(0, i, blank_id, passableToggle)
				Next
				
				For Local x:Int = 0 Until temp_x
					For Local y:Int = 0 Until temp_y
						map[x+1, y] = temp[x, y]
						map[x+1,y].x = x+1    '**********************************************
					Next
				Next



abelian_grape(Posted 2010) [#28]
Yes, I finally understand! haha, I was completely overlooking the fact that my TTile type had x, y fields and that these fields actually defined where the tiles were because in fact, I do not have anything that looks like map[x, y].x or map[x, y].y in my code, so up until now, they were not serving a purpose. Thank you so much for your help :)

-muffins