检查数组的所有值是否已被使用
抱歉,如果这是一个愚蠢的菜鸟问题。我正在为我的女朋友做一个非常小的项目 - 一个国家列表,她必须输入他们的首都(请注意,模糊的国家)。由于我完全是初学者,因此我不得不使用两个数组,一个用于国家/地区,另一个用于首都,并具有匹配的索引。这样就可以很容易地检查正确的答案,而且我不必解析任何文本文件或使用任何数据库。我使用随机数来使其更有趣。为了阻止程序一遍又一遍地生成相同的国家/地区,我使用一个整数列表来跟踪已使用的索引,并在列表包含前一个索引时重新生成数字。非常基本的东西。令人惊讶的是,这一切都有效。
但我有一个问题。基本上,我如何检查我是否已经用完了国家/地区? :) 我不能简单地根据国家数组检查列表大小,因为列表可能包含比数组更多的值,并且 if (taken.Equals(Countries.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();
}
}
}
}
Sorry if this is a stupid noob question. I'm doing a very small project for my girlfriend - a list of countries and she has to enter their capitals (obscure countries, mind you) . Since I'm a total beginner, I had to resort to using two arrays, one for countries and the other for capitals, with matching indexes. That way it's easy to check for the right answer and I don't have to parse any text files or use any data-bases. I'm using random numbers to make it more interesting. To stop the program from generating the same countries over and over again, I'm using a List of integers that keeps tracks of what indexes have already been used and regenerates the number if the list contains the previous one. Pretty basic stuff. Surprisingly, it all works.
But I'm having a problem. How do I check that I've run out of countries, basically? :) I can't simply check the List size against my countries array, since List probably includes more values than the array, and if (taken.Equals(Countries.Length)) doesn't seem to work. Or I can't find the right place in the code to put this check.
Sorry if this is simple, but I can't seem to find a proper solution.
EDIT
Wow, what an amazing community. During the short walk from Starbucks to my place I get dozens of quality answers which cover a huge array of design techniques. This is so great! Thank you everyone! Obviously, the question has been answered but I will post the code for you, if anyone has any additional comments.
// JUST A TEST FOR NOW, 13 COUNTRIES
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();
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
...
您可能需要考虑另一种方法,因为这将非常昂贵且过于复杂。
您不必尝试随机添加一个国家/地区,而是检查已添加的国家/地区,只需制作整个国家/地区列表,然后 对集合执行随机播放(“随机排序”)。这样,您就能以随机顺序一次获得所有国家/地区。
...
You might want to consider an alternative approach, as this is going to be quite expensive and overly complicated.
Instead of trying to add one country at random, checking against ones you've already added, you could just make the entire list of countries, then perform a shuffle ("random sort") on the collection. This way, you'll get all of the countries in one shot in a random order.
让我们介绍一些 C# 4.0 的东西,而不是使用两个数组,或者一个数组和一个列表,它实际上看起来并且易于使用,并且似乎是为这种类型的赋值而设计的。
眼睛跟着这段代码,具体看看这些“匿名类型”最终是如何使用的。它让生活变得非常轻松。
注意:您可以通过添加该特定国家/城市对是否被猜对来轻松扩展此匿名类型,并对她失败的国家/城市对进行后续测试。
Instead of using two arrays, or an array and a list, let's introduce something of C# 4.0 that actually looks and is easy to use and seems to be made for this type of assignments.
Follow this code with your eyes and specifically look how these "anonymous types" are used in the end. It makes life real easy.
Note: you can easily expand on this anonymous types by adding whether or not that particular country/city pair was guessed right and make a subsequent test with the ones she failed.
您可以使用
HashSet
来跟踪已使用的索引。这不会接受重复的值。Add
方法返回一个布尔值,指示该值是否已在列表中:但我可能会使用您现有的策略,但向后:创建一个预先填充 0 到 Count - 1 之间的值的列表从此列表中选择索引,并在使用时将其删除。这在逻辑上类似于 Reed Copsey 的排序建议,但可能需要对现有代码进行较少的更改。
You could use a
HashSet<int>
to keep track of indexes that have been used. This won't accept duplicate values. TheAdd
method returns a boolean that indicates whether the value was already in the list:But I would probably use your existing stragegy, but backwards: create a list pre-filled with values from 0 to Count - 1. Pick indexes from this list, removing them as you use them. This is logically similar to Reed Copsey's suggestion of sorting, but probably requires less change to your existing code.
您可以使用键/值对(例如
Dictionary
)来存储您的国家/地区和首都。然后使用随机 LINQ orderby 子句遍历集合:You can use a key/value pair, like a
Dictionary<string, string>
to store your countries and capitals. Then iterate through the collection using a random LINQ orderby clause:创建一个 Country 类和一个 Capital 类。
然后对您的类进行建模以使用
Dictionary
通用集合,以便将通用 Dictionary 对象声明为:其中 Country 是键,Capital 是其值。
有关字典的 MSDN 参考及其示例用法,您可以点击以下链接:
http:// /msdn.microsoft.com/en-us/library/xfhwa508.aspx
当您继续使用国家和首都时,请在检查字典实例中是否存在(如果有)后将它们添加到上面的字典实例中存在,然后弹出一条信息消息或警告。
Create a Country class and a Capital class.
Then model your classes to use a
Dictionary<TKey, TValue>
Generic Collection so that you declare the generic Dictionary object as:where Country is the key and Capital is its value.
For MSDN reference to Dictionary and its sample usage, you can follow below link:
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
As you keep using Countries and Capitals, add them to above Dictionary instance after checking for their existence in the Dictionary instance, if any of them do exist then either popup an info message or a warning.
快速而肮脏,不一定高效或安全。
Quick and dirty, not necessarily efficient or secure.
看来您需要的是一种不同类型的数据结构,两组列表可以正常工作,但毫无意义。我建议查看字典列表类型。
等等...
然后您可以迭代列表,同时布尔值查看是否有命中。有关字典列表类型的详细信息。
It seems like what you need is a different type of data structure, two sets of lists would work fine but it is complicated for nothing. I suggest looking into the dictionary list type.
etc...
You could then iterate through the list while a boolean value sees whether or not there was a hit. More info on Dictionary list type.
为什么不从您使用过的列表中删除这些项目呢?那么你们就没有冲突了。然后你检查 states.Count() > 0。
Why don't you remove the items from the list that you used? Then you don't have conflicts. Then you check states.Count() > 0.
我能想到的最快的事情是使用列表上的 Distinct() 调用。然后,可以将列表中的项目计数与数组的计数进行比较,以查看是否所有项目都已使用。
The quickest thing I can think to do is to use the Distinct() call on your list. Then your count of items in the list can be compared to your array's count to see if all have been used.