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;
        }


    }
}
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
user3187383
  • 139
  • 1
  • 1
  • 5

3 Answers3

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();
Community
  • 1
  • 1
Douglas
  • 53,759
  • 13
  • 140
  • 188
  • 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 Jan 12 '14 at 14:01
  • @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]`. – Douglas Jan 12 '14 at 14:03
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.

Markus
  • 20,838
  • 4
  • 31
  • 55
  • 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! – user3187383 Jan 12 '14 at 14:09
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.

Zein Makki
  • 29,485
  • 6
  • 52
  • 63