package main
import (
"fmt"
"os"
)
var queries int
func ask(r1, c1, r2, c2 int) int {
queries++
fmt.Printf("? %d %d %d %d\n", r1, c1, r2, c2)
var res int
fmt.Scan(&res)
if res == -1 {
os.Exit(0)
}
return res
}
func check_palindrome(grid [][]int, r1, c1, r2, c2 int) bool {
if grid[r1][c1] != grid[r2][c2] {
return false
}
D := (r2 - r1) + (c2 - c1)
if D < 0 {
return false
}
if D == 0 {
return true
}
type state struct{ ra, rb int }
current := make(map[state]bool)
current[state{r1, r2}] = true
steps := D / 2
for s := 0; s < steps; s++ {
next_set := make(map[state]bool)
for st := range current {
ra := st.ra
rb := st.rb
ca := c1 + s - (ra - r1)
cb := c2 - s + (r2 - rb)
for d_ra := 0; d_ra <= 1; d_ra++ {
na := ra + d_ra
nca := ca + 1 - d_ra
if na > r2 || nca > c2 {
continue
}
for d_rb := 0; d_rb <= 1; d_rb++ {
nb := rb - d_rb
ncb := cb - 1 + d_rb
if nb < r1 || ncb < c1 {
continue
}
if grid[na][nca] == grid[nb][ncb] {
next_set[state{na, nb}] = true
}
}
}
}
current = next_set
if len(current) == 0 {
return false
}
}
if D%2 == 0 {
for st := range current {
ra := st.ra
rb := st.rb
ca := c1 + steps - (ra - r1)
cb := c2 - steps + (r2 - rb)
if ra == rb && ca == cb {
return true
}
}
return false
} else {
for st := range current {
ra := st.ra
rb := st.rb
ca := c1 + steps - (ra - r1)
cb := c2 - steps + (r2 - rb)
if rb >= ra && cb >= ca && (rb-ra)+(cb-ca) == 1 {
return true
}
}
return false
}
}
func main() {
var N int
if _, err := fmt.Scan(&N); err != nil {
return
}
ans := make([][]int, N+1)
for i := 0; i <= N; i++ {
ans[i] = make([]int, N+1)
for j := 0; j <= N; j++ {
ans[i][j] = -1
}
}
ans[1][1] = 1
ans[N][N] = 0
type cell struct{ r, c int }
qEven := []cell{{1, 1}, {N, N}}
visitedEven := make(map[cell]bool)
visitedEven[cell{1, 1}] = true
visitedEven[cell{N, N}] = true
dirs := []cell{{2, 0}, {0, 2}, {1, 1}, {-2, 0}, {0, -2}, {-1, -1}}
for len(qEven) > 0 {
u := qEven[0]
qEven = qEven[1:]
for _, d := range dirs {
v := cell{u.r + d.r, u.c + d.c}
if v.r >= 1 && v.r <= N && v.c >= 1 && v.c <= N {
if !visitedEven[v] {
visitedEven[v] = true
r1, c1, r2, c2 := u.r, u.c, v.r, v.c
if r1 > r2 || (r1 == r2 && c1 > c2) {
r1, c1, r2, c2 = v.r, v.c, u.r, u.c
}
res := ask(r1, c1, r2, c2)
if res == 1 {
ans[v.r][v.c] = ans[u.r][u.c]
} else {
ans[v.r][v.c] = 1 - ans[u.r][u.c]
}
qEven = append(qEven, v)
}
}
}
}
ans[1][2] = 1
qOdd := []cell{{1, 2}}
visitedOdd := make(map[cell]bool)
visitedOdd[cell{1, 2}] = true
for len(qOdd) > 0 {
u := qOdd[0]
qOdd = qOdd[1:]
for _, d := range dirs {
v := cell{u.r + d.r, u.c + d.c}
if v.r >= 1 && v.r <= N && v.c >= 1 && v.c <= N {
if !visitedOdd[v] {
visitedOdd[v] = true
r1, c1, r2, c2 := u.r, u.c, v.r, v.c
if r1 > r2 || (r1 == r2 && c1 > c2) {
r1, c1, r2, c2 = v.r, v.c, u.r, u.c
}
res := ask(r1, c1, r2, c2)
if res == 1 {
ans[v.r][v.c] = ans[u.r][u.c]
} else {
ans[v.r][v.c] = 1 - ans[u.r][u.c]
}
qOdd = append(qOdd, v)
}
}
}
}
grid1 := make([][]int, N+1)
grid2 := make([][]int, N+1)
for i := 1; i <= N; i++ {
grid1[i] = make([]int, N+1)
grid2[i] = make([]int, N+1)
for j := 1; j <= N; j++ {
grid1[i][j] = ans[i][j]
if (i+j)%2 != 0 {
grid2[i][j] = 1 - ans[i][j]
} else {
grid2[i][j] = ans[i][j]
}
}
}
distinguished := false
var qr1, qc1, qr2, qc2 int
for d := 3; d <= 2*N-2; d++ {
for r1 := 1; r1 <= N; r1++ {
for c1 := 1; c1 <= N; c1++ {
for r2 := r1; r2 <= N; r2++ {
c2 := c1 + d - (r2 - r1)
if c2 >= c1 && c2 <= N {
res1 := check_palindrome(grid1, r1, c1, r2, c2)
res2 := check_palindrome(grid2, r1, c1, r2, c2)
if res1 != res2 {
qr1, qc1, qr2, qc2 = r1, c1, r2, c2
distinguished = true
break
}
}
}
if distinguished {
break
}
}
if distinguished {
break
}
}
if distinguished {
break
}
}
if distinguished {
res := ask(qr1, qc1, qr2, qc2)
expected := 0
if check_palindrome(grid1, qr1, qc1, qr2, qc2) {
expected = 1
}
if res != expected {
for i := 1; i <= N; i++ {
for j := 1; j <= N; j++ {
ans[i][j] = grid2[i][j]
}
}
}
}
fmt.Println("!")
for i := 1; i <= N; i++ {
for j := 1; j <= N; j++ {
fmt.Print(ans[i][j])
}
fmt.Println()
}
}