I'm currently creating a very basic game in C# and I have an inventory system created which using a very simple command (Items.Add(id, amount)) you can add items to said inventory. What I want to be able to do, which my current system does not do is be able to effectively "search" my inventory array which is a 2D array holding the item id and item amount. My current system is like this:
public static void add(int id, int amount)
{
for (int i = 0; i < Ship_Builder.Player.invCount; i++)
{
if (Ship_Builder.Player.inv[i, 0] == 0)
{
Ship_Builder.Player.inv[i, 0] = id;
Ship_Builder.Player.inv[i, 1] = amount;
}
}
Ship_Builder.Player.invCount++;
}
and I want it to (in an else if) be able to search the array. I did have this:
else if (Ship_Builder.Player.inv[i, 0] == Ship_Builder.Player.inv[i + 1, 0])
{
//Do
}
Before, but it didn't work how I wanted it to.
Any help would be greatly appreciated thanks,
Laurence.
As comments suggest, you should use a Dictionary for such a task. But if you have to use a 2-d array, which is (i presume) pre-populated with zeros before we add any items to it, then an if-else statement like you propose won't do the trick. What you need to do is iterate through the array looking for a matching id first and each time your ids don't match, you have to check if the id that you're currently checking is equal to 0. If it is, then you have traversed all "slots" which had some items in them without finding a match, which means this item must go into another, empty slot.
public static void add(int id, int amount)
{
for (int i = 0; i < Ship_Builder.Player.invCount; i++)
{
if (Ship_Builder.Player.inv[i, 0] != id)
{
if (Ship_Builder.Player.inv[i, 0] == 0)
{
Ship_Builder.Player.inv[i, 0] = id;
Ship_Builder.Player.inv[i, 1] = amount;
Ship_Builder.Player.invCount++;
continue;
}
}
else
{
Ship_Builder.Player.inv[i, 1] += amount;
continue;
}
}
}
Warning! My answer assumes that you locate new items in the empty slot with the smallest possible index. Also, if you are removing items and setting the id to zero as a result, then you'll have to traverse the whole array first in search of a matching index before you can allocate a new item. Which might get very expensive time-wise if the array is large.
There's a lot going on here (and there isn't enough detail to give any answer except in broad strokes), but how I would approach something like this would be to start with using object oriented designs rather than relying on indexed positions in arrays. I'd define something like this:
public class InventoryItem
{
public int Id { get; set; }
public int Amount { get; set; }
// Now I can add other useful properties here too
// ...like Name perhaps?
}
Now I'd make my inventory a Dictionary<int,InventoryItem> and adding something to my inventory might look something like this:
public void Add(int id, int amount)
{
// assuming myInventory is our inventory
if (myInventory.ContainsKey(id)) {
myInventory[id].Amount += amount;
}
else {
myInventory[id] = new InventoryItem()
{
Id = id,
Amount = amount
};
}
}
Now it's not necessary that you actually use the InventoryItem class, you could just stick with Dictonary<int,int>, but you'll probably find as you work through it that you'd much rather have some objects to work with.
Then you could probably have a master dictionary of all objects and just add them to your inventory, so you end up with something like:
public void Add(InventoryItem item, int amount)
{
// assuming myInventory is our inventory
if (myInventory.ContainsKey(item.Id)) {
myInventory[item.Id].Amount += amount;
}
else {
myInventory[item.Id] = new InventoryItem(item) // assuming you added a
// copy constructor, for example
{
Amount = amount
};
}
}
Depending on speed performance requirements (using arrays should be only slightly faster than this) you could just skip the hard coded values and arrays all together. This has a few semi-advanced topics:
public abstract class InventoryItem
// or interface
{
public abstract string Name { get; }
public int Count { get; set; }
}
public class InventoryGold : InventoryItem
{
public string Name { get { return "Gold" } }
}
public abstract class InventoryWeapon : InventoryItem { }
public class OgreSlayingKnife : InventoryWeapon
{
public string Name { get { return "Ogre Slaying Knife"; } }
public int VersusOgres { get { return +9; } }
}
public UpdateCount<Item>(this ICollection<Item> instance,
int absoluteCount)
{
var item = instance.OfType<Item>().FirstOrDefault();
if (item == null && absoluteCount > 0)
{
item = default(Item);
item.Count = absoluteCount;
instance.add(item);
}
else
{
if (absoluteCount > 0)
item.Count = absoluteCount;
else
instance.Remove(item);
}
}
// Probably should be a Hashset
var inventory = new List<InventoryItem>();
inventory.UpdateCount<InventoryGold>(10);
inventory.UpdateCount<OgreSlayingKnife(1)
Related
EDITED: (editd the binary search method)
I am using c sharp. I have a sorted list that has some values in it such as name and their quantity.
My code:
using System;
using System.Collections.Generic;
using static System.Console;
namespace InventoryManagementSystem
{
public class Tool
{
public Tool(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
public string Name { get; }
public int Quantity { get; }
public int CompareTo(SortedList<string, Tool> other, String name)
{
return; //not sure how to write this properly
}
}
}
//toolitems class
public class ToolItems
{
SortedList<string, Tool> gardeningTools = new SortedList<string, Tool>();
public void gardeningToolData()
{
Tool gardeningTool1 = new Tool("Garden gloves", 50);
gardeningTools.Add(gardeningTool1.Name, gardeningTool1);
WriteLine("Please enter a name of the tool");
String user = ReadLine();
int number = binarySearch(user);
}
public int binarySearch(String user)
{
while (low <= high)
{
mid = (high + low) / 2;
if (gardeningTools.Values[high].Name.CompareTo(user) == 0)
{
WriteLine("mid is: " + mid);
return mid;
}
else if (gardeningTools.Values[high].Name.CompareTo(user) > 0)
high = mid - 1;
else
low = mid + 1;
}
return -1;
}
Edited: My code works now except it returns the index 0 if the value is between first and last index of list. How can I get the exact index from the sortedlist depending on what name user search for?
In short all I am trying to do is when user enter some string value and if it matches in the sortedlist (which we search using binary search algorithm) we get the index of that value from sorted list and update the quantity of that specific value (If user chose 'A' and it is at index 0 ("A", 5) then we ask user for how many A you want to borrow and user say 2, so the quantity gets update to 3 now.
SortedList is implementing IDictionary. Basically, your sorted list will have methods that IDictionary has. You can check this link Microsoft Docs SortedList out.
In your question, my understanding is you want to find your Tool object from SortedList and update its quantity. I am not directly answering your question about how to write CompareTo method but instead proposing alternative solution to how you can achieve your actual goal. Please find below sample code:
Slight change on your Tool class, added setter to Quantity property and removed your CompareTo method:
public class Tool
{
public Tool(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
public string Name { get; }
public int Quantity { get; set; }
}
And here your console app part how to find and update quantity with user inputs:
SortedList<string, Tool> gardeningTools = new SortedList<string, Tool>();
public void gardeningToolData()
{
var gardeningTool = new Tool("Garden gloves", 50);
gardeningTools.Add(gardeningTool.Name, gardeningTool);
Console.WriteLine("Please enter a name of the tool");
var toolName = Console.ReadLine();
Console.WriteLine("Please enter quantity of tools");
var quantity = int.Parse(Console.ReadLine()); // Ideally you should check whether user enters valid integer
if(gardeningTools.TryGetValue(toolName, out var tool))
{
// You should check here whether you have sufficient quantity before decreasing quantity
tool.Quantity -= quantity;
}
}
UPDATE
I've modified this so that I'm also answering how to implement compareto.
public class Tool : IComparable<Tool>, IComparable<string>
{
public Tool(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
public string Name { get; }
public int Quantity { get; }
public int CompareTo(Tool other)
{
// You could manually compare rather than this
// return this.Name == other?.Name ? 0 : this.Name < other?.Name ? -1 : 1;
return string.Compare(this.Name, other?.Name);
}
public int CompareTo(string other) {
return string.Compare(this.Name, other);
}
}
public int binarySearch(String user)
{
while (low <= high)
{
mid = (high + low) / 2;
switch(gardeningTools.Values[mid].CompareTo(user)) {
case 0: // Found
WriteLine("mid is: " + mid);
return mid;
case -1: // Mid is too small.
low = mid + 1;
break;
default: // Mid is too high
high = mid - 1;
break;
}
// probably should also check that high and low != at this point
return -1;
}
Having a model something like this (I cannot change this):
public class SomeObject
{
public int Amount { get; set; }
public int TotalAmount { get; set; }
}
I need to iterate an array of SomeObject to populate some values and accumulate (perform not simple calculations) another fields.
static void Main(string[] args)
{
List<SomeObject> myCollection = new List<SomeObject>()
{
new SomeObject() { Amount = 3 },
new SomeObject() { Amount = 6 },
new SomeObject() { Amount = 9 }
};
int totalAccumulated = 0;
for (int i = 0; i < myCollection.Count; i++)
{
PopulateAndCalculate(myCollection[i], ref totalAccumulated);
}
//I don't want to create here a second for to iterate again all myCollection to set his TotalAmount property.
//There is another way?
Console.WriteLine($"The total accumulated is: {totalAccumulated}");
}
private static void PopulateAndCalculate(SomeObject prmObject, ref int accumulatedTotal)
{
//Populate a lot of another fields
accumulatedTotal += prmObject.Amount;
prmObject.TotalAmount = accumulatedTotal; //This don't work, but I need something alike
}
I don't want a second for statement to update TotalAmount property of each item in myCollection.
The main requirement is iterate the whole array, few times, don't care about string interpolation this is a short demo, this code must run in .net 2.0.
Theres is a clean/better way?
The solution is actually simple, though it's not exactly a good coding practice.
What you really need is for TotalAmount to be a static property. Without that, there's this:
static void Main(string[] args)
{
List<SomeObject> myCollection = new List<SomeObject>()
{
new SomeObject() { Amount = 3 },
new SomeObject() { Amount = 6 },
new SomeObject() { Amount = 9 }
};
int totalAccumulated = 0;
for (int i = 0; i < myCollection.Count; i++)
{
PopulateAndCalculate(myCollection[i], ref totalAccumulated);
}
/*****This is the new part*******/
myCollection[0].TotalAmount = totalAccumulated;
myCollection[1].TotalAmount = totalAccumulated;
myCollection[2].TotalAmount = totalAccumulated;
Console.WriteLine($"The total accumulated is: {totalAccumulated}");
}
private static void PopulateAndCalculate(SomeObject prmObject, ref int accumulatedTotal)
{
//Populate a lot of another fields
accumulatedTotal += prmObject.Amount;
//no need to mess with the total here as far as the properties are concerned.
}
You can st fields inside linq expression.
Could you consider this please
myCollection.ForEach(c => c.TotalAmount = myCollection.Sum(a => a.Amount));
Console.WriteLine($"Total accumulated :{myCollection.First().TotalAmount}");
I found a solution using the Observer Pattern.
Firstly I created a global delegate to be used by an event:
public delegate void UpdateTotalAmountDelegate(int totalAmount);
Then a new class called: 'CalculatorSetter'
public class CalculatorSetter
{
public event UpdateTotalAmountDelegate UpdateTotalAmounthHandler;
public void UpdateTotalAmount(int prmTotalAmount)
{
UpdateTotalAmounthHandler(prmTotalAmount);
}
}
I refactor the data object 'SomeObject' adding a field of type CalculatorSetter.
public class SomeObject
{
private CalculatorSetter finalCalculator;
public void SetCalculator(CalculatorSetter prmCalculator)
{
this.finalCalculator = prmCalculator;
finalCalculator.UpdateTotalAmounthHandler += FinalCalculator_UpdateTotalAmounthHandler;
}
private void FinalCalculator_UpdateTotalAmounthHandler(int totalAmount)
{
this.TotalAmount = totalAmount;
}
//Some Other Fields
public int Amount { get; set; }
public int TotalAmount { get; set; }
}
And my original code and unique for:
static void Main(string[] args)
{
List<SomeObject> myCollection = new List<SomeObject>()
{
new SomeObject() { Amount = 3 },
new SomeObject() { Amount = 6 },
new SomeObject() { Amount = 9 }
};
CalculatorSetter commonCalculator = new CalculatorSetter();
int totalToAccumulate = 0;
for (int i = 0; i < myCollection.Count; i++)
{
PopulateAndCalculate(myCollection[i], commonCalculator, ref totalToAccumulate);
}
commonCalculator.UpdateTotalAmount(totalToAccumulate);
Console.WriteLine($"The total accumulated is: {totalToAccumulate}");
Console.WriteLine($"The first total accumulated is: {myCollection[0].TotalAmount}");
}
Many thanks.
Use a wrapper and keep it simple (if you want you can change a little for use static methods you can, or static class but I dont see the point)
the result is:
The Amount is 3, The total ammount is 18
The Amount is 6, The total ammount is 18
The Amount is 9, The total ammount is 18
namespace Prueba1
{
class Program
{
public class WrapperInt {
public int Value { get; set; }
}
public class SomeObject
{
public int Amount { get; set; }
public WrapperInt TotalAmount { get; set; }
}
public Program() {
WrapperInt TotalAmountAllArrays = new WrapperInt();
List<SomeObject> myCollection = new List<SomeObject>()
{
new SomeObject() { Amount = 3, TotalAmount =TotalAmountAllArrays },
new SomeObject() { Amount = 6 , TotalAmount =TotalAmountAllArrays },
new SomeObject() { Amount = 9 , TotalAmount =TotalAmountAllArrays }
};
for (int i = 0; i < myCollection.Count; i++)
{
myCollection[i].TotalAmount.Value += myCollection[i].Amount;
}
foreach (var c in myCollection)
{
Console.WriteLine($"The Amount is:" + c.Amount + " The total ammount is:" + c.TotalAmount.Value);
}
}
static void Main(string[] args)
{
new Program();
}
}
}
Hopefully this will work for you… One possible solution is to create a wrapper class called MyTotalList which contains a List named amounts and an int named total. MyTotalList class does not expose its list amounts as an editable list. If the class exposes this list as editable, then other methods could ultimately change an items value in that list and the MyTotalList class would not be aware of this and unfortunately contain an incorrect total. To avoid this situation and for the class to work as expected, methods must use the MyTotalList’s Add and Remove methods. To ensure this happens, the private List amounts in the MyTotalList class returns a read only list which ensures that changes to the list will not be made outside the MyTotalList class. Leaving the list exposed and editable will/could cause the class to contain an incorrect total.
My solution is to create a Class that wraps a List. MyTotalList class has a no argument constructor. Once a new instance of a MyTotalList object is created you can then use that instance to Add MyObject items to its list. Every time an item is added to the MyTotalList, list amounts the variable total gets updated with the added item’s amount. Example:
Create a new MyTotalList object:
MyTotalList listOfObjects = new MyTotalList();
Then add some MyObject instances to the listOfObjects
listOfObjects.Add(new MyObject(1,3));
listOfObjects.Add(new MyObject(2,6));
listOfObjects.Add(new MyObject(3,9));
After you add the items, you can then use the listOfObjects Total property to get the total sum of all MyObject items in the list with:
listOfObjects.Total
If you need to pass or use the List of MyTotalList items you can use:
listOfObjects.Items
Bear in mind as I discussed above, this List Items is a read-only list. Therefore you cannot add/remove items in this list as you would an editable list. So the code below will fail during implementation as these methods are not exposed for read only objects.
listOfObjects.Items.Remove(new MyObject(4, 10));
listOfObjects.Items.Add(new MyObject(4, 10));
The above lines will cause the compiler to complain: xxx… does not contain a definition for Add/Remove. This ensures methods will use the MyTotalList.Add and MyTotalsList.Remove methods and eliminate any possibility of the list changing outside the MyTotalList class.
MyObject Class
class MyObject : IComparable {
public int id { get; }
public int amount { get; }
public MyObject(int inID, int inAmount) {
id = inID;
amount = inAmount;
}
public override string ToString() {
return amount.ToString();
}
public override int GetHashCode() {
return id.GetHashCode();
}
public override bool Equals(object other) {
if (other != null)
return (this.id == ((MyObject)other).id);
return false;
}
public int CompareTo(object other) {
if (this.id > ((MyObject)other).id)
return 1;
if (this.id < ((MyObject)other).id)
return -1;
return 0;
}
}
MyTotalList Class
class MyTotalList {
private int total;
private List<MyObject> amounts;
public MyTotalList() {
total = 0;
amounts = new List<MyObject>();
}
public int ListCount {
get { return amounts.Count; }
}
public IReadOnlyCollection<MyObject> Items {
get { return amounts.AsReadOnly(); }
}
public int Total {
get { return total; }
}
public void Add(MyObject other) {
if (other != null) {
if (!(amounts.Contains(other))) {
total += other.amount;
amounts.Add(other);
}
else {
Console.WriteLine("Duplicate id's not allowed!");
}
}
}
public void Remove(MyObject other) {
if (amounts.Contains(other)) {
total -= amounts[amounts.IndexOf(other)].amount;
amounts.Remove(other);
}
else {
Console.WriteLine("Item to remove not found!");
}
}
}
Examples
MyTotalList listOfObjects = new MyTotalList();
listOfObjects.Add(new MyObject(1,3));
listOfObjects.Add(new MyObject(2,6));
listOfObjects.Add(new MyObject(3,9));
Console.WriteLine("----------------------------------------");
Console.WriteLine("Initial list with total");
Console.WriteLine("items in list:");
foreach (MyObject mo in listOfObjects.Items)
Console.Write(mo.ToString() + " ");
Console.WriteLine();
Console.WriteLine("Total from list of " + listOfObjects.ListCount +
" items is: " + listOfObjects.Total);
Console.WriteLine("----------------------------------------");
Console.WriteLine("Add three more items");
listOfObjects.Add(new MyObject(4, 10));
listOfObjects.Add(new MyObject(5, 11));
listOfObjects.Add(new MyObject(6, 12));
Console.WriteLine("items in list:");
foreach (MyObject mo in listOfObjects.Items)
Console.Write(mo.ToString() + " ");
Console.WriteLine();
Console.WriteLine("Total from list of " + listOfObjects.ListCount +
" items is: " + listOfObjects.Total);
Console.WriteLine("----------------------------------------");
Console.WriteLine("Remove id 4 (10) from the list");
listOfObjects.Remove(new MyObject(4, 10));
Console.WriteLine("items in list:");
foreach (MyObject mo in listOfObjects.Items)
Console.Write(mo.ToString() + " ");
Console.WriteLine();
Console.WriteLine("Total from list of " + listOfObjects.ListCount +
" items is: " + listOfObjects.Total);
A Side note to your original post…About the class you can not change
SomeObject {
public int Amount { get; set; }
public int TotalAmount { get; set; }
}
Regardless of how you get the total for theint varable: TotaAmount… for each instance of SomeObject class to contain the same variable with the same amount and you want to ensure this is true for all existing SomeObject instances… is well a poor design. This creates redundant data and simply waste space and it makes no sense for each variable to contain this value as it has absolutely nothing to do with that SomeObject instance. This class design is counter intuitive of a good design. As #Tim Schmelter’s comment points out "a single object should not know anything about the total amount of other objects." This “redundant data” situation is something a programmer should try to avoid, not promote.
I want to add row number in object list.
here's the they i do it now but there must be better way
Profile for mapping
public class VendorEnquiryDM_TO_VM : Profile
{
public VendorEnquiryDM_TO_VM()
{
CreateMap<VENDORENQUIRY, VendorEnquiryVM>();
}
}
public class VendorEnquiryVM_TO_DM : Profile
{
public VendorEnquiryVM_TO_DM()
{
CreateMap<VENDOR_ENQUIRY, VendorEnquiryVM>().ReverseMap();
}
}
Register profile
cfg.AddProfile<VendorEnquiryDM_TO_VM>();
cfg.AddProfile<VendorEnquiryVM_TO_DM>();
This is how I add sno.
alldata = Mapper.Map<IEnumerable<Vendor_EnquiryVM>>(objDAO.getVendorEnquiry());
var _roles = alldata.Select((t, index) => new Vendor_EnquiryVM
{
sno = index + 1,
CONTACT_NO=t.CONTACT_NO,
DATE=t.DATE,
EMAIL=t.EMAIL,
id=t.id,
FIRST_NAME=t.FIRST_NAME,
wer=t.wer,
asdf=t.asdf
});
Due to just one serial no. I need to assign all properties and this is somewhat fraustrating to me for large model, please suggest me better way of doing this.
You can define a static Id and when you create the class, increment it by one
here how your class code should look like
public class Test
{
private static int mId = 0;
public Test()
{
mId = mId +1;
}
public int Id
{
get{ return mId;}
}
}
Here a demo
in order to use the same idea with collections like List, I applied some modifications and here what you can do
public class Test
{
private static int mIndex = 0; // this parameter will be incremented for each new Test
private int mId =0; // this parameter will hold the last incremented value
public Test()
{
mId = ++mIndex; // mIndex++ if you want to start with 0
}
public int Id
{
get{ return mId;}
}
}
Demo with lists
hope this will help you
So I have a CreditCard class that has some properties, one of which is for the card number as a String (public string Number { get; set; }). I'm storing the CreditCard objects in a CreditCardList class which has the variable List (private List<CreditCard> cclist = new List<CreditCard>();). I want to be able to retrieve a CreditCard by its card number by sorting the List first, then using the BinarySearch method on the List. I also want to do this by passing a String indexer of the number to search for into the BinarySearch method, along with a comparer if I need one.
This is what I have so far for the method to get the CreditCard matching the number, but Visual Studio 2013 gives me an error on the line: int index = cclist.BinarySearch(cclist[input], new CreditCardComparer()); "the best overloaded method match for 'System.Collections.Generic.List.this[int]' has some invalid arguments." I assume it's because I'm using the String indexer wrong or something.
public List<CreditCard> GetCardByNumber (string input)
{
List<CreditCard> tempList = new List<CreditCard>();
// save the current unsorted list to a temporary list to revert back to after sorting
List<CreditCard> originalList = new List<CreditCard>(cclist.Capacity);
for (int i = 0; i < cclist.Capacity; i++)
{
originalList[i] = cclist[i];
}
// begin sorting for binary search of card number
cclist.Sort();
int index = cclist.BinarySearch(cclist[input], new CreditCardComparer());
if (index < 0)
{
tempList.Add(cclist[input]);
}
// revert back to the original unsorted list
for (int i = 0; i < originalList.Capacity; i++)
{
cclist[i] = originalList[i];
}
// return the found credit card matching the specified number
return tempList;
}// end GetCardByNumber (string input)
Here are my int and string indexers:
public CreditCard this[int i]
{
get
{
if (i < 0 || i >= cclist.Count)
{
throw new ArgumentOutOfRangeException("index " + i + " does not exist");
}
return cclist[i];
}
set
{
if (i < 0 || i >= cclist.Count)
{
throw new ArgumentOutOfRangeException("index " + i + " does not exist");
}
cclist[i] = value;
saveNeeded = true;
}
}// end CreditCard this[int i]
public CreditCard this[string input]
{
get
{
foreach (CreditCard cc in cclist)
{
if (cc.Number == input)
{
return cc;
}
}
return null;
}
}// end CreditCard this[string number]
And here is my comparer class:
public class CreditCardComparer : IComparer<CreditCard>
{
public override int Compare(CreditCard x, CreditCard y)
{
return x.Number.CompareTo(y.Number);
}
}// end CreditCardComparer : IComparer<CreditCard>
And lastly, here are the necessities for my list sorting and what not...
class CreditCard : IEquatable<CreditCard>, IComparable<CreditCard>
{
public bool Equals (CreditCard other)
{
if (this.Number == other.Number)
{
return true;
}
else
{
return false;
}
}// end Equals(CreditCard other)
public int CompareTo(CreditCard other)
{
return Number.CompareTo(other.Number);
}// end CompareTo(CreditCard other)
}
Is it truly possible to do what I'm attempting, i.e. sending a string indexer that returns a CreditCard object based on a string into a BinarySearch method of List?
Also, I can provide any more code if necessary, but I felt like this was a little much to begin with.
A System.Collections.Generic.List uses an int as the indexer property, it does not let you use a string.
If you want to use a string as your indexer (primary key), you should probably use a Dictionary<string,CreditCard> instead.
There are a couple things amiss in your GetCardByNumber method. First is the method returns an entire list instead of a single CreditCard, which goes against the method name. Second, the binary search is not even needed since you do the searching in the string indexer first:
public CreditCard this[string input]
{
get
{
foreach (CreditCard cc in cclist)
{
if (cc.Number == input)
{
return cc;
}
}
return null;
}
}
By this point, you've already found the CreditCard with the information you need, so why search for it again in a BinarySearch? Thirdly, as was covered in landoncz's answer, you can't use a string as an index for a List<T>. What you probably intended to use was the CreditCardList instead of the List<CreditCard>
CreditCardList creditCardList = new CreditCardList();
creditCardList["1234"]; //correct
List<CreditCard> cclist = new List<CreditCard>();
cclist["1234"]; //incorrect. This is where your error is coming from.
If you're trying to access the indexer property inside of the class that implements it (which I'm assuming you are trying to do in your GetCardByNumber method), just use this[index]:
public class CreditCardList
{
public CreditCard this[string s] { /*Implementation*/ }
public CreditCard GetCard(string s)
{
return this[s]; // right here!
}
}
Now... according to your comment, "Retrieve the CreditCard with a specified number if it exists using the BinarySearch method in List<T> in the implementation of a String indexer.", it seems to me that the assignment wants you doing something along these lines. (a thing to note is that I'm not sure of your entire implementation of the CreditCard class, so please excuse the naive instantiation in the following code)
public class CreditCardList
{
private List<CreditCard> cclist = new List<CreditCard>();
public CreditCardList()
{
//For the sake of an example, let's magically populate the list.
MagicallyPopulateAList(cclist);
}
public CreditCard this[string s] /* In the implementation of a String indexer... */
{
get
{
CreditCard ccToSearchFor = new CreditCard() { Number = value };
cclist.Sort();
/* ...use the BinarySearch method... */
int index = cclist.BinarySearch(ccToSearchFor);
if (index >= 0)
return cclist[index]; /* ...to retrieve a CreditCard. */
else
throw new ArgumentException("Credit Card Number not found.");
}
}
}
I've been searching the internet and books but have had no luck so was hoping someone could point me in the right direction.
I basically need to sort objects by their name statement alphabetically using an insertion sort rather than the built in methods. I have tried using an Array and List but can't seem to get it to work. How would you go about doing it?
I have a class of Player, latest attempt filled with list objects:
public static List<Player> user = new List<Player>();
private string name; //Read and Write
private int score; //Read and Write
private double health; //Read and Write
private int level; //Read and Write
public string[] inventory = new string[30];
public void setName(String newName)
{
name = newName;
}
public string getName()
{
return name;
}
public void setScore(int newScore)
{
score = newScore;
}
public int getScore()
{
return score;
}
public void setHealth(double newHealth)
{
health = newHealth;
}
public double getHealth()
{
return health;
}
public void setLevel(int newLevel)
{
level = newLevel;
}
public int getLevel()
{
return level;
}
public static void Saved_Player()
{
user.Add(new Player() { name = "Timid Bob", health = 63, level = 6, score = 2000, });
user[0].inventory[0] = "Steel Sword";
user[0].inventory[1] = "1mm MAW";
user[0].inventory[2] = "Short Bow";
user[0].inventory[0] = "Grenade";
user.Add(new Player() {name = "Killer Bob", health = 82, level = 2, score = 1050000, });
user[1].inventory[0] = "Glass Sword";
user[1].inventory[1] = "250mm MAW";
user[1].inventory[2] = "Elephant Bow";
user[1].inventory[3] = "Rock";
etc... upto 6 user objects
To sort it I'm trying to use the following code in another class Form1:
//sudo code
for(int i = 0; i < Player.user.Count; i++)
{
while (i index is higher than i+1 index)
{
swap i index with i+1 index
}
}
Hope that is right :/
I think I understand how PublicJoe's has done it but how do you get and set the index of an object? Thanks for looking.
Arrays are bad for inserting into. if you think back to your classes, you might find a data structure that works better for inserting.
In an insertion sort, you take an item of your unsorted list, and then put it in the correct spot of the other list.
What you seem to be trying to do, appears to be some sort selection sort.
I think there's a problem with the 4 lines where you swap your values
object temp;
object = Player.user[Second];
Player.user[first] = Player.user[Second];
Player.user[(temp - 1)] = Player.user[Second];
I'd have a second look at that if i were you.
If you're using a list, you can simply do this:
public void InsertionSort(Player newUser)
{
var index = users.FindLastIndex(u => u.Name <= newUser.Name);
users.Insert(index, newUser);
}