#include<iostream>
#include<map>
#include<cassert>
#define rep(i, n) for ( int i = 0; i < n; i++)
using namespace std;

#define MAX 10

#define HOUSE 3
#define SPACE 0
#define SMOKE 1
#define START 2
#define BLOCK 4
/*
#define HOUSE '3'
#define SPACE '0'
#define SMOKE '1'
#define START '2'
#define BLOCK 'X'
*/

int H, W;
class State{
public:
  unsigned short pi, pj, total;
  //unsigned short G[MAX+2][MAX+2];
  //char G[MAX+2][MAX+2];
  bool V[MAX+2][MAX+2];

  State(){total = 0;}
  //State(int H, int W):H(H), W(W){ total = 0;}

  bool operator < ( const State &s) const{
    if ( pi != s.pi ) return pi < s.pi;
    if ( pj != s.pj ) return pj < s.pj;
    for ( int i = 1; i <= H; i++ ){
      for ( int j = 1; j <= W; j++ ){
	//if ( G[i][j] == s.G[i][j] ) continue;
	//return G[i][j] < s.G[i][j];
	if ( V[i][j] == s.V[i][j] ) continue;
	return V[i][j] < s.V[i][j];
      }
    }
    return false;
  }

};

static int di[4] = {0, -1, 0, 1};
static int dj[4] = {1, 0, -1, 0};

int  G[MAX+2][MAX+2];


main(){
  int si, sj;

  while(1){
    cin >> W >> H;
    if ( W == 0 && H == 0 ) break;
    int total = 0;

    for ( int i = 0; i < H+2; i++ )
      for ( int j = 0; j < W+2; j++ ) G[i][j] = BLOCK;
    for ( int i = 1; i <= H; i++ ){
      for ( int j = 1; j <= W; j++ ){
	cin >> G[i][j];
	if ( G[i][j] == START ){ si = i; sj = j;}
	if ( G[i][j] == SMOKE ) total++;
      }
    }

    /*
    bool zero[MAX+2];
    int tmp[MAX+2][MAX+2];
    for ( int i = 1; i <= H; i++ ) zero[i] = true;
    for ( int i = 0; i < H+2; i++ )
      for ( int j = 0; j < W+2; j++ ) tmp[i][j] =  G[i][j];
    for ( int i = 0; i < H+2; i++ )
      for ( int j = 1; j <= W; j++ ) if ( G[i][j] ) zero[i] = false;
    int ii = 0;
    int c = 0;
    for ( int i = 0; i < H+2; i++ ){
      if ( zero[i] ) { c++; continue;}
      for ( int j = 0; j < W+2; j++ ) G[ii][j] = tmp[i][j];
      ii++;
    }
    H -= c;

    for ( int j = 1; j <= W; j++ ) zero[j] = true;
    for ( int i = 0; i < H+2; i++ )
      for ( int j = 0; j < W+2; j++ ) tmp[i][j] =  G[i][j];
    for ( int j = 1; j <= W; j++ ) 
      for ( int i = 0; i < H+2; i++ )
	if ( G[i][j] ) zero[j] = false;
    
    int jj = 0;
    c = 0;
    for ( int j = 0; j < W+2; j++ ){
      if ( zero[j] ) { c++; continue;}
      for ( int i = 0; i < H+2; i++ ) G[i][jj] = tmp[i][j];
      jj++;
    }
    W -= c;

    */


    State s = State();
    
    for ( int i = 0; i <= H+1; i++ )
      for ( int j = 0; j <= W+1; j++ ) s.V[i][j] = ((G[i][j]==SMOKE)?true:false);
    
    map<State, int> M;
    State v;

    int ni, nj;
    M[s] = 0;
    
    for ( int r = 0; r < 4; r++ ){
      ni = si + di[r];
      nj = sj + dj[r];

      while(1){
	//if ( s.G[ni][nj] == SMOKE ){
	if ( s.V[ni][nj] ){
	  v = s;
	  v.pi = ni;
	  v.pj = nj;
	  //v.G[ni][nj] = HOUSE;
	  v.V[ni][nj] = false;
	  v.total = 1;
	  M[v] = 1;
	  break;
	} else if ( G[ni][nj] == BLOCK ) break;
	ni += di[r];
	nj += dj[r];
      }
    }

    map<State, int>::iterator it;
    
    int presize = M.size();

    int cc = 0;
    int x = 0;
    bool f;
    map<State, int> nM;

    
    while(1){
      //      nM = map<State, int>();
      nM.clear();
      f = true;
      for ( it = M.begin(); it != M.end(); it++ ){
	State cur = (*it).first;
	int cost = (*it).second;
	if ( cost == 0 ) continue;

	for ( int r = 0; r < 4; r++ ){
	  ni = cur.pi + di[r];
	  nj = cur.pj + dj[r];

	  while(1){
	    //if ( cur.G[ni][nj] == SMOKE ){
	    if ( cur.V[ni][nj]){
	      v = cur;
	      v.pi = ni;
	      v.pj = nj;
	      //v.G[ni][nj] = HOUSE;
	      v.V[ni][nj] = false;
	      v.total++;
	      f = false;
	      nM[v] += cost;
	      break;
	      //	    } else if ( cur.G[ni][nj] == START && cur.total == total ){
	    } else if ( ni == si && nj == sj && cur.total == total ){
	      x += cost;
	      break;
	    } else if ( G[ni][nj] == BLOCK ) {
	      break;
	    }

	    ni += di[r];
	    nj += dj[r];
	  }
	}
      }
      if ( f ) break;
      M = nM;
    }

    cout << x << endl;
    
  }
}

Measured memory_bytes: 64000