Desmond Smith
Desmond Smith

Reputation: 1217

List<> Contains Issue

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

Answers (8)

Greg B
Greg B

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

Michael
Michael

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

weston
weston

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:

  • 0 plays 1,2,3,4
  • 1 plays 2,3,4
  • 2 plays 3,4
  • 3 plays 4

Upvotes: 1

Jeroen van Langen
Jeroen van Langen

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

Greg B
Greg B

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

Thibault Falise
Thibault Falise

Reputation: 5885

You are missing one loop in your logic.

Based on the code you provided, here is what happens :

  1. Add current Teamname to played list
  2. Check if current Teamname is in played list

You should add another loop between steps 1 and 2 to loop on all teams and execute the game logic.

Upvotes: 0

Roland B&#228;r
Roland B&#228;r

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

Matten
Matten

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

Related Questions