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

时间:2011-11-15 18:48:44

标签: c# arrays list

对不起,如果这是一个愚蠢的菜鸟问题。我正在为我的女朋友做一个非常小的项目 - 一个国家名单,她必须进入他们的首都(晦涩的国家,请注意)。由于我是一个初学者,我不得不求助于使用两个数组,一个用于国家,另一个用于大写,具有匹配的索引。这样很容易检查正确的答案,我不必解析任何文本文件或使用任何数据库。我使用随机数字来使它更有趣。为了阻止程序一遍又一遍地生成相同的国家,我使用了一个整数列表来跟踪已经使用了哪些索引,如果列表包含前一个索引,则重新生成该数字。很基本的东西。令人惊讶的是,这一切都有效。

但我遇到了问题。我如何检查我的国家已经用完了? :)我不能简单地检查我的国家/地区数组的列表大小,因为List可能包含比数组更多的值,并且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();
            }
        }
    }
}

9 个答案:

答案 0 :(得分:5)

  

要阻止程序一遍又一遍地生成相同的国家/地区,我正在使用一个整数列表来跟踪已经使用了哪些索引,如果列表包含前一个索引,则重新生成该数字。

...

  

我如何检查我的国家已经用完了?

您可能想要考虑另一种方法,因为这将非常昂贵且过于复杂。

不是试图随机添加一个国家/地区,而是检查您已添加的国家/地区,而只需制作整个国家/地区列表,然后perform a shuffle(“随机排序”)即可。这样,您将以随机顺序一次性获得所有国家/地区。

答案 1 :(得分:4)

我们不再使用两个数组,一个数组和一个列表,而是介绍一些实际上看起来很容易使用的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);

注意:您可以通过添加该特定国家/城市对是否被正确猜测来轻松扩展此匿名类型,并对其失败的那些进行后续测试。

答案 2 :(得分:1)

您可以使用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);
}

答案 3 :(得分:1)

创建Country类和Capital类。

然后对类进行建模以使用Dictionary<TKey, TValue>通用集合,以便将通用Dictionary对象声明为:

Dictionary<Country, Capital>

其中国家是关键,资本是其价值。

对于MSDN对Dictionary及其示例用法的引用,您可以按照以下链接进行操作:

http://msdn.microsoft.com/en-us/library/xfhwa508.aspx

当你继续使用国家和大写字母时,在检查它们是否存在于Dictionary实例中之后,将它们添加到Dictionary实例之上,如果它们中的任何一个存在,则弹出信息消息或警告。

答案 4 :(得分:1)

您可以使用键/值对,例如Dictionary<string, string>来存储您的国家/地区和首都。然后使用随机LINQ orderby子句迭代集合:

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);
}

答案 5 :(得分:1)

快速而肮脏,不一定高效或安全。

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);
}

答案 6 :(得分:1)

看起来你需要的是一种不同类型的数据结构,两组列表可以正常工作,但它没有任何复杂性。我建议查看词典列表类型。

Dictionary<string,string> countryList = new Dictionary<string,string>();
countryList.Add("Canada","Ottawa");
countryList.Add("Thailand","Bankok");

等...

然后,您可以遍历列表,同时布尔值可以查看是否存在匹配。有关Dictionary list type的更多信息。

答案 7 :(得分:0)

为什么不从列表中删除您使用的项目?那你没有冲突。然后你检查states.Count()&gt; 0

答案 8 :(得分:0)

我能想到的最快的事情就是在列表中使用Distinct()调用。然后,可以将列表中的项目计数与数组的计数进行比较,以查看是否已使用所有项目。

if(myUsedList.Distinct().Count() < myArray.Count) { ... }