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