0

Alright so I am making a program to verify a 4 digit code.

The computer generates a 4 digit code The user types in a 4 digit code. Their guess. the computer tells them how many digits are guessed correctly in the correct place and how many digits have been guessed correctly but in the wrong place. The user gets 12 guesses to either win – guess the right code. Or lose – run out of guesses.

So basically, my program doesn't seem to actually verify whether the code is correct but i cant see why not because i have if and for loops for verification, please take a look.

class Program
{
    public static Random random = new Random();
    static void Main(string[] args)
    {
        int DigitOne = random.Next(0, 10);
        int DigitTwo = random.Next(0, 10);
        int DigitThree = random.Next(0, 10);
        int DigitFour = random.Next(0, 10);

        byte[] code = new byte[4];
        code[0] = Convert.ToByte(DigitOne);
        code[1] = Convert.ToByte(DigitTwo);
        code[2] = Convert.ToByte(DigitThree);
        code[3] = Convert.ToByte(DigitFour);
        bool CodeCorrect = false;
        Console.WriteLine(code[0] +""+ code[1] +""+ code[2]+""+code [3] );

        Console.WriteLine("You have 12 guesses before you will be permenantly locked out.\n");
        int AmountOfGuesses = 0;
        while (AmountOfGuesses < 12 && !CodeCorrect)
        {
            Console.WriteLine("Enter 4 digit code to unlock the safe: ");
            int[] UserCode = new int[4];

            for (int i = 0; i < 4; i++)
            {
                UserCode[i] = Convert.ToInt32(Console.Read()) - 48;
            }
            if (UserCode.Length != 4)
            {
                Console.WriteLine("Error. Try Again.\n");
            }
            else
            {
                int UserDigitOne = UserCode[0];
                int UserDigitTwo = UserCode[1];
                int UserDigitThree = UserCode[2];
                int UserDigitFour = UserCode[3];
                for (int i = 0; i < 4; i++)
                {
                    if (UserCode[i] == code[i])
                    {
                        Console.WriteLine("The digit at position " + (i + 1) + " is correct.");
                    }
                }  


                if (UserCode[0] == code[0] && UserCode[1] == code[1] && UserCode[2] == code[2] && UserCode[3] == code[3])
                {
                    CodeCorrect = true;
                    Console.WriteLine("Code Correct. Safe unlocked.");

                }
            }



            AmountOfGuesses++;
        }

        if (AmountOfGuesses > 12)
        {
            Console.WriteLine("Code Incorrect. Safe Locked permenantly.");
        }

        Console.ReadLine();

    }

2 Answers2

1

You are comparing numbers with the character representation of a number. Each value of code[] represents an actual number. You then compare those values with the values in UserCode which is a string, meaning there is a character at each index. It is never the case that ((byte)'4') == ((byte)4) (using 4 as an example, but works for any numerical digit).

One way around this is to parse each user input character into a byte using the byte.Parse method.


For fun learning purposes look at the output from the following code:

for (char i = '0'; i <= '9'; i++)
{
    Console.WriteLine("char: " + i + "; value: " + ((byte)i));
}

The output is actually:

char: 0; value: 48
char: 1; value: 49
char: 2; value: 50
char: 3; value: 51
char: 4; value: 52
char: 5; value: 53
char: 6; value: 54
char: 7; value: 55
char: 8; value: 56
char: 9; value: 57

This is due to string encoding.

I would also recommend that one you have your code working that you submit it to the fine folks at the Code Review site to review other aspects of the code which could use work.

Community
  • 1
  • 1
Anthony
  • 9,451
  • 9
  • 45
  • 72
1

If you step through the code after it generated the number 1246, and then input the same number from the command line, convert it to a char array, then convert each char to a byte, you'll get the following four bytes:

49 50 52 54

These correspond to the ASCII representations of each char, NOT the actual numbers.

Try something like this:

int[] input = new int[4];

for(int i = 0; i < 4; i++ )
{
    input[i] = Convert.ToInt32(Console.Read()) - 48;
}

The -48 should turn your ASCII code into the actual numerical representation that was provided. Console.Read() reads individual characters rather than the full line.

Also, you don't have to say:

CodeCorrect == false

This is more simply represented as:

!CodeCorrect

Similarly, if it was set to true, it would just be:

CodeCorrect 

I also suggest using a for loop to set multiple elements in an array rather than manually writing out each line of code. It's not a big deal for small arrays, but it's good practice.

UPDATE: Here's a revised version of the full program:

class Program 
{ 
    public static Random random = new Random(); 
    static void Main(string[] args) 
    {
        int[] randCombination = new int[4];
        for (int i = 0; i < 4; i++)
        {
            randCombination[i] = random.Next(0, 10);
            Console.Write(randCombination[i].ToString());
        }
        bool CodeCorrect = false;

        Console.WriteLine("\nYou have 12 guesses before you will be permenantly locked out.\n");

        int AmountOfGuesses = 0;
        while(AmountOfGuesses < 12 && !CodeCorrect)
        {
            Console.WriteLine("Enter 4 digit code to unlock the safe: ");

            int[] UserCode = new int[4];
            string input = Console.ReadLine();

            int n;
            bool isNumeric = int.TryParse(input, out n);

            int correctCount = 0;

            if(input.Length != 4 || !isNumeric)
            {
                Console.WriteLine("Error. Input code was not a 4 digit number.\n");
            }
            else 
            {
                for(int i = 0; i < 4; i++)
                {
                    UserCode[i] = Convert.ToInt32(input[i]) - 48;

                    if(UserCode[i] == randCombination[i])
                    {
                        Console.WriteLine("The digit at position " + (i + 1) + " is correct.");
                        correctCount++;
                    }
                }

                if(correctCount == 4)
                {
                    CodeCorrect = true;
                    Console.WriteLine("Code Correct. Safe unlocked.");
                }
            }
            AmountOfGuesses++;
        }

        if(AmountOfGuesses >= 12)
        {
            Console.WriteLine("Code Incorrect. Safe Locked permenantly.");
        }

        Console.ReadLine();
    }
}

A couple of things were changed:

