0

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();
        }
    }
}
Razzon22
  • 17
  • 7

1 Answers1

-1

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");
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • For some reason, my online editor is _still_ making it completely refresh every time I use Console.ReadLine, including all of the variables that are set by it. – Razzon22 Nov 29 '22 at 15:52
  • 1
    after ReadLine, your code exits. how come it run again? must be rerun. should be different. – urlreader Nov 29 '22 at 15:56
  • You are calling `deck = rtools.shuffle(deck);` only once per program execution. So, what are you expecting? If you want to call it repeatedly without restarting the program, you must use it in a loop. – Olivier Jacot-Descombes Nov 29 '22 at 16:00
  • I added a working example. It also lets you quit the application by entering "quit" + Enter. You can force a new shuffle by entering "new" + Enter. – Olivier Jacot-Descombes Nov 30 '22 at 12:13
  • The default constructor for `Random` uses `Environment.Ticks` anyway. – Enigmativity Nov 30 '22 at 22:13
  • @Enigmativity, yes but OP wants to repeat the same random sequence a few times before creating an entirely new one. Therefore, I'm creating a random seed that can be reused manually. – Olivier Jacot-Descombes Dec 01 '22 at 12:37