tags:

views:

151

answers:

2
+4  Q: 

Tournament bracket

Not sure of the best way to go about this? I want to create a tournament bracket of 2,4,8,16,32, etc teams.

The winner of the first two will play winner of the next 2 etc. All the way until there is a winner. Like this

Can anyone help me?

OK so more information.

Initially I want to come up with a way to create the tournament with the 2,4,8,16,etc. Then when I have all the users in place, if they are 16 players, there are 8 fixtures. At this point I will send the fixture to the database.

When all the players that won are through to the next round, i would want another sql query again for the 2 winners that meet.

Can you understand what i mean?

A: 

Use arrays and remove the losing teams from the main array. (But keep 'em on a separate array, for reference and reuse purposes).

Jorge
+3  A: 

I did something like this a few years ago. This was quite a while ago and I'm not sure I'd do it the same way (it doesn't really scale to double-elimintation or the like) How you output it might be a different question. I resorted to tables as it was in 2002-2003. There are certainly better techniques today.

The amount of rounds in the tournament is log2(players) + 1, as long as players is one of the numbers you specified above. Using this information you can calculate how many rounds there are. The last round contains the final winner.

I stored the player information something like this (tweek this for best practices)

Tournament
  Name
  Size

Players
  Tournament
  Name
  Position (0 to tournament.size - 1)

Rounds
  Tournament
  Round
  Position (max halves for each round)
  Winner (player position)

Note in all my queries below, I don't include the "Tournament = [tournament]" to identify the tournament. They all need it.

It's rather simple to query this with one query and to split it out as needed for the different rounds. You could do something like this to get the next opponent (assuming there is one). For round 1, you'd simply need to get the next/previous player based on if it was even or odd:

SELECT * FROM Players WHERE Position = PlayerPosition + 1
SELECT * FROM Players WHERE Position = PlayerPosition - 1

For the next round, if the user's last Round.Position was even, you'll need to make suer that the next position up has a winner: SELECT Player FROM Rounds WHERE Position = [playerRoundPosition] - 1

If not, the next player isn't decided, or there's a gap (don't allow gaps!)

If the users last Round.Position was odd, you'll need make sure there's a user below them AND that there's a winner below them, otherwise they should automatically be promoted to the next round (as there is no one to play)

SELECT COUNT(*) FROM Players WHERE Position > [Player.Position]
SELECT Player FROM Rounds WHERE Position = [playerRoundPosition] + 1

On a final note, I'm pretty sure you could use something like the following to reduce the queries you write by using something like:

SELECT Player FROM Rounds WHERE Position + Position % 2 = [playerRoundPosition]
SELECT Player FROM Rounds WHERE Position - Position % 2 = [playerRoundPosition]

Update:

Looking over my original post, I find that the Rounds table was a little ambigous. In reality, it should be named matches. A match is a competition between two players with a winner. The final table should look more like this (only the name changed): Matches Tournament Round Position (max halves for each round) Winner (player position)

Hopefully that makes it a bit more clear. When the two players go up against each other (in a match), you store that information in this Matches table. This particular implementation depends on the position of the Match to know which players participated.

I started numbering the rounds at 1 because that was more clear in my implementation. You may choose 0 (or even do something completely different like go backwords), if you choose.

In the first round, match 1 means players 1 and 2 participated. In match 2, the players 3-4 participated. Essentially the first round is simply players position and position + 1 participated. You could also store this information in the rounds table if you need more access to it. Every time I used this data in the program, I needed all the round and player information anyways.

After the first round, you look at the last round of matches. In round 2, match 1, the winners from matches 1 and 2 participate. Round 2, match 2, the winners from match 3 and 4 participate. It should look pretty familiar, except that it uses the match table after round 1. I'm sure there's a more efficent way to do this repetitive task, I just never got enough time to refactor that code (it was refactored, just not that much).

AlReece45
This is a fantastic answer. I was aware of log2scale, but you have shown me exactly what it takes.I am still trying to take in all the information you are providing.Would it be possible for you to explain the "rounds" table better?That is throwing me into confusion a little.Thanks
Luke
I could've named that table a little better. I updated the answer with that information. Hopefully that helps.
AlReece45
Thanks for the additional information you provided. I will attempt to write the code for this now!
Luke
@Luke It'd be nice if we could get this developed into some Open Source Library. Contact me (see my profile) if you're interested
AlReece45