How do I create an array of objects in constructor? - c#

I have two classes:
game
element
I want to be able to define an array of element objects in a game object. When I try this I get the warning message "..is never assigned to, and will always have its default value null"; in the local variables in the debugger I can see that the array exists, but all entries are null. The class Element works as I would expect. If I assign element objects to an array in Main it works, but not when I move the code to the Game constructor.
What am I doing wrong? I'm new to C# so it could be something very basic. Code below. Many thanks.
class Element
{
public Element()
{
elements = new List<int>(3);
elements.Add(1);
elements.Add(2);
elements.Add(3);
}
List<int> elements;
public void PrintElement()
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Element {0}: {0}", i + 1, elements[i]);
}
}
}
class Game
{
public Game()
{
Element1 = new Element();
Element2 = new Element();
Element3 = new Element();
Element[] ThisGame = new Element[3];
ThisGame[0]= Element1;
ThisGame[1] = Element2;
ThisGame[2] = Element3;
}
public Element[] ThisGame;
private Element Element1;
private Element Element2;
private Element Element3;
public void PrintGameElement(int number)
{
ThisGame[number].PrintElement();
}
}
class Program
{
Game MyGame;
static void Main(string[] args)
{
Game MyGame = new Game();
MyGame.PrintGameElement(2);
Console.Read();
}
}

In Game, you are re-declaring ThisGame.
Change
Element[] ThisGame = new Element[3];
to
ThisGame = new Element[3];

Your Game constructor should look like this:
public Game()
{
Element1 = new Element();
Element2 = new Element();
Element3 = new Element();
ThisGame = new Element[3];
ThisGame[0]= Element1;
ThisGame[1] = Element2;
ThisGame[2] = Element3;
}

You need to set the list object to something when you initialize it.
List<int> elements = null;
OR
List<int> elements = new List<int>();

look at this code it may help you to make some order in your code:
Element class :
class Element
{
//property on element to save element data
public string ElementData { get; set; }
public Element(string data)
{
ElementData = data;
}
}
Game class :
class Game
{
//property on Game to save all elements
Element[] Elements { get; set; }
public Game(Element[] elements)
{
Elements = elements;
}
public void PrintGameElements()
{
foreach (var element in Elements)
{
Console.WriteLine(element.ElementData);
}
}
public void PrintElement(int index)
{
Console.WriteLine(Elements[index].ElementData);
}
}
Main function that initialize the array and pass it to the game :
static void Main(string[] args)
{
//initialize the array
var elements = new[]
{
new Element("data x"),
new Element("data y"),
new Element("data z")
};
//pass the elements to the game
var game = new Game(elements);
//print the second element
game.PrintElement(1);
//print all elements
game.PrintGameElements();
Console.ReadKey();
}
}

Related

Random.Next is refreshing after a console update

