这就是我的问题:我正在开发一个玩家分组(它将玩家分成组)。我是通过一个for循环来做的,但是它没有划分所有的玩家:(.
代码如下:
namespace Grouper
{
public partial class Form1 : Form
{
List<string> players=new List<string>();
public Form1()
{
InitializeComponent();
LoadPlayers();
}
private void But_rnd_Click(object sender, EventArgs e)
{
LoadPlayers();
bool isOdd = players.Count % 2 == 1;
List<string> results=new List<string>();
if(!isOdd) // Count of players is even
{
Grouping(ref results);
}
if(isOdd) // Count of players is odd
{
Grouping(ref results);
results.Add("Remained: " + players[0]);
ShowResults(ref results);
}
}
private void Grouping(ref List<string> results)
{
Random r=new Random();
for (int i = 0; i < players.Count() / 2 + 1; i++)
{
int randomPlr = r.Next(players.Count() / 2 + 1, players.Count());
results.Add(i + 1 + ".: " + players[i] + " + " + players[randomPlr]);
players.RemoveAt(i);
players.RemoveAt(randomPlr - 1);
}
}
private void ShowResults(ref List<string> results)
{
string write = "";
foreach (string result in results)
{
write += result + "\n";
}
MessageBox.Show(write);
}
private void LoadPlayers()
{
players.Clear();
players.Add("p1");
players.Add("p2");
players.Add("p3");
players.Add("p4");
players.Add("p5");
players.Add("p6");
players.Add("p7");
}
}
}方法ShowResults()只显示了2个组和1个玩家,剩下的是谁(2个组和1个剩余=5个玩家,但我有7个玩家!)。
发布于 2013-05-10 23:28:53
您的代码中有几个问题。
if语句使用
这真的很奇怪
bool isOdd = players.Count % 2 == 1;
…
if(!isOdd)
{
…
}
if(isOdd) // Count of players is odd
{
…
}使用if / else,您的代码将更具可读性:
if (players.Count % 2 == 0)
{
…
}
else
{
…
}此外,您可以完全省略此检查,进行分组,然后弄清楚如何处理其余部分(谁说每次最多只能保留一个?如果您将来需要将它们划分为三个组,该怎么办?):
Grouping(…);
if (players.Count > 0)
{
… process remaining players …
}for循环中的迭代次数
正如其他人所指出的,你在这里“重复”了:
for (int i = 0; i < players.Count() / 2 + 1; i++)这将总是比你想要的多进行两次迭代。您应该将其更改为:
for (int i = 1; i < players.Count() / 2; i++)这样,它将适用于偶数或奇数计数,也适用于角球情况(仅限0或1玩家)。或者,假设您每次迭代都将两个玩家从列表中删除,只需使用:
while (Players.count() > 1)索引访问和随机访问的组合是错误的
在下面的代码中,你不能确定a) i-th元素存在,b)随机索引不匹配i,这将有效地将相同的玩家放入两组中:
int randomPlr = r.Next(players.Count() / 2 + 1, players.Count());
results.Add(i + 1 + ".: " + players[i] + " + " + players[randomPlr]);
players.RemoveAt(i);
players.RemoveAt(randomPlr - 1);要么取一半,然后取另一半,因为它们在players列表中(在这种情况下,您根本不需要做任何fors ),或者每次随机选择一个球员。例如,如下所示:
public string PickRandomPlayer(List<string> players)
{
int random = … generate random index …;
string player = players[random];
players.RemoveAt(random);
return player;
}然后在for look中调用此方法两次,为每个半场挑选一个球员。
ref参数使用无效
以下声明包含不必要和不需要的ref
private void Grouping(ref List<string> results)简单地说: Object,就像List<string>一样,默认情况下是通过引用传递的。这意味着,当您在代码中访问results参数并对其进行修改(添加/删除项)时,受影响的实例是调用者提供的实例:
void Grouping(List<string> results) { … }
…
List<string> results = new … ;
…
Grouping(results);
…
… here results contains what Grouping put in另一方面,当您指定ref时,可以将List<string>的新实例传递到该方法的外部
void Grouping(List<string> results)
{
results = new … ; // this instance will be returned out of the method!
}
…
List<string> results = new … ;
…
Grouping(ref results); // here, whatever is in results currently, is lost
…goto的使用
这就是可怕的。查看此SO question及其接受的答案。此外,谷歌的“GOTO声明被认为是有害的”,以进一步阅读这一话题。
发布于 2013-05-10 23:21:13
对于循环,您的条件是i < players.Count() / 2 + 1。也就是说,由于您在循环的每次迭代中删除了2个玩家,因此您更改了条件的值。
假设你从7个玩家开始。
条件迭代1:i= 0,条件= 4,共2人处理,5人remaining
最后,您有2个组和3个剩余的玩家,但是由于您执行了"Remained: " + players[0],您只显示了剩余的玩家中的1个。
发布于 2013-05-10 23:25:15
这不是很好,但应该可以工作(只需输入,因此调整语法):
private void But_rnd_Click(object sender, EventArgs e)
{
LoadPlayers();
List<string> results=new List<string>();
Grouping(ref results);
ShowResults(ref results);
}
private void Grouping(ref List<string> results)
{
Random r=new Random();
while (Players.count() > 1)
{
int p1 = r.next(players.count());
String p1s = players.get(p1);
players.removeat(p1);
int p2 = r.next(players.count());
String p2s = players.get(p2);
players.removeat(p2);
results.add(//whatever string you use to combine p1 + p2);
}
if (players.count() > 0)
{
// add remaining players
}
}https://stackoverflow.com/questions/16485356
复制相似问题