///<summary>
///Objet qui decrit une grille de Sodoku
///<summary> 
var sodokuGrid=  {
  ///<summary>
  ///Represente la grille en elle meme comme une matrice
  ///<summary> 
    matrix:null,
  ///<summary>
  /// Un compteur qui servira dans les tests
  ///<summary> 
    counter:0,
    size:9,
  ///<summary>
  /// Un chrono pour les tests et les perfs
  ///<summary> 
    stopWatch:0,
  ///<summary>
  /// generer une solution valide 
  ///<summary>
  ///<param name="arg"></param>
  ///<return name="matrix">renvoie une matrice sous forme de solution</return>
    resolve:function(arg){
            this.init(arg);
  
            for(var i=0;i<81;i++){
                  var row = parseInt(i / 9);
                  var col = i - (row * 9);
                  this.counter++;
                  var num = this.getNext(row,col);
                  if( num){
                      this.matrix[row][col].value =num ;
                    }else{
                      i-=2;
                    }
  
              }
            this.stopWatch=new Date()-this.stopWatch; 
          return  this.matrix
    },
  
  ///<summary>
  ///obtenir un nombre valid pour la cellule actuelle  
  ///<summary>
  ///<param name="i">la ligne actuelle</param>
  ///<param name="j">la colonne actuelle</param>
  ///<return name="number">renvoie un nombre de 1 a 9 ou undefined </return>
    getNext:function(i,j){
            var len=this.matrix[i][j].poss.length
            if(!len){
                  this.matrix[i][j].poss = this.getPossibilities();
                  return 
            }
            var num = this.matrix[i][j].poss.splice(this.randomize(0,len), 1)[0]
            if(this.isValid(i,j,num)){
                    return num
            } else{
              return this.getNext(i,j);
            }
  
    },
  ///<summary>
  ///verifie qu un nombre est valable pour la cellule   
  ///<summary>
  ///<param name="i">la ligne actuelle</param>
  ///<param name="j">la colonne actuelle</param>
  ///<param name="num">le nombre a verifier</param>
  ///<return name="number">renvoie un nombre de 1 a 9 ou undefined </return> 
    isValid:function(i,j,num){
          for(var k=0;k<j;k++){
                if(this.matrix[i][k].value ==num)return false ;
            }; 
  
            for(var k=0;k<i;k++){
              if(this.matrix[k][j].value==num)return false ;
            };
  
          var minJ=parseInt(j/3)*3,minI=parseInt(i/3)*3;
          var maxJ=minJ+3,maxI=minI+3;
          for(var l=minI;l<i;l++){
              for(var m=minJ;m<maxJ;m++){
                  if(this.matrix[l][m].value==num)return false ;
                }
            }
      return true;
    },
  ///<summary>
  ///initialise la grille    
  ///<summary>
    init:function(){
        this.matrix=new Array(this.size);
        this.counter=0;
        this.stopWatch=new Date();
        var that=this;
        this.matrix=new Array(this.size);
        for(var j=0;j<this.size;j++){
  
            this.matrix[j]=new Array(9);
            for(var i=0;i<this.size;i++){
                    this.matrix[j][i]={
                                  value:"",
                                  poss:that.getPossibilities()
                                  }						  
              }
        }						
  
      },	   
  ///<summary>
  ///genere un tableau de possibiles de 1 a 9     
  ///<return name="Array">renvoie un tableau </return> 
    getPossibilities: function(){
              return [1,2,3,4,5,6,7,8,9] ;
    }, 
  ///<summary>
  ///genere un nombre aleatoire entre deux chiffres   
  ///<summary>
  ///<param name="min">la valeur basse</param>
  ///<param name="max">la valeur haute</param>
  ///<return name="Number">renvoie entre le min et le mx </return> 
    randomize: function(min, max){
          return parseInt(Math.random()*max)+min ;
    }	

}
<!DOCTYPE html>
<html ng-app>
 <head lang="en">
<title>SODOKU</title>
<meta charset="utf-8">

</head>
<body>
<div id="sodoku"  style="width:400px; height:400px;" ng-controller="sodokuCtrl">

<table width="100%" border="1">
<tr ng-repeat="row in matrix">
    <td ng-repeat="col in row">{{col.value}}</td>
</tr>
</table>
<br/>
Nombre de boucles: <input ng-model="counter"/>
<br/>
Temps de génération en ms ::<input ng-model="stopWatch"/>
<br/>
<br/>
<br/>
<b>*</b></b><small>Actualiser la page pour générer une nouvelle grille solution </small> 
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script type="text/javascript" src="sodokuAlgo.js"></script>


<script>
 function sodokuCtrl($scope){
  
  $scope.matrix=sodokuGrid.resolve();
  $scope.counter=sodokuGrid.counter;
  $scope.stopWatch=sodokuGrid.stopWatch;
 }
 </script>
</body>
</html>