I am trying to make a card game, and I made my own shuffle function in rTools, but every time I update the console (e.g. using a console.readline statement) it re-randomizes the list. For example, in a list<string> of 1,2,3,4,5 and I use rTools.shuffle on it, the first three would be something like 3, 5, and 2. But after I refresh it without restarting the code, it would be a completely different series. I'm using an online editor, dotnetfiddle.net, if that changes anything.
I have tried multiple different approaches- here is my code:
using System;
using System.Collections.Generic;
namespace elementCard
{
public class rTools {
public rTools() {
dddd = DateTime.Now;
llll = dddd.Ticks;
ssss = llll.ToString().Substring(llll.ToString().Length - 8, 8);//This is because the original long was not accepted by System.Random(int)
_seed = Int32.Parse(ssss);
}
private DateTime dddd
{ get; set; }
private long llll
{ get; set; }
private string ssss
{ get; set; }
private int _seed
{ get; set; }
public List<string> shuffle(List<string> l)
{
int count = l.Count-1;
List<string> ret = new List<string>();
int ind = 0;
Random rng = new Random(_seed);
string card = null;
while (count > -1)
{
ind = rng.Next(0, count);
card = l[ind];
l.RemoveAt(ind);
ret.Add(card);
card = null;
count--;
}
return ret;
}
}
public class Program
{
public static void Main()
{
rTools rtools = new rTools();
Console.WriteLine("Hello World");
List<List<string>> playerHands = new List<List<string>>();
//πŸ’§πŸ”₯πŸŒ€πŸŒ±
List<string> deck = new List<string> {"1πŸ’§", "2πŸ’§", "3πŸ’§", "4πŸ’§", "5πŸ’§", "6πŸ’§", "7πŸ’§", "8πŸ’§", "9πŸ’§", "1πŸ”₯", "2πŸ”₯", "3πŸ”₯", "4πŸ”₯", "5πŸ”₯", "6πŸ”₯", "7πŸ”₯", "8πŸ”₯", "9πŸ”₯", "1πŸŒ€", "2πŸŒ€", "3πŸŒ€", "4πŸŒ€", "5πŸŒ€", "6πŸŒ€", "7πŸŒ€", "8πŸŒ€", "9πŸŒ€", "1🌱", "2🌱", "3🌱", "4🌱", "5🌱", "6🌱", "7🌱", "8🌱", "9🌱"};
List<string> sDeck = new List<string> {"RπŸ”„", "S❌", "DπŸ”³", "Xβ›ˆ", "+✨", "AπŸŒ•", "AπŸŒ‘"};
List<string> vDeck = new List<string> {"Vβ—†", "Vβ—‡", "Vβ—ˆ"};
deck = rtools.shuffle(deck);
Console.WriteLine(deck[0]);
Console.ReadLine();
Console.ReadLine();
}
}
}
Specify a seed when creating the dictionary:
Random rng = new Random(42);
Otherwise, it will automatically initialize it with a seed based on the current date/time.
You can create a new seed at every start of the program with:
public static class rTools {
// Creates a "random" seed at every start of the program.
private static readonly int _seed = (int)DateTime.Now.Ticks;
public static List<string> shuffle(List<string> l) //Shuffle function
{
...
Random rng = new Random(_seed);
...
}
}
You can also drop the readonly keyword if you want replace the seed later, or make the rTools class non static as well as all its members. Then a new seed will be created whenever you create a new instance of this class. This gives you the full control on when you want to create a completely different series.
Here is a complete solution:
The class
public class RTools
{
private readonly int _seed = (int)DateTime.Now.Ticks;
public List<string> Shuffle(List<string> l)
{
List<string> ret = new List<string>();
Random rng = new Random(_seed);
// Since you remove items, use the current count of the list.
while (l.Count > 0) {
int ind = rng.Next(0, l.Count);
string card = l[ind];
l.RemoveAt(ind);
ret.Add(card);
}
return ret;
}
}
Body of Main method
// Lets you write fancy Unicode characters.
Console.OutputEncoding = System.Text.Encoding.UTF8;
RTools rtools = new RTools();
string input;
do {
Console.WriteLine("Hello World");
List<List<string>> playerHands = new List<List<string>>();
//πŸ’§πŸ”₯πŸŒ€πŸŒ±
List<string> deck = new List<string> { "1πŸ’§", "2πŸ’§", "3πŸ’§", "4πŸ’§", "5πŸ’§", "6πŸ’§", "7πŸ’§", "8πŸ’§", "9πŸ’§", "1πŸ”₯", "2πŸ”₯", "3πŸ”₯", "4πŸ”₯", "5πŸ”₯", "6πŸ”₯", "7πŸ”₯", "8πŸ”₯", "9πŸ”₯", "1πŸŒ€", "2πŸŒ€", "3πŸŒ€", "4πŸŒ€", "5πŸŒ€", "6πŸŒ€", "7πŸŒ€", "8πŸŒ€", "9πŸŒ€", "1🌱", "2🌱", "3🌱", "4🌱", "5🌱", "6🌱", "7🌱", "8🌱", "9🌱" };
List<string> sDeck = new List<string> { "RπŸ”„", "S❌", "DπŸ”³", "Xβ›ˆ", "+✨", "AπŸŒ•", "AπŸŒ‘" };
List<string> vDeck = new List<string> { "Vβ—†", "Vβ—‡", "Vβ—ˆ" };
deck = rtools.Shuffle(deck);
foreach (string card in deck) {
Console.WriteLine(card);
}
Console.WriteLine();
input = Console.ReadLine();
if (input == "new") { // Create a completely new card deck.
rtools = new RTools();
}
} while (input != "quit");

List as local and global variable and changing global list value after method call

