There is actually a more general solution by which you can replace:
if ( $i % 3 == 2 ) {
echo "<td> </td><td> </td>\n";
} elseif ( $i % 3 == 0 ) {
echo "<td> </td>\n";
}
echo "</tr></table>";
with:
for ($i %= 3; $i < 3 && $i != 0; ++$i) {
echo "<td> </td>";
}
echo "\n</tr></table>";
Sorry about leading you on and trying to get you to do some of this.
It is usually better to give hints or give an algorithm outline than to spoonfeed with a code example solution right away, which unfortunately I am prone to do.
EDIT:
Sorry, I noticed that your count begins from 1 instead of 0, thus what I suggested does not work. If you count from 0, the only change needed should be changing:
if ( $i % 3 == 0 ) { echo "</tr><tr>"; }
$i++;
in the first loop to:
$i++;
if ( $i % 3 == 0 ) { echo "</tr><tr>"; }
Basically, you just increment before you test whether the end of the table row has been reached.
Incidentally, you can also use a switch with fall-through to handle the 'missing' columns. When counting from 1:
switch ($i % 3) {
case 2: echo "<td> </td>";
case 0: echo "<td> </td>";
}