← Home
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()
	}
}