Jump to content
  • Advertisement
Sign in to follow this  
russkii

Writing a match scheduler for a sports game in c#

This topic is 4100 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, I'm a dumb beginner in programming, and just started learning c# a month ago. I've read a few books and followed some tutorials, and am trying to learn more by writing a simple sports management game. I'm stuck at trying to write a scheduler for clubs in a competition. I just need to create a schedule for each season for a given number of clubs, in a home/away format. Seemed easy at first, but the problems were so many that I've been working on this for weeks. I won't go into exact details of my attempt (unless anyone would like me to) - let's just say that my method is very cumbersome, and doesn't work for the second half of the season (where each club that played home before must now play away, and vice versa). Would anyone be so kind as to offer some advice on how to solve this - am I missing something simple? Any help would be greatly appreciated!

Share this post


Link to post
Share on other sites
Advertisement
Would be easier if you posted the attempt, or at least how you intend to store the data.

I can help on the code part but on sports managment you're way beyond me.. ;)

Share this post


Link to post
Share on other sites
Thanks for the interest, Marius. I will still try to avoid posting the code (it's horribly long, amateurish, and ugly) and will first try to write out an explanation of what I'm trying to do - if you're still interested in seeing the code after this, I'll post it. Sorry in advance for my limited programming vocab.

Here are the "actors" in the Scheduler() method, which is responsible for (1) scheduling matchdates, (2) scheduling the first half of the season, (3) filling in the home/away bools for each match in the first half of season, and (4) scheduling the second half of season, making sure that each club plays each other club once home and once away:

Clublist is a Collection typed to accept Club objects (soccer game).
Competition is an object containing another Clublist object ("cllstClubListOb"), which will hold all of the clubs participating in the competition.
Club objects, among other unimportant items, each contain their own Clublist object ("clblstClubsToPlay"), which will be filled with, you guessed it, Clubs, representing each club on the club's schedule.

The above is repeated in a loop, until the number of Clubs in each Club's clblstClubsToPlay is equal to the total number of clubs that should be contained in these lists, if all of the clubs' schedules are properly filled.

My problem is that, while the code below seemed to work consistently with a sample of 6 clubs, when I increased the number of clubs to 20, the method loops forever, since it can never give each of the 20 clubs 18 properly scheduled clubs. For 20 clubs, there must be a total of 760 Clubs in all of the Clublists (or 38 Clubs in each club's Clublist). The problem is that my method can only fill around 360 Clubs before it runs into problems, and has to restart.

The main problem is that each club cannot just pick at random - after the first round, or so, some clubs need to have certain other clubs available for their schedule, so I try to ensure that these are not taken by other Clubs, which have more options as to who they can play during that Round. However, I cannot write full-proof code to ensure this happens. Instead, I wrote something which (I hoped) would ensure that this happened most of the time, and then put it in a loop which would exit only when the proper number of Clubs was finally scheduled. I think the problem is that I'm too stupid to figure out how the scheduling mechanics work - I doubt that in real life, schedulers keep picking clubs at random until the schedule works out - what am I missing?

As I've said, if you're still interested in seeing the code (it's a lot), I can certainly post it. Thank you for your help!


ps: I tried posting a snippet of the code, to give you an idea, but it came out all misaligned - is there an easier way of posting it neatly than having to edit it all manually?



Share this post


Link to post
Share on other sites
Ok, here's a snippet - this code basically returns a bool after each club randomly picks another club off the list, telling the picking club whether it may add the randomly selected club to its schedule for that round, or if this would prevent other clubs from selecting one club each for that round. If the latter is the case, the picking club will keep randomly picking and testing other clubs off the list. The problem, again, is that this worked with 6 clubs (at times it takes a few run-throughs for all the clubs to schedule properly) - but hasn't worked even once with 20 clubs:



//for use in Clubs.Schedule() - to see if suggested club may be added to picking club's schedule for that round

public static bool CantPlay (Club pickingclub, Club suggestedclub, int round, ClubList clubsincompetition, ClubList mastercopylist)
{
bool cantplay = false;

ClubList copyofmastercopylist = new ClubList();

Random r = new Random();

//for fist half of season in home/away formats
if (round < clubsincompetition.Count - 1)
{

copyofmastercopylist.Clear();
foreach (Club a in mastercopylist)//populate copylist and remove the queried club for testing below
{
if ((a != suggestedclub) && (a != pickingclub))
{
copyofmastercopylist.Add(a);
}
}

//first find and schedule every club that can only accept one club this week
foreach (Club c in clubsincompetition)
{

if (
(c.clblstClubsToPlay.RetreiveObjectByName(suggestedclub.strClubName) == null) &&//so hasnt yet played this club
(c.clblstClubsToPlay.RetreiveObjectByIndex(round) == null) &&//so hasn't been scheduled yet
(c != suggestedclub) && // dont test the suggested club
(c != pickingclub) && //dont test the club doing the query
(copyofmastercopylist.RetreiveObjectByName(c.strClubName) != null)
)
{
ClubList listofavailable = new ClubList();

foreach (Club otherclub in copyofmastercopylist)//try other clubs available to this club
{
if ((c.clblstClubsToPlay.RetreiveObjectByName(otherclub.strClubName) == null) &&
!(clubsincompetition.RetreiveObjectByName(otherclub.strClubName) == c))
{
listofavailable.Add(otherclub);
}
}

if (listofavailable.Count == 1)
{
copyofmastercopylist.RemoveByObject(listofavailable.RetreiveObjectByIndex(0));
copyofmastercopylist.RemoveByObject(c);
}

}
}


foreach (Club c in clubsincompetition)//check each club not yet scheduled
{
if (
(c.clblstClubsToPlay.RetreiveObjectByName(suggestedclub.strClubName) == null) &&//so hasnt yet played this club
(c.clblstClubsToPlay.RetreiveObjectByIndex(round) == null) &&//so hasn't been scheduled yet
(c != suggestedclub) && // dont test the suggested club
(c != pickingclub)&& //dont test the club doing the query
(copyofmastercopylist.RetreiveObjectByName(c.strClubName) != null)
)
{
foreach (Club otherclub in copyofmastercopylist)//try other clubs available to this club
{
if ((c.clblstClubsToPlay.RetreiveObjectByName(otherclub.strClubName) == null) &&
!(clubsincompetition.RetreiveObjectByName(otherclub.strClubName) == c))
{
copyofmastercopylist.RemoveByObject(otherclub);
copyofmastercopylist.RemoveByObject(c);
break;
}
}
}

if (c.clblstClubsToPlay.CountClubInstances(suggestedclub) == 1)
{
copyofmastercopylist.RemoveByObject(c);
}

}


if (copyofmastercopylist.Count != 0)//if any club has no other club it can play, this bool is set to true
{
cantplay = true;
}
}


//For the second half of season, basically the same as above, but with minor necessary variations

else if (!(round < clubsincompetition.Count - 1))
{
copyofmastercopylist.Clear();
foreach (Club a in mastercopylist)//populate copylist and remove the queried club for testing below
{
if ((a != suggestedclub) && (a != pickingclub))
{
copyofmastercopylist.Add(a);
}
}

//first find and schedule every club that can only accept one club this week
foreach (Club c in clubsincompetition)
{
if (
(c.clblstClubsToPlay.CountClubInstances(suggestedclub) == 1) &&//so hasnt yet played this club
(c.clblstClubsToPlay.RetreiveObjectByIndex(round) == null) &&//so hasn't been scheduled yet
(c != suggestedclub) && // dont test the suggested club
(c != pickingclub) && //dont test the club doing the query
(copyofmastercopylist.RetreiveObjectByName(c.strClubName) != null)
)
{
ClubList listofavailable = new ClubList();

foreach (Club otherclub in copyofmastercopylist)//try other clubs available to this club
{
if ((c.clblstClubsToPlay.CountClubInstances(otherclub) == 1) && !(clubsincompetition.RetreiveObjectByName(otherclub.strClubName) == c))
{
listofavailable.Add(otherclub);
}
}

if (listofavailable.Count == 1)
{
copyofmastercopylist.RemoveByObject(listofavailable.RetreiveObjectByIndex(0));
copyofmastercopylist.RemoveByObject(c);
}

}
}

foreach (Club c in clubsincompetition)//check each club not yet scheduled
{
if (
(c.clblstClubsToPlay.CountClubInstances(suggestedclub) == 1) &&//so hasnt only played club once
(c.clblstClubsToPlay.RetreiveObjectByIndex(round) == null) &&//so hasn't been scheduled yet
(c != suggestedclub) && // dont test the suggested club
(c != pickingclub) && //dont test the club doing the query
(copyofmastercopylist.RetreiveObjectByName(c.strClubName) != null)
)
{
foreach (Club otherclub in copyofmastercopylist)//try other clubs available to this club
{
if ((c.clblstClubsToPlay.CountClubInstances(otherclub) == 1) && !(clubsincompetition.RetreiveObjectByName(otherclub.strClubName) == c))
{
copyofmastercopylist.RemoveByObject(otherclub);
copyofmastercopylist.RemoveByObject(c);
break;
}
}
}

if (c.clblstClubsToPlay.CountClubInstances(suggestedclub) == 2)
{
copyofmastercopylist.RemoveByObject(c);
}

}

if (copyofmastercopylist.Count != 0)//if any club has no other club it can play, this bool is set to true
{
cantplay = true;
}
}


return cantplay;//if "cantplay" is true, then the club in question must keep looking

}



= PHEW! Sorry for the ugliness - does that make any sense to you?

Share this post


Link to post
Share on other sites
Ok, sorry for my third post in a row - but the formatting on the posted message is not how it looked when I edited the code in the message window - I apologize for the messed up indentations.

Share this post


Link to post
Share on other sites
Tried creating a complete list of who plays who?
ex;
struct clublist{
club club1;
club club2;
};
std::vector<clublist> whoplays;

Fill inn all the clubs, determining home/away by the ordering (or a separate bool)
Then afterwards just looping trough it to fill the separate clubs based on the 'global' list.
Maybe a separate counter in the 'club' function counting the number of games they have, so you can check its within bounds before adding it to the list.

[Edited by - marius1930 on September 26, 2007 6:26:51 AM]

Share this post


Link to post
Share on other sites
Hmm, but wouldn't the same problem remain - that, with every round, there are more restrictions on which Club each Club may pick. This, it seems to me, is what prevents my scheduler from finishing properly - I cant write proper code to ensure that, in each round, the last Clubs on the list still have available to them at least one Club which they have not yet played (in the first half of season), or at least one Club which they have not yet played twice (second half of season).

I guess, as I see it, my problem is more of a matter of logistics - there must be some method that professionals (and sports game designers) use in scheduling clubs in a competition, instead of looping through the same Random picker until finally, on one pass, every club gets a full schedule (which is basically what I'm forced to do).

Thanks for trying to help!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!