Go: // AOJ 1160: How Many Islands? http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1160

package main

import (
	"bufio"
	"container/list"
	"fmt"
	"os"
	"strconv"
)

var SEA = 0
var LAND = 1

func nextInt(sc *bufio.Scanner) int {
	sc.Scan()
	v, _ := strconv.Atoi(sc.Text())
	return v
}

func discoverIslands(M, V [][]int, H, W int) int {
	// 島を探す
	queue := list.New()
	islands := 0
	for i := 1; i <= H; i++ {
		for j := 1; j <= W; j++ {
			// 訪問済みの土地ならスキップ
			if V[i][j] == 1 {
				continue
			}

			// 訪問中の土地が海なら訪問済みにしてスキップ
			if M[i][j] == SEA {
				V[i][j] = 1
				continue
			}

			// 未訪問の陸地が見つかったので
			// 島の数を1つ増やし、この陸地から辿れる陸地を訪問していく
			islands++
			queue.PushBack([]int{i, j})

			for queue.Len() > 0 {
				cur := queue.Remove(queue.Front()).([]int)
				h, w := cur[0], cur[1]
				if V[h][w] == 1 {
					continue
				}
				V[h][w] = 1

				// 全方向に未訪問の陸地がないか探索
				for v := -1; v <= 1; v++ {
					for l := -1; l <= 1; l++ {
						dh := h + v
						dw := w + l
						if M[dh][dw] == LAND && V[dh][dw] == 0 {
							queue.PushBack([]int{dh, dw})
						}
					}
				}
				/*
					if M[h-1][w] == LAND {
						queue.PushBack([]int{h - 1, w})
					}
					if M[h-1][w+1] == LAND {
						queue.PushBack([]int{h - 1, w + 1})
					}
					if M[h][w+1] == LAND {
						queue.PushBack([]int{h, w + 1})
					}
					if M[h+1][w+1] == LAND {
						queue.PushBack([]int{h + 1, w + 1})
					}
					if M[h+1][w] == LAND {
						queue.PushBack([]int{h + 1, w})
					}
					if M[h+1][w-1] == LAND {
						queue.PushBack([]int{h + 1, w - 1})
					}
					if M[h][w-1] == LAND {
						queue.PushBack([]int{h, w - 1})
					}
					if M[h-1][w-1] == LAND {
						queue.PushBack([]int{h - 1, w - 1})
					}
				*/
			}
		}
	}
	return islands
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	for {
		W, H := nextInt(sc), nextInt(sc)

		if W == 0 && H == 0 {
			break
		}
		// Initialize map and visted list
		M := make([][]int, H+2)
		V := make([][]int, H+2)
		for i := 0; i < H+2; i++ {
			M[i] = make([]int, W+2)
			V[i] = make([]int, W+2)
		}
		for i := 1; i <= H; i++ {
			for j := 1; j <= W; j++ {
				M[i][j] = nextInt(sc)
			}
		}

		islands := discoverIslands(M, V, H, W)

		fmt.Println(islands)
	}
}

C++: #include <iostream>
#include <vector>
#include <map>
#include <set>
using namespace std;

void add_label(map<int,int> &tbl, int a, int b){
	if( a == b ) return;
	if( a > b ) tbl[a] = b;
	else tbl[b] = a;
}

int main(void){
	int w, h;
	while( cin>>w>>h, w||h ) {
		vector<vector<int> > field( h );
		vector<vector<int> > labeled( h );
		for( int i=0; i<h; ++i ) {
			field[i] = vector<int>( w );
			labeled[i] = vector<int>( w );
			for( int j=0; j<w; ++j ) {
				cin>>field[i][j];
				labeled[i][j] = 0;
			}
		}
		int label = 1;
		map<int, int> tbl;
		for( int i=0; i<h; ++i ) {
			for( int j=0; j<w; ++j ) {
				if( field[i][j] ){
					bool f = false;
					if( i ) {
						if( j && labeled[i-1][j-1] ) {
							if(!f) labeled[i][j] = labeled[i-1][j-1];
							f = true;
						}
						if( labeled[i-1][j] ) {
							if(!f) labeled[i][j] = labeled[i-1][j];
							else add_label( tbl, labeled[i][j] ,labeled[i-1][j] );
							f = true;
						}
						if( j < w - 1 && labeled[i-1][j+1] ) {
							if(!f) labeled[i][j] = labeled[i-1][j+1];
							else add_label( tbl, labeled[i][j] ,labeled[i-1][j+1] );
							f = true;
						}
						if( j && labeled[i][j-1] ) {
							if(!f) labeled[i][j] = labeled[i][j-1];
							else add_label( tbl, labeled[i][j] ,labeled[i][j-1] );
							f = true;
						}
						if(!f) labeled[i][j] = ++label;
					} else {
						if( j && labeled[i][j-1] ){
							if(!f) labeled[i][j] = labeled[i][j-1];
							else add_label( tbl, labeled[i][j] ,labeled[i][j-1] );
							f = true;
						}
						if(!f) labeled[i][j] = ++label;
					}
				}
			}
		}
		for( auto x : tbl ) {
			int a = x.first;
			int b = x.second;
			while( tbl.find(b) != tbl.end() ) {
				b = tbl.find(b)->second;
			}
			for( int i=0; i<h; ++i ) {
				for( int j=0; j<w; ++j ) {
					if( labeled[i][j] == a ) labeled[i][j] = b;
				}
			}
		}
		
		for( int i=0; i<h; ++i ) {
			cerr<<"!";
			for( int j=0; j<w; ++j ) {
				cerr<<labeled[i][j];
			}
			cerr<<endl;
		}
		
		set<int> nums;
		nums.insert(0);
		for( int i=0; i<h; ++i ) {
			for( int j=0; j<w; ++j ) {
				nums.insert( labeled[i][j] );
			}
		}
		cout<<nums.size()-1<<endl;
	}
	return 0;
}

