Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 214
  • Last Modified:

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); });
0
ScottBlinn
Asked:
ScottBlinn
  • 2
  • 2
1 Solution
 
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
 
ScottBlinnAuthor Commented:
This did the trick. Thank you Idle Mind.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now