0

So i got my hangman up and running but the what i dont like is the way my program picks the random word (which isnt completely random and can be guessed, pseudo)..

NOTE: Some parts in the code are in Slovene language. I changed the important ones to english.

I'm trying to make a simpler and actually random way to pick that word. I did try to implement various other options but without success...

Also i do not really understand how DateTime.Now.Ticks picks a word.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace HANGMAN //moj imenski prostor

{
    class Program
    {
        static void Main(string[] args)
        {
            Random random = new Random((int)DateTime.Now.Ticks);

        string[] WORDBANK = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF" };

        string WordToGuess = WORDBANK[random.Next(0, WORDBANK.Length)];
        string WordToGuessUppercase = WordToGuess.ToUpper();

        StringBuilder displayToPlayer = new StringBuilder(WordToGuess.Length);
        for (int i = 0; i < WordToGuess.Length; i++)
            displayToPlayer.Append('_');

        List<char> correctGuesses = new List<char>();
        List<char> incorrectGuesses = new List<char>();

        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.WriteLine("__________________________________________________________________");
        Console.WriteLine();
        Console.Write("VISLICE - Maturitetna Naloga pri predmetu Informatika");
        Console.WriteLine();
        Console.WriteLine("__________________________________________________________________");
        Console.WriteLine();
        Console.WriteLine("-> Imas 5 poizkusov <-");
        Console.WriteLine();
        Thread.Sleep(500);

        int lives = 5;
        bool won = false;
        int lettersRevealed = 0;

        string input;
        char Guess;

        while (!won && lives > 0) 
        {
            Thread.Sleep(500);
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Ugani besedo, izberi crko: ");
            Console.WriteLine();


            input = Console.ReadLine().ToUpper();
            Ugib = input[0];

            if (correctGuesses.Contains(Guess)) 
            {
                Thread.Sleep(500);
                Console.WriteLine();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Crko '{0}' si ze uporabil, bila je pravilna!", Guess);
                Console.WriteLine("____________________________________________");
                continue;
            }

            else if (nepravilniUgibi.Contains(Ugib)) 
            {
                Thread.Sleep(500);
                Console.WriteLine();
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Crko '{0}' si ze uporabil, bila je napacna!", Guess);
                Console.WriteLine("___________________________________________");
                continue;
            }

            if (WordToGuessUppercase.Contains(Guess)) 
            {
                pravilniUgibi.Add(Ugib);

                for (int i = 0; i < WordToGuess.Length; i++) 
                {
                    if (WordToGuessUppercase[i] == Guess)
                    {
                        displayToPlayer[i] = WordToGuess[i];
                        lettersRevealed++;
                    }
                }

                if (lettersRevealed == WordToGuess.Length)
                    won = true;
            }
            else 
            {
                incorrectGuesses.Add(Guess);

                Console.WriteLine();
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Narobe, crke '{0}', ni v besedi!", Guess);
                Console.WriteLine("________________________________");
                Console.WriteLine();
                poizkusi--;
            }

            Console.WriteLine(displayToPlayer.ToString());
        }

        if (won)
        {
            Console.WriteLine();
            Thread.Sleep(500);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Zmaga!");
            Console.WriteLine();
            Thread.Sleep(1000);
            Console.WriteLine("KONEC IGRE");
        }    
        else
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine();
            Thread.Sleep(1000);
            Console.WriteLine("Zal si to igro zgubil. Poskusi ponovno! Pravilna beseda je bila '{0}'", WordToGuess);
        }

    }
}

}

J.Pisar
  • 17
  • 2
  • Well i've been told that the DateTime.Now.Ticks isnt completly random, that its Pseudo-random? Also could you explain what exactly does the DateTime.Now:Ticks do? – J.Pisar Apr 02 '17 at 18:03
  • DateTime.Now.Ticks itself is not random at all, it is just the number of 100ns intervals since midnight, January 1st, 0001. But it makes for a good [random number generator seed](https://referencesource.microsoft.com/#mscorlib/system/random.cs,92e3cf6e56571d5a,references), it will be different each time you call it, at least on the same machine and if nothing tampers with the clock. The actual random stuff happens when you [call Next()](https://referencesource.microsoft.com/#mscorlib/system/random.cs,ddd1e9e09c70bab5,references). – Cee McSharpface Apr 02 '17 at 18:09
  • @dlatikay: _"it will be different each time you call it"_ -- this is not quite true. The tick count is not increased quickly enough to guarantee this. A C# program can execute a large number of statements (dozens, if not hundreds or more) before the count is increased. It's also worth noting that [the default seed for `Random` already uses a clock tick count](https://referencesource.microsoft.com/#mscorlib/system/random.cs,5d22f8880fc9f8d9), so there's not really any point in passing that explicitly. – Peter Duniho Apr 02 '17 at 18:39
  • 1
    To the OP: it is not really clear what your question is. Your use of `Random` in the code example seems fine, and not _"guessable"_ at all. Your question should include a good [mcve] that reliably reproduces whatever specific problem you are seeking help with, along with a detailed explanation of what that code does, what you want it to do instead, and what _specifically_ you are having trouble figuring out. – Peter Duniho Apr 02 '17 at 18:41
  • @PeterDuniho sure. but we're not talking about newly seeded instances every other millisecond - op code seeds once per main(), and is waiting for console input etc. the default seed to random is a part of my answer. the real problem of OP code is a trivial misplaced variable. – Cee McSharpface Apr 02 '17 at 23:03
  • @dlatikay: your statement that `DateTime.Now.Ticks` _"will be different each time you call it"_ is what I am addressing. The OP's code only creates a single `Random` object, which means a statement about "each time you call it" implicitly is to be take more broadly than the code at hand (since "each time you call it" implies multiple calls, which doesn't apply here). And your statement taken at face value is just plain wrong. The value won't be different literally _each time_ it's called. – Peter Duniho Apr 02 '17 at 23:40
  • @dlatikay: _"the real problem of OP code is a trivial misplaced variable"_ -- I think your guess about the bug is a reasonable one, but please note that the code above won't compile at all, due to the use of `WordToGuess` before it's been initialized. For all we know (including you), the misuse of `WordToGuess` is a transcription error, and not actually present in the real code. Since the OP didn't provide actual code, it's impossible to know for sure what the problem _really_ is. – Peter Duniho Apr 02 '17 at 23:40
  • edited both into my answer in good faith that we will eventually see an mcve that compiles. – Cee McSharpface Apr 03 '17 at 00:00

1 Answers1

0

The random number generator is fine. The ticks in the Random constructor will seed the generator with a different number each time your program runs. You can expect that no two sequences will be the same: C# - Random number with seed (be careful not no create new instances of Random faster than the tick count increments).

Note that calling the constructor as new Random(System.DateTime.Now.Ticks) is almost the same as calling the parameterless constructor, new Random(), because that seeds it with the value of Environment.TickCount - which is the number of ticks since the machine booted - in the current implementation of the .NET framework.

Pseudo-random: yes.
There is a whole bunch of questions dealing with the implementation, its theoretical background, and true random sources, start here: https://stackoverflow.com/a/4440760/1132334


Regarding the code, you have a simple mistake in the call to Next:

Instead of

string WordToGuess = WORDBANK[random.Next(0, WordToGuess.Length)];

write

string WordToGuess = WORDBANK[random.Next(0, WORDBANK.Length)];

The forward reference WordToGuess.Length does not compile in C#, you intended to use the length of the wordbank array for sure. The second int argument is the exclusive upper bound, documented here.

Community
  • 1
  • 1
Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77