#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50;
struct Edge {
  int v, eq;
};
vector<Edge> G[MAXN * MAXN + 5];
int adj[MAXN * MAXN + 5][MAXN * MAXN + 5];
int mat[MAXN + 5][MAXN + 5];
bool vis[MAXN * MAXN + 5];
int n;
bool isPal(int i, int j, int i2, int j2) {
  printf("\? %d %d %d %d\n", i, j, i2, j2);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}
void printMat() {
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      if (~mat[i][j])
        printf("%2d ", mat[i][j]);
      else
        printf(" ? ");
    }
    printf("\n");
  }
}
void dfs(int u, bool val) {
  if (vis[u]) return;
  vis[u] = 1;
  int i = (((u) / n) + 1), j = (((u) % n) + 1);
  mat[i][j] = val;
  for (Edge e : G[u]) {
    dfs(e.v, val ^ (!e.eq));
  }
}
bool shouldSwap() {
  if (n == 3) {
    bool pal = isPal(1, 1, 2, 3);
    if (pal) return mat[1][1] != mat[2][3];
    if (mat[1][3] != mat[2][2]) return true;
    if (mat[1][2] != mat[2][1]) return true;
    if (mat[1][2] != mat[2][3]) return true;
    pal = isPal(1, 1, 3, 2);
    if (pal) return mat[1][1] != mat[3][2];
    if (mat[3][1] != mat[2][2]) return true;
    if (mat[2][1] != mat[3][2]) return true;
    pal = isPal(1, 2, 3, 3);
    if (pal) return mat[1][2];
    return mat[1][2] == mat[1][3];
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j + 3 <= n; j++) {
      if (mat[i][j] == mat[i][j + 3] && mat[i][j + 1] == mat[i][j + 2] ||
          mat[i][j] != mat[i][j + 3] && mat[i][j + 1] != mat[i][j + 2]) {
        bool eq = isPal(i, j, i, j + 3);
        return !eq ^ (mat[i][j] != mat[i][j + 3]);
      }
    }
  }
  for (int i = 1; i + 3 <= n; i++) {
    for (int j = 1; j <= n; j++) {
      if (mat[i][j] == mat[i + 3][j] && mat[i + 1][j] == mat[i + 2][j] ||
          mat[i][j] != mat[i + 3][j] && mat[i + 1][j] != mat[i + 2][j]) {
        bool eq = isPal(i, j, i + 3, j);
        return !eq ^ (mat[i][j] != mat[i + 3][j]);
      }
    }
  }
  return false;
}
int main() {
  memset(mat, -1, sizeof(mat));
  scanf("%d", &n);
  mat[1][1] = 1;
  mat[n][n] = 0;
  for (int i = 1; i <= n; i += 2) {
    if (i + 2 <= n) {
      mat[i + 2][1] = mat[i][1] ^ !isPal(i, 1, i + 2, 1);
    }
    for (int j = 1; j + 2 <= n; j += 2) {
      bool eq;
      if (i != n || j + 2 != n) {
        eq = isPal(i, j, i, j + 2);
        mat[i][j + 2] = mat[i][j] ^ (!eq);
      }
      if (i + 1 <= n) {
        eq = isPal(i, j, i + 1, j + 1);
        mat[i + 1][j + 1] = mat[i][j] ^ (!eq);
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    int start = 1;
    if (i & 1) start = 2;
    for (int j = start; j + 2 <= n; j += 2) {
      bool eq = isPal(i, j, i, j + 2);
      G[(((i)-1) * (n) + (j - 1))].push_back(
          {(((i)-1) * (n) + (j + 2 - 1)), eq});
      G[(((i)-1) * (n) + (j + 2 - 1))].push_back(
          {(((i)-1) * (n) + (j - 1)), eq});
    }
    if (i < n) {
      if (i & 1) {
        bool eq = isPal(i, 2, i + 1, 3);
        G[(((i)-1) * (n) + (2 - 1))].push_back(
            {(((i + 1) - 1) * (n) + (3 - 1)), eq});
        G[(((i + 1) - 1) * (n) + (3 - 1))].push_back(
            {(((i)-1) * (n) + (2 - 1)), eq});
      } else {
        bool eq = isPal(i, 1, i + 1, 2);
        G[(((i)-1) * (n) + (1 - 1))].push_back(
            {(((i + 1) - 1) * (n) + (2 - 1)), eq});
        G[(((i + 1) - 1) * (n) + (2 - 1))].push_back(
            {(((i)-1) * (n) + (1 - 1)), eq});
      }
    }
  }
  memset(vis, 0, sizeof(vis));
  dfs((((1) - 1) * (n) + (2 - 1)), 0);
  bool swap = shouldSwap();
  if (swap) {
    memset(vis, 0, sizeof(vis));
    dfs((((1) - 1) * (n) + (2 - 1)), 1);
  }
  printf("!\n");
  int c, c2;
  for (c = 1; c <= n; c++) {
    for (c2 = 1; c2 <= n; c2++) {
      printf("%d", mat[c][c2]);
    }
    printf("\n");
  }
  fflush(stdout);
}
