检查数组的所有值是否已被使用

本文关键字:是否 数组 检查 | 更新日期: 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) { ... }