C #, 203 202 196 193 178 bayt
n=>{var r=new int[n,n];for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,b=1-2*(i%2),j;n>i++;){r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++;}return r;}
@StefanDelport sayesinde bir bayt kaydedildi.
@FelipeNardiBatista sayesinde 22 bayt kaydedildi.
Bu, karelerin nasıl oluşturulduğuna dair aşağıdaki gözlemlerle çalışır:

Gördüğünüz gibi her bit önceki kareye eklenir. Rakamlar için, bulunduğumuz yerin tamına gidiyoruz, aşağıya, karenin olduğu yerden bir alttaydı ve daha sonra sona erdi. Tek sayılar esasında tam tersidir, bir sola gideriz, o zamana kadar mevcut yüksekliğin bir üzerine çıktıktan sonra sağdan sona doğru.
Tam / Biçimli sürüm:
using System;
using System.Linq;
class P
{
static void Main()
{
Func<int, int[,]> f = n =>
{
var r = new int[n, n];
for (int o = n - 2 + n % 2 >> 1, i = r[o, o] = 1, c = 2, w = o, h = o, b = 1 - 2 * (i % 2), j; n > i++;)
{
r[h, w += b] = c++;
for (j = 0; j < i - 1; ++j)
r[h += b, w] = c++;
for (j = 0; j < i - 1; ++j)
r[h, w -= b] = c++;
}
return r;
};
Console.WriteLine(String.Join("\n", f(3).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
Console.WriteLine(String.Join("\n", f(4).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
Console.WriteLine(String.Join("\n", f(5).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
Console.ReadLine();
}
}
public static class ArrayExtensions
{
public static T[][] ToJagged<T>(this T[,] value)
{
T[][] result = new T[value.GetLength(0)][];
for (int i = 0; i < value.GetLength(0); ++i)
result[i] = new T[value.GetLength(1)];
for (int i = 0; i < value.GetLength(0); ++i)
for (int j = 0; j < value.GetLength(1); ++j)
result[i][j] = value[i, j];
return result;
}
}
4? Veya herhangi bir çift sayı.