0

I am new to c# and attempting to do it the right way. I have searched stackoverflow and consulted tutorials and books re 'sorting class objects' but have yet to find anything that works for me, despite struggling with LISTS, INUMERATORS and COMPARATORS. To help me learn c# I am attempting to replicate an old board game. It includes Cards that need to be sorted or shuffled on the start of a new game. I'm getting the card data via a stored procedure from SQL Server because I am trying to get to grips with that as well. How can I simply sort my card class objects and RETURN them from my function below? Am I even going about this task in the best way? Below is my 'PirateCard' class. Many thanks.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Collections;

namespace Buccaneer
{
    public class PirateCard : Card
    {


        public PirateCard()
        {
        }

        public PirateCard[] initCards()
        {
            string spName = "sp_select_cards_by_type";
            int cardCount = 1;
            db DB = new db();
            DataTable dt = new DataTable();

            Dictionary<string, string> spParams = new Dictionary<string, string>();
            spParams.Add("@Type", "PIRATE");

            dt = DB.executeSelectStoredProcedureWithParams(spName, spParams);
            PirateCard[] pirateCards = new PirateCard[dt.Rows.Count + 1];

            List<int> sortNumber = shuffle();
            Console.WriteLine(sortNumber.Count);

            foreach (DataRow row in dt.Rows)
            {
                pirateCards[cardCount] = new PirateCard();
                pirateCards[cardCount].Type = row["fldtype"].ToString();
                pirateCards[cardCount].Number = row["fldno"].ToString();
                pirateCards[cardCount].SortNumber= sortNumber.ElementAt(cardCount - 1);
                pirateCards[cardCount].IncentiveType = row["fldincentivetype"].ToString();
                pirateCards[cardCount].Value = row["fldvalue"].ToString();
                pirateCards[cardCount].PlayWithin = row["fldplaywith"].ToString();
                pirateCards[cardCount].Text = row["fldtext"].ToString();           
                Console.WriteLine(pirateCards[cardCount].Number + ":" + pirateCards[cardCount].SortNumber);
                cardCount++;
            }
            Console.WriteLine(DB.RecordCount + " pirate cards were found.");
            //  SHUFFLE OR SORT CARDS on .SortNumber here...
            //  ???
            return pirateCards;
        }

        public List<int> shuffle()
        {
            Random randNum = new Random();
            List<int> numbers = new List<int>();
            while (numbers.Count < ApplicationGlobals.numberOfPirateCards)
            {
                int num = randNum.Next(1, ApplicationGlobals.numberOfPirateCards + 1);
                if (numbers.Contains(num))
                {                    
                }
                else
                {
                    numbers.Add(num);
                    Console.WriteLine(num + " Numbers allocated so far " + numbers.Count);
                }
            }
            Console.WriteLine(numbers.Count + " random numbers allocated");
            return numbers;
        }


    }
}

3 Answers 3

2

You can sort the cards using the LINQ OrderBy extension method. I'm assuming you want your cards sorted based on their SortNumber property.

return pirateCards.OrderBy(card => card.SortNumber).ToArray();

Edit: On second thoughts, you should do away with your shuffle method (and SortNumber property), and use the first extension method provided from this answer, which is based on the Fisher–Yates shuffle. You can call it using:

return pirateCards.Shuffle();
Sign up to request clarification or add additional context in comments.

2 Comments

Many thanks for the amazingly quick response. I have been trying things LIKE that, and just did. But I get... Object reference not set to an instance of an object.
@user3187383: Yes, that's because your array is one element larger than the number of cards (so the last item remains null). Replace new PirateCard[dt.Rows.Count + 1] with new PirateCard[dt.Rows.Count].
0

If you want to stick with the array, there are various overloads of the Array.Sort method. some take a Comparison as a parameter, e.g.:

Array.Sort(pirateCards, (x, y) => x.SortNumber - y.SortNumber);

By the way, your array is one element to large; you should initialize it as follows to avoid a NullReferenceException when sorting:

PirateCard[] pirateCards = new PirateCard[dt.Rows.Count];

Also, cardCount needs to be initilized with a value of 0 as arrays start with 0 in .NET.

1 Comment

Many thanks to both. I had been fiddling about with the array initialisation and increment, I have now changed the code to start the array at zero (cardCount) and avoid the need to add 1 or subtract one at various points. Much simpler!
0

You can save a lot of time by using "LinQ to SQL Classes" that will convert your database tables to classes. Then you can sort and group your array of objects in simple code.

1 Comment

I did see some things about LINQ and will investigate, thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.