C# 不使用特定字符的随机字符
我正在尝试创建一些类似于基本随机密码生成器的东西,包括大写、小写和数字,但出于某种原因C# 不使用特定字符的随机字符,c#,random,ascii,C#,Random,Ascii,我正在尝试创建一些类似于基本随机密码生成器的东西,包括大写、小写和数字,但出于某种原因 static void Main(string[] args) { bool validLength = false; int userDefinedLength = 0; Console.WriteLine("How many characters would you like your password to be?");
static void Main(string[] args)
{
bool validLength = false;
int userDefinedLength = 0;
Console.WriteLine("How many characters would you like your password to be?");
do
{
try
{
userDefinedLength = int.Parse(Console.ReadLine());
validLength = true;
if (userDefinedLength < 3)
{
Console.WriteLine("Please enter something larger than 3.");
validLength = false;
}
}
catch (Exception)
{
Console.WriteLine("Please input a valid integer length.");
}
} while (validLength == false);
char[] passwordArray = new char[userDefinedLength];
int asciiValue = 0;
char asciiChar = ' ';
bool validPassword = false;
Random ranAsciiGroup = new Random();
Random ascValue = new Random();
do
{
for (int i = 0; i < passwordArray.Length; i++)
{
int randomAsc = 0;
randomAsc = ranAsciiGroup.Next(1, 4);
//Console.WriteLine(randomAsc);
if (randomAsc == 1)
{
asciiValue = ascValue.Next(65, 91);
//Console.WriteLine(asciiValue);
}
else if (randomAsc == 2)
{
asciiValue = ascValue.Next(97, 123);
//Console.WriteLine(asciiValue);
}
else if (randomAsc == 3)
{
asciiValue = ascValue.Next(48, 58);
//Console.WriteLine(asciiValue);
}
asciiChar = (char)asciiValue;
passwordArray[i] = asciiChar;
//validPassword = true;
}
bool isDigit = false;
bool isUpper = false;
bool isLower = false;
for (int i = 0; i < passwordArray.Length; i++)
{
if (char.IsDigit(passwordArray[i]))
{
isDigit = true;
}
if (char.IsUpper(passwordArray[i]))
{
isUpper = true;
}
if (char.IsLower(passwordArray[i]))
{
isLower = true;
}
}
if (isDigit == true && isUpper == true && isLower == true)
{
validPassword = true;
}
} while (validPassword == false);
Console.WriteLine("Your password is...");
Console.ForegroundColor = ConsoleColor.DarkGreen;
foreach (char c in passwordArray)
{
Console.Write(c);
}
Console.ReadLine();
}
System.Random
类不是设计为强RNG,而是设计为快速RNG。如果你想要一个高质量的随机数发生器,你需要使用一个基于类的随机数发生器
它使用加密随机生成器作为现有随机类的内部
运行它会让我
MM77D5EDJ0OHOOE8KPPIY0TOC0HWQJPO37B4LFJ56LVCQVA4JE83J8BS8XEXX6ZCEr2OD8A70V2xFKIY0ROY3GN105RZT6PE8F2I
您可以看到它似乎没有您发现的偏见。为您的RNG播种 别忘了给你的random实例植入种子
var random = new System.Random(Environment.TickCount);
而且,一个实例就足够了
消除重复
如果希望确保表示所有字符,可以使用不同的随机选择技术。例如,您可以生成一个非常长的字符串,其中包含您想要的所有字符,对其进行随机排序,然后获取前n个字符。这种方法将完全消除重复字符,并保证最终使用每个字符。例如:
using System;
using System.Linq;
public class Program
{
static readonly Random _random = new System.Random(Environment.TickCount);
const string dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklpmnopqrstuvwxyz0123456789!@#$%^&*()_+-=";
static string GetPassword(int length)
{
return new String
(
dictionary
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}
public static void Main()
{
var s = GetPassword(30);
Console.WriteLine(s);
}
}
在本例中,我们将字符串视为可枚举的(是的,这是允许的),并使用LINQ方法对其随机排序,并取前n个字符。然后,我们将结果传递给包含答案的新System.String
的构造函数
样本输出:
运行#1:
运行#2:
运行#3:
我觉得很随意
受控重复
当然,上述解决方案只允许字典中每个字符最多有一个实例。但也许你希望他们能够出现不止一次,但不要太多。如果您希望控制有限的可能重复次数,您可以做一些小的更改:
static string GetPassword(int length, int maxRepeats)
{
return new String
(
Enumerable.Range(0, maxRepeats)
.SelectMany( i => dictionary )
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}
在本例中,我们克隆字典maxreats
次,并使用SelectMany
将它们连接起来。然后我们对这个巨大的字符串进行随机排序,并取前n个字符作为密码
您使用的是
随机
错误,请看,我没有仔细查看,但您的代码似乎使用了小于6的数字,请看以下几个100个字符的示例:2MT1l99JZT41VKEIHU47G42ZS1OVD6Q934A3MJASHG523C8SU1OIM0QJ9LEYL164W3IYH0G8W5R1I2JZGY6RDTJ526D3RQVJ9CZ
和WSN5L11BZ72LP4UMPO2RMQW3WPC47P02XCAJITOITIHK2AOXYM2W431VAC7NUU6Z62TYUO49JN8E9EZM69HYX5X23
这实际上并不有趣,这是因为Random的同步实例。是的,我刚刚删除了Random的第二个实例,并在整个程序中使用了第一个实例。这似乎现在起作用了。下面是一个小例子,它给出了这种效果的一些直方图:您不需要手动为其设定种子。使用默认构造函数执行与您列出的完全相同的操作
!#t(hfTz0rB5cvKy1d$oeVI2mnsCba
y7Y(MB1pWH$wO5XPD0b+%Rkn9a4F!_
tH92lnh*sL+WOaTYR160&xiZpC5@G3
static string GetPassword(int length, int maxRepeats)
{
return new String
(
Enumerable.Range(0, maxRepeats)
.SelectMany( i => dictionary )
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}