fixturelist 生成器问题 java

fixturelist generator issue java

概览

所以我正在尝试创建一个灯具列表生成器。为简单起见,该计划未考虑主场和客场比赛。该程序使用 generateFixtures() 方法每轮生成灯具,然后重复指定的轮数,直到生成所有灯具。

程序如何运作

generateFixtures 方法在其参数中传递了一个数组列表,其中包含该分区中需要为该轮生成固定装置的所有团队。此外,传递的 arrayList 将始终包含 20 个团队。然后创建两个字符串,它们保存 arraylist 中随机组的值。 generateFixtures() 然后使用 alreadyUsed() 方法检查是否有任何一个团队已经被用于该回合。它还会检查两支球队是否已经确定了整个赛季(但我将在稍后更详细地解释这部分)。然后它会进一步检查以确保两个团队不相同(在那个 team1 == team2 中)。当所有检查完成后,它会将两支球队放入赛程表地图,称为 fixturesDone。并且还将这两支球队放入 'used' arraylist,这样这两支球队就不会在该回合中再次使用。它不断重复 while 循环,直到所有团队都固定(因为 arraylist 'used' 大小大于或等于 19)。然后在 main 方法中设置一个循环,以不断循环 generateFixtures() 方法,直到整个赛季的所有固定装置都完成。

问题

问题出现在 'fixturesDone' 地图或 alreadyFixtured() 方法中。老实说,不确定哪一个可能导致问题。当我直接从 if 语句内部的 generateFixtures 方法打印出固定装置时,会生成固定装置,但通常会有重复的固定装置,而当我从 'fixturesDone' 地图打印出固定装置时,没有重复的固定装置,但只有似乎有 20 个固定装置存在,而且它总是 20 个,这表明我可能在其中一个循环中搞砸了。我已经解决这个问题几个小时了,我真的很困惑,所以非常感谢任何帮助:)

代码

无论如何记住我在这里所说的是必要的代码,祝你好运。

public static void generateFixtures(ArrayList<String> al){

    ArrayList<String> used = new ArrayList<String>();

    while(used.size() <= 19){

    String team = al.get(showRandomInteger(0, 19, r));  
    String team2 = al.get(showRandomInteger(0, 19, r));
    if(alreadyUsed(used, team, team2) == false && alreadyFixtured(fixturesDone, team, team2) == false && !team.equals(team2)){
        fixturesDone.put(team, team2);
        used.add(team);
        used.add(team2);

        System.out.println(team + "vs. " + team2);

    }
    }

    System.out.println("\n New week \n");
}

public static boolean alreadyFixtured(Map <String, String> m, String team1, String team2){
    if(m.containsKey(team1) || m.containsKey(team2)){

            for(Map.Entry<String, String> entry : m.entrySet()){

                if((entry.getKey().equals(team1) && entry.getValue().equals(team2)) || (entry.getKey().equals(team2) && entry.getValue().equals(team1)) ){
                    return true;
                }else{
                    return false;
                }
            }



    }else{
        return false;
    }
    return false;
}

public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {

    for(int i = 0; i <= 19; i++){
        generateFixtures(ReadXML(1));
    }

    System.out.println("\n Map version: ");

    for(Map.Entry <String, String> entry : fixturesDone.entrySet()){
        System.out.println(entry.getKey() + " vs. " + entry.getValue());
    }

}

你的 alreadyFixtured 逻辑一团糟。它只会检查地图中的第一个条目,因为在只检查 foreach 循环中的第一个条目后,你 return true 或 false。真的,您可以将代码替换为:

if(m.containsKey(team1))
    return m[team1].equals(team2);
if(m.containsKey(team2))
    return m[team2].equals(team1);

return false;

但是您还需要比这个 fixturesDone 地图更好的数据结构。这引出了我的下一点。

您的 fixturesDone 地图(我假设是全球地图)几乎没有用。您最多只能与之前的 2 轮进行比较,因为每个键只能在地图中出现一次,并且每次调用 generateFixtures 时都会覆盖一半的键值对。您应该将假定的 Map<String, String> fixturesDone 更改为 Map<String, ArrayList<String>>,在这种情况下,您需要将 alreadyFixtured 逻辑更改为:

if(m.containsKey(team1))
    return m[team1].contains(team2);
if(m.containsKey(team2))
    return m[team2].contains(team1);

return false;

您还应该将团队选择更改为 do-while 循环:

String team, team2;
do{
    team = al.get(showRandomInteger(0, 19, r));
}while(used.contains(team));

do{
    team2 = al.get(showRandomInteger(0, 19, r));
}while(used.contains(team2) || team2.equals(team1));

那么后面的if语句就可以写成:

if(!alreadyFixtured(fixturesDone, team, team2))

但是,您仍然有一个潜在的问题,即在特定回合中只剩下已经互相比赛过的球队,在这种情况下,您的代码将无限循环。这并不像听起来那么微不足道。以一种循环方式生成所有固定装置然后随机化这些固定装置出现的顺序可能更容易。