Python 3, 667 bytes
N=next
E=enumerate
def F(C,x,y,f):
global t,a,v,n
try:c=C[y][x]
except:return
if(x,y)in v:return
t|=c==0
if not c&f:return
C[y][x]=0;v+=[(x,y)]
if c!=15:n[c]=n.get(c,0)+1;a+=.5
else:a+=1
if c&1and y>0:F(C,x,y-1,4)
if c&2:F(C,x+1,y,8)
if c&4:F(C,x,y+1,1)
if c&8and x>0:F(C,x-1,y,2)
return(v,n)
def s(C):
global t,a,v,n
t=a=0;v=[];n={}
for y,r in E(C):
for x,e in E(r):
if e:v,n=F(C,x,y,15);break
if v:break
if not v:return 1
m=map(min,zip(*v));M=map(max,zip(*v))
if not n and(N(M)-N(m)+1)*(N(M)-N(m)+1)==a:return s(C)
if t:return 0
try:n[6]==n[9]and n[3]==n[12]or exec("return 0")
except:return 0
if 2*n[6]*n[12]==a:return s(C)
return 0
Try it online! (all testcases)
This is probably pretty golfable. Definitely replace-exec on "return" will save a few bytes, but I don't want to do that until after a bit more golfing.
fireflame241
- 16.4k
- 2
- 31
- 74