• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 215
  • 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

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

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