#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define rep(i,n) REP(i,0,n)
#define mp make_pair
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define EPS 1e-8
#define DEB 0

const int dx[] = {1,0,-1,0}; //r,d,l,u
const int dy[] = {0,1,0,-1};

int w,h,sx,sy,home,last;
int field[16][16];
int num[16][16];
int kari[32];
vector<pair<int,int> > v;

#if DEB
stack<int> st;
#endif

class state{
public:
  char x,y;
  int s;
  state(char _x, char _y, int _s){
    x = _x;
    y = _y;
    s = _s;
  }
  
  bool operator<(const state& a)const{
    if( s==a.s ){
      if( x==a.x ) return y<a.y;
      else         return x<a.x;
    }else{
      return s<a.s;
    }
  }
  
};

map<state,int> msi;

inline int numofbits(int bits) {
  bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
  bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
  bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
  bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
  return (bits & 0x0000ffff) + (bits >>16 & 0x0000ffff);
}

inline bool isnotgoal(int s){
  return (((last&s)) == last);
}
inline int isnot(int s){
  rep(i,home)if( !(s&(1<<i)) ){
    if( (kari[i]&s)==kari[i] ) return i;
  }
  return -1;
}
inline bool inside(int x, int y){
  return (x<0 || y<0 || x>=w || y>=h);
}


int dfs(int x, int y, int s){
  if( (1<<home)-1 == s ){ //âÎÉßêé
    return 1;
  }
  if( isnotgoal(s) ){ //³ïÉßé½ßÌÆðÁïµ½©Ç¤©
    return 0;
  }
  if( msi.count(state(x,y,s)) ){ //ùÉÊÁ½óÔ
    return msi[state(x,y,s)];
  }
  
  int mask = (1<<home)-1;
  // v[gªu¯È¢ÆÌL³
  if( s>0 && numofbits(~s&mask)>1 && isnot(s&~(1<<num[y][x]))!=-1 ){
#if DEB
    printf("s:%d ,(%d,%d)  __%d  ___isnot:%d\n",s,x,y,s&~num[y][x],isnot(s&~num[y][x]));
    stack<int> tmp = st;
    while( !tmp.empty() ){
      printf("%d,",tmp.top());
      tmp.pop();
    }
    puts("\n");
#endif
    return 0;
  }
  
  int ret = 0;
  rep(k,4){
    for(int i=1; i<20; i++){
      int tx = x + dx[k]*i;
      int ty = y + dy[k]*i;
      if( inside(tx,ty) ) break;
      if( field[ty][tx]==1 ){
	field[ty][tx] = 0;
#if DEB
	st.push(num[ty][tx]);
#endif
	ret += dfs(tx,ty,s|(1<<num[ty][tx]));
	field[ty][tx] = 1;

#if DEB
	st.pop();
#endif

	break;
      }
    }
  }
  msi[state(x,y,s)] = ret;
  return ret;
}

int main(){

  while(scanf("%d%d",&w,&h),w|h){
    msi.clear();
    v.clear();
    memset(num,-1,sizeof(num));
    memset(kari,0,sizeof(kari));
    home = last = 0;
    rep(i,h){
      rep(j,w){
	scanf("%d",&field[i][j]);
	if( field[i][j]==2 ){
	  sx = j;
	  sy = i;
	}
	if( field[i][j]==1 ){
	  num[i][j] = home;
	  home++;
	  v.pb(mp(j,i));
	}
      }
    }

    // other homes
    rep(i,v.size()){
      rep(k,4){
	for(int j=1; j<20; j++){
	  int tx = v[i].first + dx[k]*j;
	  int ty = v[i].second + dy[k]*j;
	  if( inside(tx,ty) ) break;
	  if( field[ty][tx]==1 ){
	    kari[i] |= (1<<num[ty][tx]);
	  }
	}
      }
    }

    //last homes
    rep(k,4){
      for(int i=1; i<20; i++){
	int tx = sx + dx[k]*i;
	int ty = sy + dy[k]*i;
	if( inside(tx,ty) )break;
	if( field[ty][tx]==1 ){
	  last |= (1<<num[ty][tx]);
	}
      }
    }
#if DEB
    printf("sz:%d\n",v.size());
    printf("last:%d\n",last);
    rep(i,v.size()){
      printf("home:%d  , %d\n",i,kari[i]);
    }
#endif
    
    

    printf("%d\n",dfs(sx,sy,0));
  }
  

  return 0;
}