#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

typedef tree<
ll,
null_type,
less<ll>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
// ordered_set X;
// *X.find_by_order(i) = ith largest element (counting from zero)
// X.order_of_key(k) = number of items in X < k (strict lt)

ll MOD = 998244353;

ll pow(ll a, ll x, ll MOD) {
    if (x == 0) return 1;
    ll halfpow = pow(a, x/2, MOD);
    ll ans = (halfpow * halfpow) % MOD;
    if (x % 2 == 1) ans = (ans * a) % MOD;
    return ans;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int N;
    cin >> N;

    vs A(N);
    for (int i=0;i<N;i++) cin >> A[i];

    int M = (N+1)*(N+1);
    vi num_on(M, 0);
    vi num_off(M, 0);
    vi num_unset(M, 0);

    for (int i=0;i<N-1;i++) {
        for (int j=0;j<N-1;j++) {
            int x = N - abs((1+i) + (1+j) - N);
            int y = abs(i - j);

            if (y > x) {
                int tmp = y;
                y = x;
                x = tmp;
            }

            
            int c = (N+1)*y + x;

            if (A[i][j] == 'o') {
                num_on[c]++;
            } else if (A[i][j] == 'x') {
                num_off[c]++;
            } else if (A[i][j] == '?') {
                num_unset[c]++;
            }
        }
    }

    int even_size = (N/2) + 1;
    int odd_size = (N+1)/2;

    vi ondegs(N+1, 0);
    vvi adj(N+1);


    for (int x=0;x<=N;x++) {
        for (int y=0; y<x; y++) {
            int c = (N+1)*y + x;
            if (num_on[c] > 0 && num_off[c] > 0) {
                cout << 0 << endl;
                return 0;
            }
            else if (num_on[c] > 0) {
                ondegs[x]^=1;
                ondegs[y]^=1;
            } else if (num_on[c] + num_off[c] == 0 && num_unset[c] > 0) {
                adj[x].push_back(y);
                adj[y].push_back(x);
            }
        }
    }

    /*
    for (int i=0;i<=N;i++) {
        cout << i << ": ";
        for (int nbr : adj[i]) cout << nbr << " ";
        cout << endl;
    }*/

    vb used(N, false);
    int num_edges = 0;

    // even

    ll even_ans = 1;
    num_edges = 0;
    for (int i=0;i<=N; i+=2) {
        num_edges += adj[i].size();
    }
    num_edges /= 2;
    if (even_size % 2 == 0) {
        even_ans = pow(2, num_edges, MOD);
    } else {
        int num_comps = 0;
        for(int i=0; i<=N;i+=2) {
            if (!used[i]) {
                queue<int> bfs;
                int num_odd = 0;
                bfs.push(i);
                used[i] = true;

                while (!bfs.empty()) {
                    int cur = bfs.front();
                    bfs.pop();

                    if (ondegs[cur] == 1) num_odd++;

                    for (int nbr : adj[cur]) {
                        if (!used[nbr]) {
                            used[nbr] = true;
                            bfs.push(nbr);
                        }
                    }
                }
                if (num_odd % 2 == 1) {
                    cout << 0 << endl;
                    return 0;
                }
                num_comps++;
            }
        }

        even_ans = pow(2, num_edges - even_size + num_comps, MOD);
    }
    
    ll odd_ans = 1;
    num_edges = 0;
    for (int i=1;i<=N; i+=2) {
        num_edges += adj[i].size();
    }
    num_edges /= 2;
    if (odd_size % 2 == 0) {
        odd_ans = pow(2, num_edges, MOD);
    } else {
        int num_comps = 0;
        for(int i=1; i<=N;i+=2) {
            if (!used[i]) {
                queue<int> bfs;
                int num_odd = 0;
                bfs.push(i);
                used[i] = true;

                while (!bfs.empty()) {
                    int cur = bfs.front();
                    bfs.pop();

                    if (ondegs[cur] == 1) num_odd++;

                    for (int nbr : adj[cur]) {
                        if (!used[nbr]) {
                            used[nbr] = true;
                            bfs.push(nbr);
                        }
                    }
                }
                if (num_odd % 2 == 1) {
                    cout << 0 << endl;
                    return 0;
                }
                num_comps++;
            }
        }

        odd_ans = pow(2, num_edges - odd_size + num_comps, MOD);
    }

    ll ans = (even_ans * odd_ans) % MOD;

    cout << ans << endl;

    return 0;
}

Measured memory_bytes: 35456