Problem:
魔方陣

n × n の正方形のマス目の中に数字の１から n × n が一つずつ入っていて、縦のどの列のマス目の和も、横のどの列のマス目の和も対角線のマス目の和も等しいものを魔方陣といいます。

一辺のマスの個数が奇数の魔方陣の作り方には以下の方法があります。

中央のマス目のちょうど一つ下のマス目に１を入れる。

次の数字を右斜め下のマス目に入れる。
ただし、数字を入れようとしたマス目が正方形からはみ出している場合、すでに数字が埋まっている場合は以下の方法に従って数字を入れるマス目を探す。

右にはみ出した場合には、同じ行の左はしに、左にはみ出した場合には、同じ行の右はしに、下にはみ出した場合には、同じ列の一番上に数字を入れる。

数字を入れようとしたマス目が埋まっているときには、その埋まっているマス目の左斜め下のマス目に入れる。

全てのマス目が埋まるまで２を繰り返す。

この方法に従って、一辺のマス目の個数 n を入力として、その大きさの魔方陣を出力するプログラムを作成して下さい。ただし、n は 3 以上 15 以下の奇数とします。マス目に入る各数字は右詰 4 桁で出力してください。

入力

複数の入力が与えられます。各入力で n （正の整数）が１行に与えられます。入力は 0 で終了します。入力の数は 10 を超えません。

出力

各入力に対して n × n の魔方陣を出力して下さい。

Sample Input

3
5
0

Output for the Sample Input

4 9 2
3 5 7
8 1 6
11 24 7 20 3
4 12 25 8 16
17 5 13 21 9
10 18 1 14 22
23 6 19 2 15

Solution in JAVA (judge verdict: Accepted)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Magic Square
 */
public class Main {

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line = "";

		while (!(line = br.readLine()).equals("0")) {

			int n = Integer.parseInt(line);
			MagicSquare square = new MagicSquare(n);
			System.out.print(square.toString());
		}
	}

}

class MagicSquare {
	private int n;
	private int[][] square;

	MagicSquare(int n) {
		this.n = n;
		square = new int[n][n];
		generate();
	}

	private void generate() {
		int max = n * n + 1;
		Index idx = null;
		for (int i = 1; i < max; i++) {
			if (i == 1) {
				idx = first();
			} else {
				idx = next(idx);
			}
			setValue(i, idx);
		}
	}

	private Index first() {
		int x = n / 2 + 1;
		int y = n / 2;
		return new Index(x, y);
	}

	private Index next(Index idx) {
		int nx = idx.x + 1;
		int ny = idx.y + 1;
		Index next = new Index(nx, ny);
		correct(next);
		return next;
	}

	private void correct(Index idx) {

		int x, y;
		x = idx.x;
		y = idx.y;

		if (0 <= x && x < n && 0 <= y && y < n) {
			if (square[x][y] == 0) {
				return;
			} else {
				++idx.x;
				--idx.y;
			}
		} else {
			if (x >= n) { // 下
				idx.x = 0;
			} else if (y >= n) {// 右
				idx.y = 0;
			} else if (y < 0) {// 左
				idx.y = n - 1;
			}
		}
		correct(idx);
	}

	private void setValue(int value, Index idx) {
		square[idx.x][idx.y] = value;
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				sb.append(String.format("%4d", square[i][j]));
				if (j == n - 1) {
					sb.append("\n");
				}
			}
		}
		return sb.toString();
	}
}

class Index {
	int x, y;

	Index(int x, int y) {
		this.x = x;
		this.y = y;
	}
}