1 - 16 is a simple matter:
$aAvailable = range(1, 16); // this can be an array from a db
$aPairs = array();
$iAvailable = count($aAvailable);
for ($i = 0; $i < $iAvailable; ++$i)
for ($j = $i; $j < $iAvailable; ++$j)
if ($i != $j)
$aPairs = array($aAvailable[$i], $aAvailable[$j]);
Which will return a list of. . . 120 pairs of x,y. That should be all combinations covered from 1 - 16 (in this example, you can query a dataset BUT it will need to be a numerical array to work with the loops [since I was too lazy to use a while :P]), without repeating the combinations. So 1, 3 will exist, but 3, 1 will not. If order doesn't matter, and you can have both 1, 3, and 3, 1, simply change the
for ($j = $i
to $j = 0. That would result in, uhh, 240 matches.
oic, doing it in "rounds" is also far more complex. Since you effectively shuffle the numbers around. Should be a relatively easy change overall to gather though, I'll get back.