Question about breaking a nested loop
BlitzMax Forums/BlitzMax Beginners Area/Question about breaking a nested loop
| ||
Hi, I am trying to break the program flow from a nested loop. I have one routine which searches whole 2D map to see if there are empty squares on the map and on those empty squares I will put a monster. When I find the empty square I like to break whole loop . not even search for the next square. Global Search_map_x:Byte Global Search_map_y:Byte Global Search_map_tmp_x:Byte Global Search_map_tmp_y:Byte Global Levels:String[51, 42, 42, 5] Global Monster_creation_not_allowed:Byte For Search_map_y = 1 To 37 For Search_map_x = 1 To 38 If Levels[Current_Level, Search_map_x, Search_map_y, 1] = "00" And Levels[Current_Level, Search_map_x, Search_map_y, 2] = "00" And Levels[Current_Level, Search_map_x, Search_map_y, 3] = "00" And Levels[Current_Level, Search_map_x, Search_map_y, 4] = "00" Then Monster_creation_not_allowed = 0 Search_map_tmp_x = Search_map_x Search_map_tmp_y = Search_map_y Exit EndIf If Levels[Current_Level, Search_map_x, Search_map_y, 1] <> "00" And Levels[Current_Level, Search_map_x, Search_map_y, 2] <> "00" And Levels[Current_Level, Search_map_x, Search_map_y, 3] <> "00" And Levels[Current_Level, Search_map_x, Search_map_y, 4] <> "00" Then Monster_creation_not_allowed = 1 EndIf Next Next If Monster_creation_not_allowed = 1 Then 'Here is the not allowing monster message endif 'The rest code bellow creates the monster at position Search_map_tmp_x and Search_map_tmp_y We assume the map is already filled with walls and other stuff. I try to check if there is an empty square on the map to put a monster and then before put the monster , I check if there is and another one square empty to put its respawn position. The "00" are the empty squares and other from "01" to "99" are occupied squares. The search_map_x and The search_map_x variables , scan the map and when the coordinates of those search_map_x and The search_map_x in levels[] array have an empty square "00" then I would like to interrupt whole loop and go to next code bellow. It doesn't seems to work. Any idea how to break any level nested loop. Thank you. |
| ||
Do you mean something like that:Local Found=FALSE For Search_map_y = 1 To 37 For Search_map_x = 1 To 38 If ... Then Found=TRUE EndIf If Found=TRUE Then Exit ..... Next If Found=TRUE Then Exit Next If Found=TRUE Monster_creation_not_allowed = 0 Search_map_tmp_x = Search_map_x Search_map_tmp_y = Search_map_y Endif |
| ||
I did a very simple maze game a couple of years back and put the listing into a forum post as it's pretty short. There's an example of how to exit a maze search in that. http://www.blitzbasic.com/Community/posts.php?topic=101884 |
| ||
Hiya, BRL have already thought of this and BlitzMax can use Exit Labels, documented under BlitzMax Help->Language->Program Flow->Exit and Continue Eg:- Strict Local x,y #Leave For x = 0 Until 20 For y = 0 Until 15 If x = 10 And y = 10 Exit Leave Next Next Print x Print y Hope it helps. |
| ||
Hi Takis76. Here's another way to look at the code:'bytes chnged to ints - they are internally anyway? 'lets make these smaller and simpler to view 'Global Search_map_x:Int 'Global Search_map_y:int 'Global Search_map_tmp_x:int 'Global Search_map_tmp_y:int Global map_x:Int Global map_y:Int Global lvl:Int = 0 'changed from string to int as int's are faster ;) and allow for some other optimisations 'I will assume that a result of 0 means thet we can put a monster there - see original = "00". 'I will further assume that there can not be a negative result Global Levels:int[51, 42, 42, 5] Global Monster_creation_allowed:int 'version 1 - for loops converted to repeats Print "Version 1 - does the same as original code" map_y = 1 Local foundx:Int = -1 Local foundy:Int = -1 Repeat map_x = 1 Repeat If Levels[lvl, map_x, map_y, 1] + Levels[lvl, map_x, map_y, 2] + Levels[lvl, map_x, map_y, 3] + Levels[lvl, map_x, map_y, 4] = 0 Then foundx = map_x foundy = map_y End if map_x :+ 1 Until map_x > 38 Or foundx > -1 map_y :+ 1 Until map_y > 37 Or foundx > -1 If foundx > -1 then Print "monster can be placed at "+foundx+" "+foundy Else Print "monster can't be placed" End If 'version 2 print Print "Version 2 - picks random position in a level" 'any repeat should have the additions of a trap - to make sure it doesn't loop indefinately. we'll set the trap to trip at 100 repeats Local trap:Int = 0 repeat map_x = Rand(1, 38) map_y = Rand(1, 37) If Levels[lvl, map_x, map_y, 1] + Levels[lvl, map_x, map_y, 2] + Levels[lvl, map_x, map_y, 3] + Levels[lvl, map_x, map_y, 4] = 0 Then foundx = map_x foundy = map_y End If trap :+ 1 Until foundx > -1 Or trap > 100 If foundx > -1 And trap =< 100 Then Print "monster can be placed at "+foundx+" "+foundy Else Print "monster can't be placed" End If it looks bigger because there are two different methods for finding what you are wanting. There is also more error checking and print's so you can see what is going on :) Also because there are no for loops, you won't need to exit in the same way. Use loops for things you know. Try not to use exits! While and repeat can give better results :) |
| ||
@col I am in SuperStrict mode so labels , gotos and gosubs not allowed. Very interesting code , I will report what I have done when I change my code. Thank you very much for now. |
| ||
You can use loop labels in SuperStrict, as per the above example. |
| ||
Heh, you learn something new everyday, never had any idea that blitz had loop labels :) |
| ||
This code idea worked in my game. (This idea was nice)For Search_map_y = 1 To 37 For Search_map_x = 1 To 38 If ... Then Found=TRUE EndIf If Found=TRUE Then Exit ..... Next If Found=TRUE Then Exit Next Also the idea with repeat of AdamStrange is nice too . but the code is more complicated. As my original code used for loops I used the first idea with exits. As I understood , I need to put exit in both loops. I was put exit only in one loop. I fixed my code and now I break whole loop and I check if there are empty squares to put the monster and the monster respawn position. (Each monster needs 2 empty squares , one for the monster position and one for respawn position) It worked perfectly. Thank you very much. |
| ||
You could wrap it in a function or method within a type and simply Return from the function or method when your done. If you need return values from the function you can get fancy and use VarLocal found_x:Int Local found_y:Int If Found(found_x,found_y) Then Put_Monster(found_x,found_y) Function Found:Int(x:Int Var, y:Int Var) For Search_map_y = 1 To 37 For Search_map_x = 1 To 38 If ... Then x = Search_map_x y = Search_map_y Return True EndIf ..... Next Next Return False End Function |