#include <iostream>
#include <fstream>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string>
#include <tuple>
#include <vector>
#include <map>
#include <unordered_map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <random>
#include <cassert>
using namespace std;
#define LL long long
#define MP(a, b) make_pair(a, b)
#define MMP(a, b, c) make_pair(make_pair(a, b), c)
#define MAX 1000000000
#undef INT_MIN
#undef INT_MAX
#define INT_MIN -2147483648
#define INT_MAX 2147483647
#define LL_MIN -9223372036854775808
#define LL_MAX 9223372036854775807
#define PI 3.14159265359

vector<pair<int,int> > house;
vector<pair<int,int>> way[23];
int ok[23];

int solve(int i, int j){
	if(i == (1<<house.size())-1) return ok[j];
	int ans = 0;
	if((i&(1<<j)) == 0) return 0;
	bool flg = true;
	for(int k=way[j].size()-1; k>=0; k--){
		if(way[j][k] == MP(-1,-1)){
			flg = true;
			continue;
		}
		if(flg == false) continue;
		if((i&way[j][k].second) == way[j][k].second && (i&(1<<way[j][k].first)) == 0){
			ans += solve(i+(1<<way[j][k].first), way[j][k].first);
			flg = false;
		}
	}
	return ans;
}

int main() {
	iostream::sync_with_stdio(false);

	START:
	
	int m,n;
	cin >> m >> n;
	if(n == 0 && m == 0) return 0;
	int a[10][10];
	house.clear();
	pair<int,int> kyokai;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> a[i][j];
			if(a[i][j] == 0) a[i][j] = -1; //空地
			else if(a[i][j] == 2){
				a[i][j] = -2; //教会
				kyokai = MP(i,j);
			}
			else{
				a[i][j] = house.size();
				house.push_back(MP(i,j));
			}
		}
	}

	//経路計算
	for(int i=0; i<house.size(); i++){
		way[i].clear();
		int x = house[i].first;
		int y = house[i].second;
		int tmp = 0;
		for(int j=x+1; j<n; j++){
			if(a[j][y] >= 0){
				way[i].push_back(MP(a[j][y],tmp));
				tmp += 1<<a[j][y];
			}
			
		}
		way[i].push_back(MP(-1,-1));
		tmp = 0;
		for(int j=x-1; j>=0; j--){
			if(a[j][y] >= 0){
				way[i].push_back(MP(a[j][y],tmp));
				tmp += 1<<a[j][y];
			}
		}
		way[i].push_back(MP(-1,-1));
		tmp = 0;
		for(int j=y+1; j<m; j++){
			if(a[x][j] >= 0){
				way[i].push_back(MP(a[x][j],tmp));
				tmp += 1<<a[x][j];
			}
		}
		way[i].push_back(MP(-1,-1));
		tmp = 0;
		for(int j=y-1; j>=0; j--){
			if(a[x][j] >= 0){
				way[i].push_back(MP(a[x][j],tmp));
				tmp += 1<<a[x][j];
			}
		}
	}

	//教会隣接家dp初期化
	for(int i=0; i<house.size(); i++){
		ok[i] = 0;
	}
	for(int i=kyokai.first+1; i<n; i++){
		if(a[i][kyokai.second] >= 0){
			ok[a[i][kyokai.second]] = 1;
		}
	}
	for(int i=kyokai.first-1; i>=0; i--){
		if(a[i][kyokai.second] >= 0){
			ok[a[i][kyokai.second]] = 1;
		}
	}
	for(int i=kyokai.second+1; i<m; i++){
		if(a[kyokai.first][i] >= 0){
			ok[a[kyokai.first][i]] = 1;
		}
	}
	for(int i=kyokai.second-1; i>=0; i--){
		if(a[kyokai.first][i] >= 0){
			ok[a[kyokai.first][i]] = 1;
		}
	}

	//最終的な答え
	int ans = 0;
	for(int i=kyokai.first+1; i<n; i++){
		if(a[i][kyokai.second] >= 0){
			ans += solve(1<<a[i][kyokai.second],a[i][kyokai.second]);
			break;
		}
	}
	for(int i=kyokai.first-1; i>=0; i--){
		if(a[i][kyokai.second] >= 0){
			ans += solve(1<<a[i][kyokai.second],a[i][kyokai.second]);
			break;
		}
	}
	for(int i=kyokai.second+1; i<m; i++){
		if(a[kyokai.first][i] >= 0){
			ans += solve(1<<a[kyokai.first][i],a[kyokai.first][i]);
			break;
		}
	}
	for(int i=kyokai.second-1; i>=0; i--){
		if(a[kyokai.first][i] >= 0){
			ans += solve(1<<a[kyokai.first][i],a[kyokai.first][i]);
			break;
		}
	}
	cout << ans << endl;
	
	goto START;

	return 0;
}


Measured memory_bytes: 3112