public Class Card
{
}
public partial class Form
{
List<Card> list2 = new List<Card>();
}
public List<Card> insertInList(ref List<Card> list1)
{
foreach(...)
{
list1.Add(instanceOfObject Card)
}
return list2;
}
private void btn_click(...)
{
insertInList(ref list2);
}
Edit 1 As this is my second edit, I would appreciate If somebody can tell me that I am using "ref" modifiers well in order to have list full of elements after calling insertInList() method?
Edit 2 How would You change this example, but to have same list full of elements after insert method call, but If your list is defined in method insertInList?
Edit3 (The Biggest Issue) I have still problem, that I am getting 3 lists (same names as Namespace.Class) in ListBox while I am expecting only 1?
public List<Karta> ubaciUListu(ref List<Karta> Lista1)
{
//List<Karta> Lista11 = new List<Karta>();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
Karta k = new Karta(0,"","");
// k.Id =(int)row.Cells[0].Value;
k.Pojam =(string) row.Cells[1].Value;
k.Opis = (string)row.Cells[2].Value;
Lista1.Add(k);
}
return Lista1;
}
public partial class Form2 : Form
{
List<Karta> nova = new List<Karta>();
public Form2(List<Karta> input)
{
InitializeComponent();
nova = input;
if (nova.Count!=0)
{
lstBox.DataSource = nova;
}
}

Initilialising an array of objects that contain an array of other objects?

I am trying to declare an array of buildings but the floors associated with each building are never initialised. I want to provide values to the data members for each instance of floor that is associated with each instance of building:
class Floor
{
public int number;
public int rooms;
//constructor
Floor()
{
rooms = 5;
number= 0;
}
}
class Building
{
public Floor[] floors= new Floor[6];
}
public partial class frmF2 : Form
{
Building[] x = new Building[7];
...
}
But it is very ugly.
class Building
{
Building()
{
floors = new Floor[6];
for(int i=0; i<6;++i)
floors[i] = new Floor();
}
public Floor[] floors;
}

Acessing object through object array

I want to learn classes atm and here is what I came up with:
Class level to create a level. This class has an object array that fills itself with rooms (raeume) which is the other class. Now, I want to access the objects in the object array from room, after I inserted them. Here is what I want to type:
wohnung.rooms[i].raumname.toString();
Here are the two classes
class raum
{
static object[] o_nebenraum = new object[3]; //N-O-S-W
static string s_raumname = "";
public object[] nebenraume
{
get
{
return o_nebenraum;
}
set
{
o_nebenraum = value;
}
}
public string raumname
{
get
{
return s_raumname;
}
set
{
s_raumname = value;
}
}
}
class level
{
static object[] o_rooms = new object[100];
public object[] rooms
{
get
{
return o_rooms;
}
set
{
o_rooms = value;
}
}
}
Here is how I set everything up.
level wohnung = new level();
raum keller = new raum();
raum wohnzimmer = new raum();
raum kueche = new raum();
raum schlafzimmer = new raum();
wohnung.rooms[0] = keller;
wohnung.rooms[1] = wohnzimmer;
wohnung.rooms[2] = kueche;
wohnung.rooms[3] = schlafzimmer;
keller.raumname = "Keller";
wohnzimmer.raumname = "Wohnzimmer";
kueche.raumname = "KΓΌche";
schlafzimmer.raumname = "Schlafzimmer";
for (uint i = 0; i < 3; i++)
{
Console.WriteLine("Wohnung beinhaltet jetzt " + *MISSING CODE PART, I WANT TO GET THE .raumname out of the object array from wohnung.room*);
}
Console.ReadKey();
You have to use generic typed list List<T> (See on MSDN) instead of array, in this case you'll have the indexed access for the typed list elements
So instead of:
static object[] o_rooms = new object[100];
public object[] rooms
Use:
static IList<raum> o_rooms = new List<Raum>(100);
public IList<raum> rooms
Try this(in the for Loop):
Console.WriteLine("Wohnung beinhaltet jetzt " + (wohnung.rooms[i] as raum).raumname );
You would be better off using generics though in which case the class level would now look like:
class level
{
static List<raum> o_rooms = new List<raum>();
public List<raum> rooms
{
get { return o_rooms; }
set { o_rooms = value; }
}
}
and the for loop can be replaced with a foreach loop as follows:
foreach(raum room in wohnung.rooms)
{
Console.WriteLine("Wohnung beinhaltet jetzt " + room.raumname );
}

List inside object becomes empty again after exiting function block

I have an object 'ForValidation' that has List of int as a property,
and an object 'Validator' which has a Verify(IEnumerable ForValidation) method. Verify method adds numbers in ForValidation list property.
In main function, I have IEnumerable of Validator and IEnumerable of ForValidation
every time Verify(IEnumerable) exits, the list inside ForValidation is back at 0 count.
From my understanding, objects are reference types in C# and modifications from anywhere should reflect in the same object.
I tried running visual studio debugger line by line to check that list inside 'ForValidation' is in fact being added data and then disappears after Verify method.
public class ForValidation
{
private readonly object #lock = new object();
private readonly List<int> ExistenceChecks = new List<int>();
public IEnumerable<int> ExistsPlaces => ExistenceChecks;
public string CheckProperty { get; }
public ForValidation(string checkProperty )
{
CheckProperty = checkProperty ;
}
public void ConfirmExistence(int place)
{
lock (#lock)
{
ExistenceChecks.Add(place);
}
}
}
public class Validator
{
public int ValidatorNumber { get; }
private readonly Datasource somedatasource;
public Validator(int number, Datasource someds)
{
ValidatorNumber = number;
somedatasource = someds;
}
public void Verify(IEnumerable<ForValidation> forValidations)
{
ForValidation[] copy = forValidations.ToArray();
IEnumerable<string> checkProperties = from member in copy
select member.CheckProperty;
IEnumerable<CompareAgainst> existingMembers
= somedatasource.Filter(new CheckPropertiesFilter(checkProperties)).Execute();
foreach (ForValidation forValidation in copy)
{
if (existingMembers.FirstOrDefault(m => m.CheckProperty == forValidation.CheckProperty) != null)
{
forValidation.ConfirmExistence(ValidatorNumber);
}
}
int x = copy.Length;
//each forValidation.ExistsPlaces has items until this code block
}
}
main
{
private readonly IEnumerable<ForValidation> forValidations {...}
private readonly IEnumerable<Validator> validators {...}
foreach (Validator validator in validators)
{
validator.Verify(forValidations);
// each forValidation.ExistsPlaces count is 0 again in this block
}
}
IExpect every ForValidation items inside forValidations will have remembered items inside its IEnumerable ExistsPlaces property after each Verify method by validators but it becomes 0 count after each iteration of Verify method in the foreach loop
I cannot reproduce your problem. Here is my code.
public static void Main(string[] args)
{
var validators = new[] { new Validator(666), new Validator(667) };
var forValidations = new [] { new ForValidation("v1"), new ForValidation("v2") };
Console.WriteLine("Before Verify");
foreach (var fv in forValidations)
Console.WriteLine($"Object: {fv.CheckProperty} - count of places: {fv.ExistsPlaces.Count()}");
foreach (Validator validator in validators)
validator.Verify(forValidations);
Console.WriteLine("After Verify");
foreach (var fv in forValidations)
Console.WriteLine($"Object: {fv.CheckProperty} - count of places: {fv.ExistsPlaces.Count()}");
}
Result
Before Verify
Object: v1 - count of places: 0
Object: v2 - count of places: 0
After Verify
Object: v1 - count of places: 2
Object: v2 - count of places: 2
Classes:
public class ForValidation
{
private readonly object #lock = new object();
private readonly List<int> ExistenceChecks = new List<int>();
public IEnumerable<int> ExistsPlaces => ExistenceChecks;
public string CheckProperty { get; }
public ForValidation(string checkProperty)
{
CheckProperty = checkProperty;
}
public void ConfirmExistence(int place)
{
lock (#lock)
{
ExistenceChecks.Add(place);
}
}
}
public class Validator
{
public Validator(int validatorNumber)
{
ValidatorNumber = validatorNumber;
}
public int ValidatorNumber { get; }
public void Verify(IEnumerable<ForValidation> forValidations)
{
ForValidation[] copy = forValidations.ToArray();
IEnumerable<string> checkProperties = from member in copy
select member.CheckProperty;
foreach (ForValidation forValidation in copy)
{
//if (existingMembers.FirstOrDefault(m => m.CheckProperty == forValidation.CheckProperty) != null)
{
forValidation.ConfirmExistence(ValidatorNumber);
}
}
int x = copy.Length;
//each forValidation.ExistsPlaces has items until this code block
}
}

Categories