Determain and assign a play order based on player initiative within a list in C#

I have a list of players. Each player has two properties, Initiative (int) and TurnOrder (int). In C# (.Net 2.0 for this please) I would like to assign each player in the list a unique integer for their TurnOrder (1 through X) based on which player's have the highest initiative (numerically speaking). I would want to randomly break ties between players with the same initiative value, which could be between two or more players (each player with a matching initiative would "roll the dice" to see what the final order would be between them).

The idea would be once I have assigned each player in the list a unique TurnOrder, I could then simply sort the list by TurnOrder:

PlayerList.Sort(delegate(Player p1, Player p2) { return p1.Initiative.CompareTo(p2.Initiative); });
ScottBlinnAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rendaduiyanCommented:
How about this one:
1) sorting the players by Initiative, high to low
2) use a loop to give each player a TurnOrder value by:
    2-1) if n nad n+1 has same Initiative, find the one bigger than n;
      a) randomly assign TurnOrder for n, n+1, ...
    2-2) assigne a TurnOrder .
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
Here is an implementation:
    public class Player
    {
        public int TurnOrder;
        public int Initiative;
        
        public Player(int Initiative) { this.Initiative = Initiative; }
    }
 
    public partial class Form1 : Form
    {
 
        private Random R = new Random();
        List<Player> PlayerList = new List<Player>();
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            PlayerList.Add(new Player(5));
            PlayerList.Add(new Player(2));
            PlayerList.Add(new Player(1));
            PlayerList.Add(new Player(7));
            PlayerList.Add(new Player(5));
            PlayerList.Add(new Player(5));
            PlayerList.Add(new Player(4));
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            PlayerList.Sort(SortByInitiative);
            for (int i = 0; i < PlayerList.Count; i++)
            {
                PlayerList[i].TurnOrder = i + 1;
            }
            PlayerList.Sort(delegate(Player p1, Player p2) { return p1.TurnOrder.CompareTo(p2.TurnOrder); });
 
            foreach (Player p in PlayerList)
                Console.WriteLine(p.TurnOrder.ToString() + " --> " + p.Initiative.ToString());
        }
 
        private int SortByInitiative(Player p1, Player p2)
        {
            if (p1.Initiative != p2.Initiative)
                return p2.Initiative.CompareTo(p1.Initiative);
            else
                return R.Next() >= .5 ? 1 : -1;
        }
 
    }

Open in new window

0
ScottBlinnAuthor Commented:
Thank you guys.

Idol Mind: I implemented your solution and it almost does the trick. It seems that because it only takes in two players to compare at once, you end up with the same pattern/order between all players with the same Initiative value (so all players with an Initiative of 5 show up in the same order/are assigned the same TurnOrder value within the final list). What would I need to do to assign a random order between the players with the same Initiative each time the code is run?
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
Apologies ScottBlinn...I used the wrong Random method.

Use this SortByInitiative() instead:

        private int SortByInitiative(Player p1, Player p2)
        {
            if (p1 == p2)
                return 0; // <-- need this because the internal Sort method compares an object against itself (and should return zero)
            else
            {
                if (p1.Initiative != p2.Initiative)
                    return p2.Initiative.CompareTo(p1.Initiative);
                else
                    return R.NextDouble() >= .5 ? 1 : -1;
            }
        }

Here is a modified version (I added a "name" field to make sure):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
 
        private Random R = new Random();
        List<Player> PlayerList = new List<Player>();
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            PlayerList.Add(new Player(5, "a"));
            PlayerList.Add(new Player(2, "b"));
            PlayerList.Add(new Player(1, "c"));
            PlayerList.Add(new Player(7, "d"));
            PlayerList.Add(new Player(5, "e"));
            PlayerList.Add(new Player(5, "f"));
            PlayerList.Add(new Player(4, "g"));
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            PlayerList.Sort(SortByInitiative);
            for (int i = 0; i < PlayerList.Count; i++)
            {
                PlayerList[i].TurnOrder = i + 1;
            }
            PlayerList.Sort(delegate(Player p1, Player p2) { return p1.TurnOrder.CompareTo(p2.TurnOrder); });
 
            foreach (Player p in PlayerList)
                Console.WriteLine(p.TurnOrder.ToString() + " --> " + p.Initiative.ToString() + ", " + p.Name);
        }
 
        private int SortByInitiative(Player p1, Player p2)
        {
            if (p1 == p2)
                return 0;
            else
            {
                if (p1.Initiative != p2.Initiative)
                    return p2.Initiative.CompareTo(p1.Initiative);
                else
                    return R.NextDouble() >= .5 ? 1 : -1;
            }
        }
 
    }
 
    public class Player
    {
        public string Name;
        public int TurnOrder;
        public int Initiative;
 
        public Player(int Initiative, string name) { this.Initiative = Initiative; this.Name = name; }
    }
 
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ScottBlinnAuthor Commented:
This did the trick. Thank you Idle Mind.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.