Reputation: 1217
Edit - Check is Moved to The Else, Looping & Multiple Object Changes are Now Prime Issue
I need 5 Teams objects To Play Against each other (Each must play against the Other 4 teams)
The Check had to be in the ELSE statement, Now the Only Problem left is the Scores add and subtract from ALL the teams same time, and i only play once, i need them to loop so that they all played against everyone
I Started off like this. Yet i don't know how to go about doing this
//This is the list i check against and add players to when the team
//Played against them
List<string> played = new List<string>();
//Teamlist Holds Objects of type Team
//Contructor - (TeamName,Points,Wins,Losses,Draws,totalpoints)
//string, rest are int type
foreach (var item in Teamlist)
{
if (played.Contains(item.Teamname))
{
//Played against them already or is the same name as their own
}
else
{
//Add own Name on Check
played.Add(item.Teamname);
//Looping here against all Teams Entered to be played against
//How do i go about doing this?
//If Team 1 Wins Team 2 - This is just 2 Randoms between 1
//and 10
if (rand1 > rand2)
{
item.WinGame(); //Increments Team win Points
}
else if (rand1 == rand2)
{
item.DrawGame(); //Draw awards no points
}
else
{
item.LoseGame(); //Lose Points
}
}
}
foreach (var item in Teamlist)
{
//This ToString() looks like this
//return string.Format("Team Name : {0} \t {1} \t {2} \t {3} \t
//{4} \t {5}", teamname, points, win, loss, draw, totalpoints);
Console.WriteLine(item.ToString());
}
Upvotes: 2
Views: 288
Reputation: 14888
EDIT: This is wrong. It would give you both home and away games.
What about taking the Cartesian Product of the list of teams to give you the list of matches to be played. With Linq it's pretty easy:
static void Main(string[] args)
{
var teams = new[]
{
new { Name = "Team 1"},
new { Name = "Team 2"},
new { Name = "Team 3"},
new { Name = "Team 4"},
new { Name = "Team 5"}
};
var matches =
// here we loop over all the items in the teams collection.
// "teamA" is our loop variable.
from teamA in teams
// here we loop over all the items in the teams collection again.
// like a nested foreach (in)
// "teamB" is our loop variable.
from teamB in teams
// this is like an if(teamA.Name != teamB.Name) within our nested foreach loops
where teamA.Name != teamB.Name
// the select says how we want to create our collection of results.
// Here we're creating a new anonymous object containing the two rival teams.
select new { Team1 = teamA, Team2 = teamB };
foreach (var match in matches)
{
var result = PlayMatch(match.Team1, match.Team2);
Console.WriteLine("{0} played {1} The result was {2}",
match.Team1.Name,
match.Team2.Name,
result);
}
}
private static string PlayMatch(object team1, object team2)
{
// Left as an exercise for the OP.
return "...";
}
Upvotes: 2
Reputation: 1833
Edit: Method originally played each team twice. Your notion of a played list is actually required. See below.
Edit: Here's another method, which may prove faster.
void PlayRound(Team[] teams)
{
for (int i = 0; i < teams.Length; i++)
for (int j = i + 1; j < teams.Length; j++)
PlayMatch(teams[i], teams[j]);
}
/// <summary>
/// Plays a full round, one match per team.
/// </summary>
void PlayRound(List<Team> teams)
{
List<Team> played = new List<Team>(); // keep track of teams in the outer loop
foreach (Team teamA in teams)
{
foreach (Team teamB in teams)
{
if (teamA == teamB || played.Contains(teamB))
continue;
else
PlayMatch(teamA, teamB);
}
played.Add(teamA); // add outer loop team to ensure one match per pairing
}
}
/// <summary>
/// Plays a match.
/// </summary>
void PlayMatch(Team teamA, Team teamB)
{
int scoreA = rand.Next();
int scoreB = rand.Next();
if (scoreA > scoreB)
{
teamA.Win();
teamB.Lose();
}
else if (scoreA == scoreB)
{
teamA.Draw();
teamB.Draw();
}
else
{
teamB.Win();
teamA.Lose();
}
}
Upvotes: 1
Reputation: 54781
Assuming teamList is IList<Team>
:
for(int i = 0; i < teamList.Count() - 1; i++)
for(int j = i + 1; j < teamList.Count(); j++)
{
var team1 = teamList[i];
var team2 = teamList[j];
// will execute for each pair once
}
For 5 teams:
Upvotes: 1
Reputation: 22038
foreach (var item in Teamlist)
{
//Add own Name on Check
played.Add(item.Teamname);
if (played.Contains(item.Teamname))
{
//Played against them already or is the same name as their own
}
This is always true? You add the name and next you'll try to find it (you just added it....)
played.Add(item.Teamname);
Should be at the end of the foreach scope i guess
Upvotes: 0
Reputation: 14888
To fix your code, you need to move played.Add(item.Teamname);
inside your else branch, so you're only adding the team name to the played
collection if they haven't played them.
foreach (var item in Teamlist)
{
//Add own Name on Check
// played.Add(item.Teamname); // <---- Move from here
if (played.Contains(item.Teamname))
{
//Played against them already or is the same name as their own
}
else
{
//Add own Name on Check
played.Add(item.Teamname); // <---- To here
...
Upvotes: 1
Reputation: 5885
You are missing one loop in your logic.
Based on the code you provided, here is what happens :
You should add another loop between steps 1 and 2 to loop on all teams and execute the game logic.
Upvotes: 0
Reputation: 1730
here lies your problem:
played.Add(item.Teamname);
if (played.Contains(item.Teamname))
The first line adds the team name to the played list, the second line checks if the team name is in the list. This should always be true, so you never get into the else path...
Upvotes: 1
Reputation: 17631
Maybe because you made a little error:
First you add item.Teamname
//Add own Name on Check
played.Add(item.Teamname);
Then you check if the previously added item.Teammname
is within the list -- always true:
if (played.Contains(item.Teamname))
{
Upvotes: 2