Tablica char z odwiedzonymi (sprawdzonymi) kamieniami i rekurencyjnie szukasz. Oczywiście na tej tablicy zaznaczasz jako odwiedzone i odwiedzone już pomijasz. Jeśli którykolwiek zwróci, że ma wolnego sąsiada, zwraca true po stosie w górę. Możesz wszędzie zwracać 1 i przy sprawdzaniu sąsiadów dodawać oddechy dla danego kamienia.
//W - szerokość
//H - wysokość planszy
//plansza[][] - tablica liczb przechowujących wartość pola: 0-puste, dwie inne - gracze.
char O[W][H];
int sprawdz(int x, int y, int k){
if(O[x][y]>0 || x<0 || y<0 || x>=W || y>=H) return 0; //poza planszą lub odwiedzony
O[x][y]=1; //oznacz jako odwiedzony
if(plansza[x][y]==0) return 1; //puste pole, zwróć 1, jako że to jest oddech
if(plansza[x][y]!=k) return 0; //pole przeciwnika, puste pole wzięte pod uwagę wcześniej; zwraca brak oddechu
//Tu mamy już pewność, że to kamień tego samego gracza
//zwraca więc oddechy sąsiadów
return sprawdz(x+1,y,k)+sprawdz(x-1,y,k)+sprawdz(x,y+1,k)+sprawdz(x,y-1,k);
}
Tyle że przed każdym sprawdzaniem musisz czyścić tą tablicę. Nieoptymalne, ale można sobie pozwolić na takie marnotrawstwo czasu, skoro sprawdzać ma tylko po wykonanym ruchu