Solved

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

Posted on 2009-06-28
5
203 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
This did the trick. Thank you Idle Mind.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Introduction                                                 Was the var keyword really only brought out to shorten your syntax? Or have the VB language guys got their way in C#? What type of variable is it? All will be revealed.   Also called…
This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

762 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

7 Experts available now in Live!

Get 1:1 Help Now