Sorting Arrays via For-Loops.

Archive of the old editing forum
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
Locked
XxMiltenXx
Posts: 219
Joined: Wed Jan 08, 2014 8:40 am
Graphics Processor: nVidia with Vulkan support
Location: Germany

Sorting Arrays via For-Loops.

Post by XxMiltenXx »

Hello everyone, I need help with For-Loops and Arrays ...

The basic idea is that the script acquires the Health of all players ingame and their corresponding TIDs, puts them into 2 arrays and sorts them from lowest to highest health. Since I had trouble getting the health via For-Loops into the arrays, I simply request the health already while initializing the arrays.
All that is working fine, BUT the sorting process is somewhat broken. The first index of the array does not get sorted, while any following indexes will be sorted as intended.
Example:
Player 1 = 100 Health, Player 2 = 50 Health, Player 3 = 25 Health

So the result SHOULd be: Player 3, Player 2, Player 1
The result however is: Player 1, Player 3, Player 2

Player 2 and Player 3 got sorted properly, while Player 1 remains in it's position.
I know that, because I used HUDMESSAGE to show me the results.

Here's the Script

Code: Select all

Script 2 (void)
{
	int counter;
	int innercounter;
	int itemamount; //dummy variable for swapping
	int player; //dummy variable for swapping
	int sortitemamount[8] = { CheckActorInventory(1000, "Health"), CheckActorInventory(1001, "Health"), CheckActorInventory(1002, "Health"), CheckActorInventory(1003, "Health"), CheckActorInventory(1004, "Health"), CheckActorInventory(1005, "Health"), CheckActorInventory(1006, "Health"), CheckActorInventory(1007, "Health") } ;

	int sortplayer[8] = { 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007 };
	For (counter = 0; counter < PlayerCount() - 2; counter++);	//Sort the variables, from lowest to highest amount
	{
		For (innercounter = counter + 1; innercounter < PlayerCount() - 1; innercounter++);
		{
			If (sortitemamount[counter] > sortitemamount[innercounter])
			{
				itemamount = sortitemamount[counter];
				player = sortplayer[counter];
				sortitemamount[counter] = sortitemamount[innercounter];
				sortplayer[counter] = sortplayer[innercounter];
				sortitemamount[innercounter] = itemamount;
				sortplayer[innercounter] = player;
			}
		}
	}
}
Maybe you have any idea what's wrong with it, I simply cannot figure it out.

PS: I am fully aware that I can use "GetActorProperty(TID, APROP_Health)" but I want to use this script for Armor & Ammo as well later on.
boris
Posts: 784
Joined: Tue Jul 15, 2003 3:37 pm

Re: Sorting Arrays via For-Loops.

Post by boris »

You can read up on sorting algorithms here (with code examples): http://www.sorting-algorithms.com/
Aliotroph?
Posts: 35
Joined: Wed May 07, 2008 2:54 am

Re: Sorting Arrays via For-Loops.

Post by Aliotroph? »

Your loops don't loop enough. Either use a <= or increment the numbers by one. Also not sure why you have a ; on the end of the loop conditions. It doesn't appear to cause an error, but it doesn't make any sense.
User avatar
edward850
Posts: 5904
Joined: Tue Jul 19, 2005 9:06 pm
Location: New Zealand
Contact:

Re: Sorting Arrays via For-Loops.

Post by edward850 »

Aliotroph? wrote:Also not sure why you have a ; on the end of the loop conditions. It doesn't appear to cause an error, but it doesn't make any sense.
The statement is valid, but of course it won't do what he'd expect. The for loop will run independent of the block after it, making it useless, and the block will always run independently. And of course since he defines all his counters at the top level first, the blocks are still valid, thus ACC has nothing to complain about.
XxMiltenXx
Posts: 219
Joined: Wed Jan 08, 2014 8:40 am
Graphics Processor: nVidia with Vulkan support
Location: Germany

Re: Sorting Arrays via For-Loops.

Post by XxMiltenXx »

Aliotroph? wrote:Your loops don't loop enough. Either use a <= or increment the numbers by one. Also not sure why you have a ; on the end of the loop conditions. It doesn't appear to cause an error, but it doesn't make any sense.
Good that you mentioned that!

I tried the script again as I posted it, with the errorness ";" that I accidently put. The same example as given above and the result is again: 100, 25, 50.

If I remove the ";", the result will be: 50, 100, 25, because - as you noted as well, I don't loop enough! So due to the ";" it acts as if the counter is 1 higher, hence Index 0 is never adressed...

So if I remove the ";" and raise the loop 1 higher , he will actually sort it correctly ... so putting a ";" does matter, even though the compiler does not bother to complain about it, but it will cause errorness behaviour.

Thanks for your help there. Such a little error ...

So for everyone who's interested and may need it, here's a fixed and working version...

Code: Select all

Script 2 (void)
{
   int counter;
   int innercounter;
   int sortitemamount[8];
   int sortplayer[8];
   int itemamount; //dummy variable for swapping
   int player; //dummy variable for swapping
   For (counter = 0; counter < PlayerCount(); counter++)
   {
      sortitemamount[counter]=CheckActorInventory(1000+counter, "Health");
      sortplayer[counter] = 1000+counter;
   }
   For (counter = 0; counter < PlayerCount() - 1; counter++)   //Sort the variables, from lowest to highest amount
   {
      For (innercounter = counter + 1; innercounter < PlayerCount(); innercounter++)
      {
         If (sortitemamount[counter] > sortitemamount[innercounter])
         {
            itemamount = sortitemamount[counter];
            player = sortplayer[counter];
            sortitemamount[counter] = sortitemamount[innercounter];
            sortplayer[counter] = sortplayer[innercounter];
            sortitemamount[innercounter] = itemamount;
            sortplayer[innercounter] = player;
         }
      }
   }
}
User avatar
Vincent(PDP)
Posts: 60
Joined: Fri May 16, 2014 3:49 pm
Location: Sweden
Contact:

Re: Sorting Arrays via For-Loops.

Post by Vincent(PDP) »

NEVER use PlayerCount() in for loops like this.
If there are (for example) 6 players playing and suddenly Player 3 and 4 disconnects (they have IDs 2 and 3), PlayerCount() will return 4.
And now your for loop will not be able check all player's health because of the fact that you always have the same player number. So if PlayerCount() returns 4, the health will not be checked for Player 5 and 6 (IDs 4 and 5) because "counter < PlayerCount()" makes your loop not go longer than 3, which is Player 2.

A correct aproach is to always use the number of maximum players in a loop.
I.e:

Code: Select all

For(counter = 0; counter < 8; counter++)
{
    If(PlayerInGame(counter)) //To be sure that there is a player with this ID.
    {
        //More calculations...
    }
}
And one more thing... If you need to check zero-based elements as a condition in a loop, you either do:

Code: Select all

counter < PlayerCount() //Goes up to 7 with 8 players playing.
or:

Code: Select all

counter <= PlayerCount() - 1 //Goes up to 7 with 8 players playing.
Because the condition you used will skip one player:

Code: Select all

counter < PlayerCount() - 1 //Goes up to 6 with 8 players playing.
But still (to not make you confused), don't use PlayerCount() as such conditions.
Locked

Return to “Editing (Archive)”