- Home /
Infinite loop when I try to generate randomly a 2D dungeon..
Hey everyone ! I'm trying to make a little game unsing random genaration. I have a c++ code which works very well but when I import and "convert" this code in C# in unity it doesn't work..
The problem appears when I'm trying to prevent rooms collisions...
So there is the code of the function :
for(int i = 0; i < tabRoom.Length; i++)
{
if(i == 0)
{
tabRoom[i].Init(UnityEngine.Random.Range(iMinWidthRoom, iMaxWidthRoom),UnityEngine.Random.Range(iMinHeightRoom, iMaxHeightRoom),iMapWidth,iMapHeight);
tabRoom[i].PosOk = true;
}
else
{
/*While the new room collides with another room we change her position*/
while(tabRoom[i].PosOk == false)
{
/*The function init changes the room's position and the room's size randomly*/
tabRoom[i].Init(UnityEngine.Random.Range(iMinWidthRoom,iMaxWidthRoom),
UnityEngine.Random.Range(iMinHeightRoom,
iMaxHeightRoom),iMapWidth,iMapHeight);
//We check if there is a collision with the new room or not
for(int j = 0; j < tabRoom.Length; j++)
{
if((tabRoom[j].iXpos > tabRoom[i].iXpos + tabRoom[i].iWidth )
|| ((tabRoom[j].iXpos) + tabRoom[j].iWidth < tabRoom[i].iXpos )
|| (tabRoom[j].iZpos > tabRoom[i].iZpos + tabRoom[i].iHeight )
|| (tabRoom[j].iZpos + tabRoom[j].iHeight < tabRoom[i].iZpos))
{
tabRoom[i].PosOk = true; //No collision
}
else
{
//j = tabRoom.Length;
tabRoom[i].PosOk = false; //Collision
}
}
}
}
}
So I hope someone will can help me because I have no idea... :/
Answer by Rodriguez547 · Nov 17, 2015 at 05:22 PM
I found the solution, I'm completly stupid...
for(int i = 0; i < tabRoom.Length; i++)
{
if(i == 0)
{
tabRoom[i].Init(UnityEngine.Random.Range(iMinWidthRoom, iMaxWidthRoom),UnityEngine.Random.Range(iMinHeightRoom, iMaxHeightRoom),iMapWidth,iMapHeight);
tabRoom[i].PosOk = true;
}
else
{
/*While the new room collides with another room we change her position*/
while(tabRoom[i].PosOk == false)
{
tabRoom[i].Init(UnityEngine.Random.Range(iMinWidthRoom, iMaxWidthRoom),UnityEngine.Random.Range(iMinHeightRoom, iMaxHeightRoom),iMapWidth,iMapHeight);
//We check if there is a collision with the new room or not
for(int j = 0; j < tabRoom.Length; j++)
{
!!!!!if( i != j )!!!!!!
{
if( (tabRoom[j].iXpos > tabRoom[i].iXpos + tabRoom[i].iWidth )
|| ((tabRoom[j].iXpos) + tabRoom[j].iWidth < tabRoom[i].iXpos )
|| (tabRoom[j].iZpos > tabRoom[i].iZpos + tabRoom[i].iHeight )
|| (tabRoom[j].iZpos + tabRoom[j].iHeight < tabRoom[i].iZpos))
{
tabRoom[i].PosOk = true; //No collision
}
else
{
tabRoom[i].PosOk = false; //Collision
break;
}
}
}
}
}
}
Answer by tanoshimi · Nov 17, 2015 at 12:39 PM
The logic in your while loop looks flawed to me. Look at these highlighted lines:
*a* while(tabRoom[i].PosOk == false) **
{
*b* for(int j = 0; j < tabRoom.Length; j++) **
{
...
if( ...) { }
*c* else
{
*d* tabRoom[i].PosOk = false; **
*e* j = tabRoom.Length;**
}
}
}
Once you fall into that else branch at c, you're stuck in an infinite loop, because you're setting PosOk to false d, and you're also setting j to tabRoom.Length e, which means that the for(int j=0; at b condition will never be true, and that contains the only bit of code that could have set PosOk to true.
First, thank you for your reply ! :)
Hum the 'e' line is here only to exit the for loop to "optimise" the code. I can replace this line by a "break;" for example, it is all the same.
But don't think that it's the problem because this algorithm works correctly in c++... :/
$$anonymous$$aybe I didn't understand your reply ?
The line at e breaks the for loop. It doesn't break the while loop, and that's the one you're stuck in.
Answer by troien · Nov 17, 2015 at 01:53 PM
Well, there are several things with this piece of code...
We check if there is a collision with the new room or not
First of all, at some point, i will be equal to j meaning there will most likely be a collision with itself at some point (when i == tabRoom.Length - 1 you have an infinite loop I suppose). Secondly, you constantly overwrite tabroom[i].PosOk in that for loop but you only check it after the for loop (meaning that your code might ignore some collisions) which isn't what you would want to do if you intend to do what you wrote in your comments...
Changing it to something like this might work...
//We check if there is a collision with the new room or not
tabRoom[i].PosOk = true; // before we check collision set this to no collision
for(int j = 0; j < tabRoom.Length; j++)
{
if (j != i && (/*Insert code that returns true when there is a collision*/))
{
tabRoom[i].PosOk = false; //Collision
break; // Not required but quits checking for collision whn we already found one (ore efficient
}
}
// If we didn't find a collision, PosOk is still true, if we did find a collision PosOk is set to false (obviously infinite is still possible in case there are no OK positions left and there is always a collision :D)
Your answer
Follow this Question
Related Questions
SOLVED! - Pick Number != These Other Numbers 2 Answers
Randomly Generated Levels 3 Answers
How do I split a rectangle into random smaller rectangles? 1 Answer
Having trouble with PlayerPrefs in my script. 1 Answer
How to create a perlin noise heightmap with the values being the highest around a point? 1 Answer