0

I'm trying to create a console application for basic banking functions. I understand how the random number generator works, but I need to set up an array so that the random numbers don't repeat, considering that the random number that is generated represents the users personalized PIN number. How would I implement this into my current code?

class BankAccount
{
    private string firstName;
    private string lastName;
    private int accountNumber;
    private decimal balance;
    static public int customers = 0;
    private int pinNumber;

    public decimal Balance
    {
        get
        {
            return balance;
        }
        set
        {
            if (value >= 0)
                balance = value;
            else
            {
                Console.WriteLine("There will be an overdraft fee of $10.00.");
                balance = value - 10;
            }
        }
    }

    public string FirstName
    {
        get
        {
            return firstName;
        }
    }

    public string LastName
    {
        get
        {
            return lastName;
        }
    }

    public int AccountNumber
    {
        get
        {
            return accountNumber;
        }
    }

    public int PinNumber
    {
        get
        {
            return pinNumber;
        }
    }

    public BankAccount(string firstNameValue, string lastNameValue)
    {
        firstName = firstNameValue;
        lastName = lastNameValue;
        accountNumber = customers + 1;
        Random pin = new Random();
        pinNumber = pin.Next(1111, 9999);
        Balance = 0;
        customers++;
    }

    public BankAccount()
    {
        Balance = 0;
        customers++;
    }

    public void Credit(decimal amount)
    {
        Balance = Balance + amount;
    }

    public void Debit(decimal amount)
    {
        if (amount > Balance)
            Console.WriteLine("Debit amount exceeded account balance.");
        Balance = Balance - amount;
    }

    public static decimal AverageBalance(BankAccount[] accounts)
    {
        int count = 0;
        decimal total = 0;
        for (int i = 0; i < accounts.Length; i++)
        {
            if (accounts[i] != null)
            {
                total += accounts[i].Balance;
                count++;
            }
        }
        return total / count;
    }
}
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • Don't want to sound harsh: But with such a question i recommend to NOT write a banking application!!! – dognose Apr 06 '14 at 19:55
  • 1
    I'm not a professional programmer. I am still in my first year studies. This was just part of an assignment that we had to do. I am humble enough to say that I have much to learn, and I just try to pick up on things as I go. This was the only issue I had with the assignment. – user3504400 Apr 06 '14 at 19:58
  • well okay if you are "still learning" - wheres the point of "telling" the solution? Do some research, and you'll figure out! After finding out, you'll never forget. Having it told, you can't remember in 2 weeks... – dognose Apr 06 '14 at 22:04

4 Answers4

2

When you do new Random(), .Net uses the current time as seed. If you do this more than once in a short span of time, you'll generate the same string of random numbers. You might want to just make a static Random variable in BankAccount.

static Random random = new Random();

// later, in the constructor
pinNumber = random.Next(0, 10000); // 0 <= pinNumber < 10000

I changed the range on Next so that it will generate in the full range.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • Thanks, but how can I use an array to prevent such duplication? – user3504400 Apr 06 '14 at 20:18
  • @user3504400 (assuming this is a little like a real bank scenario) You don't need to. Two people can have the same PIN number. But if you're generating them randomly, you don't want to give them the same PIN number. – Tim S. Apr 06 '14 at 20:26
0

This method initializes an array with distinct random numbers. I didn't test it but it should work. Create an array, initialize it using the code below and then pass it to your method.

public void SetValues(int[] array)
    {
        Random randomNumber = new Random();

        for (int i = 0; i < array.Length; i++)
        {
            bool distinctNumber = true;
            int number = randomNumber.Next(1, 100);
            for (int j = 0; j < i; j++)
            {
                if (number == array[j])
                {
                    distinctNumber = false;
                    break;
                }
            }
            if ( distinctNumber )      
                array[i] = number;
            else
                --i;    
        }
    }
Adrian
  • 693
  • 5
  • 19
0

While I do not understand the concern about repeating digits in a PIN number, the solution should be pretty straight forward. Your array will only contain very few (four) digits, so there is no problem in checking if a number is repeated. The simplest way would be to use the Contains method and only append if the number is unique. Contains will however look at all numbers in the array, so you should either initialize it to something you do not allow (negative values), or build it using a list.

Random rnd = new Random();

var pin = new[] {-1, -1, -1, -1};

for(var i = 0; i < pin.length; i++)
   int nextDigit = rnd.Next(0, 10);
   while (pin.contains(nextDigit)){ nextDigit + rnd.Next(0, 10); }
   pin[i] = nextDigit;
}
faester
  • 14,886
  • 5
  • 45
  • 56
0

By borrowing an extension method from this excellent answer based on the Fisher-Yates shuffle this can be accomplished relatively cleanly.

First define an extension method to shuffle a given List<T>:

public static void Shuffle<T>(this IList<T> list)  
{  
    Random rng = new Random();  
    int n = list.Count;  
    while (n > 1) {  
        n--;  
        int k = rng.Next(n + 1);  
        T value = list[k];  
        list[k] = list[n];  
        list[n] = value;  
    }  
}

Then define the function to generate a PIN consisting of distinct digits:

public IEnumerable GeneratePIN() {

    var pinDigits = new List<int>(Enumerable.Range(0,10));
    pinDigits.Shuffle();
    return pinDigits.Take(4);

}

Or, as an even better option, you can also use a more generalized pin generation function to generate pins of arbitrary lengths from arbitrary types.

public static IEnumerable<T> GeneratePIN<T>(IEnumerable<T> valueRange, int length)
{
    var pinValues = new List<T>(valueRange);
    pinValues.Shuffle();
    return pinValues.Take(length);
}

That said, it's worth mentioning that restricting the PINs to distinct values reduces to number of possible PINs from 10000 to 5040, making it significantly less secure.

Community
  • 1
  • 1
Colin Cochrane
  • 2,565
  • 1
  • 19
  • 20