【发布时间】:2021-11-02 14:13:15
【问题描述】:
我正在 C# 中尝试以下编码挑战:
管理机器人出厂设置。
当机器人离开工厂时,它没有名字。
第一次开启机器人时,会在 两个大写字母后跟三个数字的格式,例如 RX837 或 BC811。
每隔一段时间,我们需要将机器人重置为出厂设置 设置,这意味着它的名称被擦除。下次问的时候 该机器人将使用一个新的随机名称进行响应。
名称必须是随机的:它们不应遵循可预测的 序列。使用随机名称意味着有冲突的风险。您的解决方案 必须确保每个现有机器人都有一个唯一的名称。
我创建了一个机器人类,它通过了我的 8 个单元测试中的 7 个。失败的一个是:
[Fact]
public void Robot_names_are_unique()
{
const int robotsCount = 10_000;
var robots = new List<Robot>(robotsCount); // Needed to keep a reference to the robots as IDs of recycled robots may be re-issued
var names = new HashSet<string>(robotsCount);
for (int i = 0; i < robotsCount; i++) {
var robot = new Robot();
robots.Add(robot);
Assert.True(names.Add(robot.Name));
Assert.Matches(@"^[A-Z]{2}\d{3}$", robot.Name);
}
}
我浏览了我的代码,我认为问题在于我正在生成随机值,但在创建多个名称时我不能确保这些值是唯一的。这是我的课:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Robot
{
Random random = new Random();
Dictionary<string, bool> usedNames = new Dictionary<string, bool>();
public Robot()
{
Name = RandomName();
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public void Reset()
{
Name = RandomName();
}
private string RandomName()
{
Random rand = new Random();
int nums = random.Next(000, 1000);
var val = nums.ToString("000");
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string letters = new string(Enumerable.Repeat(chars, 2)
.Select(s => s[random.Next(s.Length)]).ToArray());
string name = $"{letters}{val}";
if (usedNames.ContainsKey(name))
{
// Implement here or refactor with loop?
}
return name;
}
}
但是,在查看了我的代码之后,我觉得有更好的方法。我认为该方法将涉及从头到尾依次遍历名称中可能的数字和字母,以确保每个名称都是唯一的。我在正确的轨道上吗?我能做的更好吗?
【问题讨论】:
-
随机文字后面可以加ID吗?
-
usedNames是一个实例字段,因此每个Robot都会跟踪其使用过的名称,仅此而已。 -
1) 您应该只使用
Random的一个(静态)实例(参见this)。 2)您目前没有采取任何措施来防止生成重复名称,因为 a)usedNames未在其他实例之间共享,并且 b)即使是,您的if语句当前为空(或者您没有包含该部分? )。 -
我会创建一个静态的
NameGenerator类来跟踪使用过的名称并生成新的唯一名称,并在您的Robot类中调用它的CreateName()方法。 -
@41686d6564,我还没有实现。我想看看重写整个方法以根据可能值的总范围迭代每个可能值是否更有意义......如果这有意义的话。+