Solved

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

Posted on 2009-06-28
5
205 Views
Last Modified: 2012-05-07
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
Comment
Question by:ScottBlinn
  • 2
  • 2
5 Comments
 
LVL 5

Expert Comment

by:rendaduiyan
ID: 24733961
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
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24734159
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
 

Author Comment

by:ScottBlinn
ID: 24738141
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
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 400 total points
ID: 24738425
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
 

Author Closing Comment

by:ScottBlinn
ID: 31597788
This did the trick. Thank you Idle Mind.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Code works but I need to redo it and assign values to Model 7 31
Problem of RegEx to match the first occurence of 10 35
Host asp.net pages 5 25
Turn on intranet settings 1 36
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now