#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int b[N][N];
int n;
int dx[] = {0, 1, 2, 0};
int dy[] = {2, 1, 0, -2};
int was[N][N][N][N];
int ask(int x1, int y1, int x2, int y2) {
  if (x1 > x2 || y1 > y2) swap(x1, x2), swap(y1, y2);
  if (was[x1][y1][x2][y2] != -1) {
    return was[x1][y1][x2][y2];
  }
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int f;
  cin >> f;
  return was[x1][y1][x2][y2] = f;
}
int insight(int x, int y) { return (1 <= x && x <= n && 1 <= y && y <= n); }
void get_half() {
  b[1][1] = 1;
  b[n][n] = 0;
  queue<pair<int, int>> q;
  q.push({1, 1});
  while (q.size()) {
    auto c = q.front();
    q.pop();
    for (int k = 0; k < 3; ++k) {
      int nx = c.first + dx[k];
      int ny = c.second + dy[k];
      if (!insight(nx, ny)) continue;
      if (b[nx][ny] == -1) {
        b[nx][ny] = b[c.first][c.second];
        if (!ask(c.first, c.second, nx, ny)) {
          b[nx][ny] ^= 1;
        }
        q.push({nx, ny});
      }
    }
  }
}
void hard() {
  b[1][2] = 0;
  queue<pair<int, int>> q;
  q.push({1, 2});
  while (q.size()) {
    auto c = q.front();
    q.pop();
    for (int k = 0; k < 4; ++k) {
      int nx = c.first + dx[k];
      int ny = c.second + dy[k];
      if (!insight(nx, ny)) continue;
      if (b[nx][ny] == -1) {
        b[nx][ny] = b[c.first][c.second];
        if (!ask(c.first, c.second, nx, ny)) {
          b[nx][ny] ^= 1;
        }
        q.push({nx, ny});
      }
    }
  }
}
void print() {
  cout << "!" << endl;
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      cout << b[i][j];
    }
    cout << endl;
  }
}
void rev() {
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      if (i % 2 != j % 2) {
        b[i][j] ^= 1;
      }
    }
  }
}
vector<vector<pair<int, int>>> ways;
vector<pair<int, int>> path;
void dfs(int i, int j) {
  if (!insight(i, j)) return;
  path.push_back({i, j});
  if ((int)(path.size()) == 4) {
    ways.push_back(path);
    path.pop_back();
    return;
  }
  dfs(i + 1, j);
  dfs(i, j + 1);
  path.pop_back();
}
pair<pair<int, int>, int> get() {
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      if (i == j && i == 1) continue;
      ways.clear();
      dfs(i, j);
      for (auto k : ways) {
        int f = b[i][j] == b[k[2].first][k[2].second];
        int c = b[k[1].first][k[1].second] == b[k[3].first][k[3].second];
        if (c == f) {
          int r = ask(i, j, k[3].first, k[3].second);
          if (r) {
            if (i % 2 == j % 2) {
              return {k[3], b[i][j]};
            } else {
              return {k[0], b[k[3].first][k[3].second]};
            }
          } else {
            if (i % 2 == j % 2) {
              return {k[3], (b[i][j] ^ 1)};
            } else {
              return {k[0], b[k[3].first][k[3].second] ^ 1};
            }
          }
        }
      }
    }
  }
  assert(false);
}
void solve() {
  fill(&was[0][0][0][0], &was[0][0][0][0] + N * N * N * N, -1);
  fill(&b[0][0], &b[0][0] + N * N, -1);
  cin >> n;
  get_half();
  hard();
  auto fi = get();
  int x = fi.first.first;
  int y = fi.first.second;
  int d = fi.second;
  if (b[x][y] != d) {
    rev();
  }
  print();
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  solve();
  return 0;
}
