Sfortunatamente non ho molto tempo, ma vi lascio almeno questo fondamentale suggerimento col quale giocare un po'.
#define ASIZE 9
int main(void)
{
int i, j;
for (i = 0; i < ASIZE; ++i)
{
for (j = 0; j < ASIZE; ++j)
{
printf("%2d ", i + j);
}
puts("");
}
return(0);
}
Eccone l'output:
0 1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9 10
3 4 5 6 7 8 9 10 11
4 5 6 7 8 9 10 11 12
5 6 7 8 9 10 11 12 13
6 7 8 9 10 11 12 13 14
7 8 9 10 11 12 13 14 15
8 9 10 11 12 13 14 15 16
Vedete qualcosa di interessante?

Per ogni antidiagonale, quale che sia la dimensione della matrice (anche rettangolare),
la somma degli indici è costante e identifica univocamente l'antidiagonale stessa (e perfino la sua lunghezza, con un minimo di riflessione). Fatto banale, ma forse non ovvio di primo acchito.
Da qui, tutto il resto è in discesa. Non occorre perdere tempo a gestire tutte le combinazioni di casi particolari per tenere gli indici "dentro" la struttura, o ricorrere al solito operatore modulo tuttofare. Si tratta semplicemente di popolare ciascuna antidiagonale, seguendo direzioni adeguatamente alternate, per poi ruotare o specchiare, secondo la specifica istanza del problema, l'intera matrice al termine del lavoro.
EDIT: Prima di fornire ulteriori spunti per una soluzione in C (in fondo non credo ne abbiate bisogno), voglio sottolineare ancora una volta perché
APL e J sono i miei linguaggi preferiti per questo genere di cose. Ricordo che pochi anni fa un thread del genere è stato lanciato nella
mailing list di J: ne sono scaturite diverse soluzioni di grande fascino, oltre all'occasione di conoscere uno dei tanti
episodi meno noti sull'eccezionale figura di Kenneth Iverson, creatore del linguaggio.
Una delle migliori soluzioni generali si configura come segue:
($ [: /:@; [: <@|.`</. [: |. i.) 7 8
Dove 7 e 8 sono dei parametri esemplificativi, e rappresentano le dimensioni della matrice generata. Non male, eh?
