检查数组的所有值是否已被使用
本文关键字:是否 数组 检查 | 更新日期: 2023-09-27 18:14:37
对不起,如果这是一个愚蠢的新手问题。我正在为我的女朋友做一个非常小的项目-一个国家的列表,她必须输入他们的首都(不知名的国家,注意)。由于我完全是初学者,所以我不得不使用两个数组,一个用于国家,另一个用于首都,并使用匹配的索引。这样就很容易检查正确答案,我不需要解析任何文本文件或使用任何数据库。我用随机数是为了让它更有趣。为了防止程序一遍又一遍地生成相同的国家,我使用了一个整数列表,它跟踪已经使用的索引,如果列表包含前一个索引,则重新生成数字。非常基本的东西。令人惊讶的是,这一切都有效。
但是我有一个问题。基本上,我怎么检查我已经没有国家了呢?:)我不能简单地检查列表大小对我的国家数组,因为列表可能包含比数组更多的值,如果(taken.Equals(nations . length)))似乎不工作。或者我在代码中找不到正确的位置来放这个支票。
对不起,如果这是简单的,但我似乎找不到一个合适的解决方案。编辑哇,多么神奇的社区啊。在从星巴克到我家的一小段路程中,我得到了几十个高质量的答案,涵盖了大量的设计技术。这太棒了!谢谢大家!显然,这个问题已经得到了回答,但如果有人有任何额外的评论,我会为你发布代码。
//现在只是一个测试,13个国家
string[] Countries = {"Belgium", "France", "The Netherlands", "Spain", "Monaco", "Belarus", "Germany",
"Portugal", "Ukraine", "Russia", "Sweden", "Denmark", "South Africa"};
string[] Capitals = {"Brussels", "Paris", "Amsterdam", "Madrid", "Monaco", "Minsk", "Berlin",
"Lisbon", "Kiev", "Moscow", "Stockholm", "Copenhagen", "Pretoria"};
Random number = new Random();
List<int> taken = new List<int>();
int index;
int score = 0;
private int Generate()
{
while (true) {
index = number.Next(0, Countries.Length);
if (taken.Contains(index)) continue;
// THIS IS WHAT I WAS INITIALLY TRYING TO DO
if (taken.Equals(Countries.Length)) {
MessageBox.Show("Game over!");
return -1;
}
return index;
}
}
private void Form1_Load(object sender, EventArgs e)
{
index = Generate();
taken.Add(index);
label1.Text = Countries[index];
label3.Text = "0 out of " + Countries.Length.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim() == Capitals[index].ToString()) {
label2.Text = "You win!";
index = Generate();
taken.Add(index);
label1.Text = Countries[index];
textBox1.Clear();
label3.Text = ++score + " out of " + Countries.Length.ToString();
}
else {
label2.Text = "Wrong!";
textBox1.Clear();
}
}
}
}
为了防止程序一遍又一遍地生成相同的国家,我使用了一个整数列表,它跟踪已经使用的索引,如果列表包含前一个,则重新生成数字。
…
我如何检查我是否已经用完了国家?
您可能需要考虑另一种方法,因为这将非常昂贵且过于复杂。
与其尝试随机添加一个国家,对照已经添加的国家进行检查,不如创建整个国家列表,然后对集合执行洗牌("随机排序")。通过这种方式,你将以随机顺序一次性获得所有国家。
不使用两个数组,或者一个数组和一个列表,让我们介绍一些c# 4.0的东西,它看起来很容易使用,似乎是为这种类型的赋值而设计的。
用你的眼睛看这段代码,特别看看这些"匿名类型"最后是如何使用的。它让生活变得轻松。
// initialize your array like so,
// now you can access your items as countries[1].name and countries[1].city
// and you will never have to worry about having too much cities or countries
// PLUS: they're always together!
var countries = new [] {
new { name = "The Netherlands", city = "Amsterdam"},
new { name = "Andorra", city = "Vaduz" },
new { name = "Madagascar", city = "Antananarivo"}
};
// randomize by shuffling (see http://stackoverflow.com/questions/375351/most-efficient-way-to-randomly-sort-shuffle-a-list-of-integers-in-c-sharp/375446#375446)
Random random = new Random();
for (int i = 0; i < countries.Length; i += 1)
{
int swapIndex = random.Next(i, countries.Length);
if (swapIndex != i)
{
var temp = countries[i];
countries[i] = countries[swapIndex];
countries[swapIndex] = temp;
}
}
// go through all your items in the array using foreach
// so you don't have to worry about having too much items
foreach(var item in countries)
{
// show your girlfriend the country, something like
string inputString = DisplayCountry(item.country);
if(inputString == item.city)
{
ShowMessage("we are happy, you guessed right!");
}
}
// at the end of the foreach-loop you've automatically run out of countries
DisplayScore(to-your-girlfriend);
注意:您可以通过添加特定国家/城市对是否猜对来轻松扩展此匿名类型,并对她失败的国家/城市对进行后续测试。
您可以使用HashSet<int>
来跟踪已使用的索引。这将不接受重复的值。Add
方法返回一个布尔值,指示该值是否已经在列表中:
if (hashSet.Add(index))
DisplayValue(index);
else
//regenerate
但我可能会使用你现有的策略,但反过来:创建一个列表,预先填充从0到Count - 1的值。从这个列表中选择索引,在使用它们时删除它们。这在逻辑上类似于Reed Copsey的排序建议,但可能需要对现有代码进行更少的更改。
var availableIndexes = new List<int>(Enumerable.Range(0, countryCount));
var random = new Random();
while (availableIndexes.Count > 0)
{
var index = availableIndexes[Random.Next(0, availableIndexes.Count)];
DisplayValue(index);
availableIndexes.Remove(index);
}
您可以使用键/值对,如Dictionary<string, string>
来存储您的国家和首都。然后使用随机LINQ顺序子句遍历集合:
Dictionary<string, string> Countries = new Dictionary<int, string>();
// populate your collection of countries
foreach(var country in Countries.OrderBy(c => Guid.NewGuid()))
{
Console.WriteLine("Key: {0} Value: {1}", country.Key, country.Value);
}
创建Country类和Capital类
然后建模您的类使用Dictionary<TKey, TValue>
泛型集合,以便您声明泛型字典对象为:
Dictionary<Country, Capital>
其中Country为关键,Capital为值。
关于字典的MSDN参考及其示例用法,您可以遵循以下链接:
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx当你继续使用国家和首都时,在字典实例中检查它们是否存在后,将它们添加到上面的字典实例中,如果它们中的任何一个确实存在,那么弹出一个信息消息或警告。
又快又脏,不一定高效或安全。
Dictionary<string, string> countriesAndCapitals = new Dictionary<string, string>()
{
{ "Afghanistan", "Kabul" },
{ "Albania", "Tirane" },
{ "Algeria","Algers" },
{ "Andorra", "Andorra la Vella" } //etc, etc
};
foreach (var countryCapital in countriesAndCapitals.OrderBy(f => Guid.NewGuid()))
{
Console.WriteLine(countryCapital.Key + " " + countryCapital.Value);
}
似乎你需要的是一种不同类型的数据结构,两组列表可以工作得很好,但它是复杂的。我建议查一下字典列表类型。
Dictionary<string,string> countryList = new Dictionary<string,string>();
countryList.Add("Canada","Ottawa");
countryList.Add("Thailand","Bankok");
等等……
然后可以在布尔值查看是否有命中时遍历列表。关于字典列表类型的更多信息。
你为什么不把你用过的项目从列表中删除呢?这样就不会有冲突了。然后检查state . count ()> 0
我能想到的最快的事情就是在你的列表上使用Distinct()调用。然后,可以将列表中的项目计数与数组的计数进行比较,以查看是否所有项目都已使用。
if(myUsedList.Distinct().Count() < myArray.Count) { ... }