  • Added a for loop at the top that generates a random number, enters it into an array of ints and then prints it to standard output.
  • I changed the way user input is read back to the Console.ReadLine(). The reason for this is to check if the user inputted a four digit integer. the int.TryParse statement makes sure the input is an int, and the Length property checks the length.
  • I also used a counter to count each correct guess. If 4 correct digit guesses were made, the safe is unlocked.
  • Your final if statement would never have evaluated because Amount of Guesses would equal 12, not be greater than it. Changed it to >= from >. Always be on the lookout for small things like this.

EDIT #2: For more information on int.TryParse, see the following:

Community
  • 1
  • 1
Augustin Popa
  • 1,423
  • 1
  • 19
  • 22
  • I have implemented the change you said, and to some degree it works but it still doesn't recognize every value correctly, Ive edited the code in the questions, could you please look again and try to explain why, sorry to pester just that i am learning c# and want to understand where i am going wrong in my program so i can implement thigns in future. – user3063533 Oct 17 '14 at 19:32
  • Can you add your revised code to your post so I can take a look at it? – Augustin Popa Oct 17 '14 at 19:35
  • there we go, refresh and you should see it – user3063533 Oct 17 '14 at 19:37
  • Yes, I'm looking at it now. – Augustin Popa Oct 17 '14 at 19:55
  • I added a revised version of the code along with some points explaining what I changed. I switched back to reading the full line from standard input and now the program makes sure user input is a 4 digit int. Let me know if there are any more questions :). – Augustin Popa Oct 17 '14 at 20:10
  • Thanks very much, You have been very helpful, could you briefly explain however what tryParse does? – user3063533 Oct 17 '14 at 20:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63256/discussion-between-user3063533-and-augpopa). – user3063533 Oct 17 '14 at 20:21
  • I have added two links to my answer that should provide further details about int.TryParse. In essense, you can use it to check that the input is an integer then output the integer along with a bool indicating whether the parse was successful. I use this bool to make sure the user provided an int before continuing. If int.TryParse return true, I have an int and proceed with the rest of the code, otherwise I output an error. – Augustin Popa Oct 17 '14 at 20:23