#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 DEB 0

/*
real	0m2.117s
*/
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 hS[24],hx[24],hy[24],edge[24][4][24]; //[src][dir][dest]

#if DEB
int already_1,already_2;
#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 bool isnotgoal(int s){
  return (((last&s)) == last);
}
inline bool isnot(int s){
  rep(i,home)if( !(s&(1<<i)) ){
    if( (hS[i]&s)==hS[i] ) return true;
  }
  return false;
}
inline bool inside(int x, int y){
  return (x<0 || y<0 || x>=w || y>=h);
}


int dfs(int x, int y, int s, int src){
  if( (1<<home)-1 == s ){ //âÎÉßêé
    return 1;
  }
  if( isnotgoal(s) ){ //³ïÉßé½ßÌÆðÁïµ½©Ç¤©
    return 0;
  }
  state tmp(x,y,s);
  if( msi.count(tmp) ){ //ùÉÊÁ½óÔ
#if DEB
    if( msi[tmp]>0 ){
      already_1++;
    }else{
      already_2++;
    }
#endif
    return msi[tmp];
  }
  
  // v[gªu¯È¢ÆÌL³
  // numofbits(~s&mask)>1
  if( s>0 && ((s&(s-1))!=0) && isnot(s&~(1<<num[y][x])) ){
    return 0;
  }
  
  int ret = 0;
  rep(k,4){
    for(int j=0; edge[src][k][j]!=-1; j++){
      int dest = edge[src][k][j];
      int nx = hx[dest];
      int ny = hy[dest];
      if( field[ny][nx]==1 ){
	field[ny][nx] = 0;
	ret += dfs(nx, ny, s|(1<<dest), dest);
	field[ny][nx] = 1;
	break;
      }
    }
  }
  /*
  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;
	ret += dfs(tx,ty,s|(1<<num[ty][tx]));
	field[ty][tx] = 1;
	break;
      }
    }
  }
  */
  msi[tmp] = ret;
  return ret;
}

int main(){

  while(scanf("%d%d",&w,&h),w|h){
    msi.clear();
    memset(num,-1,sizeof(num));
    memset(edge,-1,sizeof(edge));
    memset(hS,0,sizeof(hS));
    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 ){
	  hx[home]=j; hy[home]=i;
	  num[i][j] = home;
	  home++;
	}
      }
    }

    // other homes
    rep(i,home){
      rep(k,4){
	int sz = 0;
	for(int j=1; j<20; j++){
	  int tx = hx[i] + dx[k]*j;
	  int ty = hy[i] + dy[k]*j;
	  if( inside(tx,ty) ) break;
	  if( field[ty][tx]==1 ){
	    hS[i] |= (1<<num[ty][tx]);
	    edge[i][k][sz++] = num[ty][tx];
	  }
	}
      }
    }

#if DEB
    rep(i,home){
      printf("i:(%d,%d)\n",hx[i],hy[i]);
    }
    rep(i,home){
      rep(k,4){
	for(int j=0; edge[i][k][j]!=-1;j++){
	  printf("i:%d(%d)  --> %d\n",i,k,edge[i][k][j]);
	}
      }
    }
#endif

    //last homes
    rep(k,4){
      int sz = 0;
      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]);
	  edge[home][k][sz++] = num[ty][tx];
	}
      }
    }
    printf("%d\n",dfs(sx,sy,0,home));

#if DEB
    int cnt = 0;
    map<state,int>::iterator it;
    for(it=msi.begin(); it!=msi.end(); it++){
      if( it->second == 0 ){
	cnt++;
      }
    }
    printf("msi_sz:%d  >0:%d  ==0:%d  already>0:%d , already==0:%d\n",msi.size(),msi.size()-cnt,cnt,already_1,already_2);
    already_1 = already_2 = 0;
#endif

  }
  

  return 0;
}

Measured memory_bytes: 27000