C++: # include <algorithm>
# include <cassert>
# include <cctype>
# include <cstdio>
# include <cstdlib>
# include <cstring>
# include <cmath>
# include <iostream>
# include <map>
# include <queue>
# include <set>
# include <sstream>
# include <stack>
# include <string>
# include <vector>
# include <iomanip>

# define rep(i, n) for (int i = 0; i < (int)(n); i++)
# define irep(i, n) for (int i = int(n) - 1; i >= 0; i--)
# define FOR(i, m, n) for (int i = int(m); i < (int)(n); i++)

using namespace std;
int w, h, ans;

template <typename T>
void show_all(T t) {
  rep (i, t.size()) {
    rep (j, t[0].size()) {
      cout << setfill('0') << setw(5) << t[i][j] << ' ';
    }
    cout << endl;
  }
  cout << endl;
}


void dfs(vector<vector<int>> &c, int i, int j) {
  vector<int> next_i = {0, 1, 1, 1, 0, -1, -1, -1};
  vector<int> next_j = {1, 1, 0, -1, -1, -1, 0, 1};

  rep (k, 8) {
    int ii = i + next_i[k];
    int jj = j + next_j[k];

    if (0 <= ii && 0 <= jj && ii < c.size() && jj < c[0].size() && c[ii][jj] == 1) {
      c[ii][jj] = 1000;
      dfs(c, ii, jj);
    }
  }
}


int main() {

  while (cin >> w >> h && w && h) {
    vector<vector<int>> c;
    ans = 0;

    rep (i, h) c.push_back(vector<int>(w));
    rep (i, h) {
      rep (j, w) {
        cin >> c[i][j];
      }
    }

    rep (i, h) {
      rep (j, w) {
        if (c[i][j] == 1) {
          ans++;
          c[i][j] = 1000;
          dfs(c, i, j);
        }
      }
    }

    cout << ans << endl;
  }
}

C++: #include<iostream>
using namespace std;
void kazoe(int p,int P, int box[50][50]){
  if(box[p][P+1]==1){
    box[p][P+1]=0;
    P=P+1;
    kazoe(p,P,box);
  }
  if(box[p+1][P+1]==1){
    box[p+1][P+1]=0;
    P=P+1;
    p=p+1;
 kazoe(p,P,box);
  }
  if(box[p+1][P]==1){
    box[p+1][P]=0;
    p=p+1;
 kazoe(p,P,box);
  }
  if(box[p+1][P-1]==1){
    box[p+1][P-1]=0;
    P=P-1;
    p=p+1;
 kazoe(p,P,box);
  }
  if(box[p][P-1]==1){
    box[p][P-1]=0;
    P=P-1;
 kazoe(p,P,box);
  }
  if(box[p-1][P-1]==1){
    box[p-1][P-1]=0;
    P=P-1;
    p=p-1;
 kazoe(p,P,box);
  }
  if(box[p-1][P]==1){
    box[p-1][P]=0;
    p=p-1;
 kazoe(p,P,box);
  }
  if(box[p-1][P+1]==1){
    box[p-1][P+1]=0;
    P=P+1;
    p=p-1;
 kazoe(p,P,box);
  }
}
int main(){
  int w,h,i,I,p,P,a=0;
  int box[50][50];
  while(1){
    cin>>w>>h;
    if(w==0&&h==0) break;
    for(i=0;i<h;i++){
      for(I=0;I<w;I++){
	cin>>box[i][I];
      }
    }
    for(i=0;i<h;i++){
      for(I=0;I<w;I++){
	if(box[i][I]==1){
	  p=i;
	  P=I;
	  box[p][P]=0;
	  kazoe(p,P,box);
	  box[i][I]=1;
	}
      }
    }
    for(i=0;i<h;i++){
      for(I=0;I<w;I++){
	if(box[i][I]==1) a++;
      }
    }
  
    cout<<a<<endl;
    a=0;
  }
  return 0;
}