Sudoku initial commit
This commit is contained in:
commit
214c84417d
6 changed files with 5470 additions and 0 deletions
2379
corelib.js
Normal file
2379
corelib.js
Normal file
File diff suppressed because it is too large
Load diff
57
css.css
Normal file
57
css.css
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
@CHARSET "UTF-8";
|
||||||
|
|
||||||
|
body{
|
||||||
|
background: white;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-style: normal;
|
||||||
|
font-size:x-small;
|
||||||
|
font: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sudoku{
|
||||||
|
margin-left: 5%;
|
||||||
|
}
|
||||||
|
#interface{
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
br{
|
||||||
|
clear:both;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.vspace{
|
||||||
|
min-height: 10px;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pagbreak{
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sudo_table{
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
table.par{
|
||||||
|
background-color: #AAAAAA;
|
||||||
|
color: black;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table{
|
||||||
|
float:left;
|
||||||
|
page-break-after:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.impar{
|
||||||
|
background-color:#BBBBBB;
|
||||||
|
color:black;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
td{
|
||||||
|
min-width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
border: dashed;
|
||||||
|
border-width: thin;
|
||||||
|
}
|
62
index.html
Normal file
62
index.html
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Sudoku</title>
|
||||||
|
<script type="text/javascript" src="js.js"></script>
|
||||||
|
<link href="css.css" type="text/css" rel="stylesheet">
|
||||||
|
<script type="text/javascript" src="sudoku.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="sudoku">
|
||||||
|
</div>
|
||||||
|
<div id="interface">
|
||||||
|
<label>Escolha o número de sudokus a gerar:</label>
|
||||||
|
<select id="num_sud" onchange="gera('num_sud')">
|
||||||
|
</select>
|
||||||
|
<input type="button" value="Imprimir" id="print" onclick="window.print()">
|
||||||
|
<label>Com Soluções?</label><input id="com_sol" type="checkbox" onclick="gera('num_sud')"></input>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var MAXIT=10000;
|
||||||
|
var PopulateComboBox=function(id){
|
||||||
|
var c=$(id);
|
||||||
|
var opt;
|
||||||
|
var html="";
|
||||||
|
for(var i=1;i<=MAXIT;i++){
|
||||||
|
html+="<option value=\""+i+"\">"+i+"</option>";
|
||||||
|
}
|
||||||
|
c.innerHTML=html;
|
||||||
|
}
|
||||||
|
|
||||||
|
var gera=function(id){
|
||||||
|
var nsud=$(id).get('$option')[$(id).selectedIndex].value;
|
||||||
|
var ch=$('com_sol');
|
||||||
|
var s=new Sudoku();
|
||||||
|
var html="";
|
||||||
|
for(var i=1;i<=nsud;i++){
|
||||||
|
while(!s.buildSudoku());
|
||||||
|
html+=s.getSudoku();
|
||||||
|
if(ch.checked){
|
||||||
|
html+=s.toHTML();
|
||||||
|
html+="<div class='vspace'></div>";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(i%2==0)
|
||||||
|
html+="<div class='vspace'></div>";
|
||||||
|
}
|
||||||
|
if(ch.checked){
|
||||||
|
if(i%3==0)
|
||||||
|
html+="<div class='pagbreak'></div>";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(i%6==0) html+="<div class='pagbreak'></div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.innerHTML=html;
|
||||||
|
}
|
||||||
|
PopulateComboBox('num_sud');
|
||||||
|
var d=$('sudoku');
|
||||||
|
</script>
|
||||||
|
</html>
|
258
sudoku.js
Normal file
258
sudoku.js
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
/***
|
||||||
|
* Classe que implementa o Sudoku
|
||||||
|
* @author Balhau
|
||||||
|
* @classDescription O objecto Sudoku contém funções para geração de sudokus e respectivas soluções
|
||||||
|
* @requires Este ficheiro necessita do ficheiro js.js como requisito devido a funções utilitárias
|
||||||
|
*/
|
||||||
|
var Sudoku=function(){
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
this._mat=[];
|
||||||
|
this.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
Sudoku.getPosXY=function(pos){
|
||||||
|
var x=pos%9;
|
||||||
|
var y=Math.floor(pos/9);
|
||||||
|
return {"x":x,"y":y};
|
||||||
|
};
|
||||||
|
|
||||||
|
Sudoku.toPos=function(x,y){
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
if(x>=dx)
|
||||||
|
x=dx-1;
|
||||||
|
if(y>=dy)
|
||||||
|
y=dy-1;
|
||||||
|
return y*9+x;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Verifica se a coluna contem valores todos diferentes
|
||||||
|
* @param pos Posição no vector
|
||||||
|
* @param val Valor a colocar no vector
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.checkColum=function(pos,val){
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
var p=Sudoku.getPosXY(pos);
|
||||||
|
for(var i=0;i<dy;i++){
|
||||||
|
if(this._mat[p.x+i*dy]==val)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifica se a linha contem valores todos diferentes
|
||||||
|
* @param pos Posição no vector
|
||||||
|
* @param val Valor a colocar no vector
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.checkLine=function(pos,val){
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
var p=Sudoku.getPosXY(pos);
|
||||||
|
for(var i=0;i<dx;i++){
|
||||||
|
if(this._mat[p.y*dy+i]==val)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que verifica se o valor é válido para o bloco
|
||||||
|
* @param pos Indice do vector
|
||||||
|
* @param val Valor a atribuir
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.checkBlock=function(pos,val){
|
||||||
|
var p=Sudoku.getPosXY(pos);
|
||||||
|
var pi,pj;//variaveis que identificam o bloco
|
||||||
|
if(p.x<3)pi=0;else if(p.x>=3 && p.x<6)pi=1;else pi=2;
|
||||||
|
if(p.y<3)pj=0;else if(p.y>=3 && p.y<6)pj=1;else pj=2;
|
||||||
|
var ci=0;
|
||||||
|
var pii=pi*3;
|
||||||
|
var li=pj*9*3;
|
||||||
|
for(var i=0;i<9;i++){
|
||||||
|
if(i%3==0 && i!=0){
|
||||||
|
ci=0;
|
||||||
|
li+=9;
|
||||||
|
}
|
||||||
|
//var p=Sudoku.getPosXY(li+ci+pii);
|
||||||
|
//console.log("PosA: "+p.x+","+p.y);
|
||||||
|
if(this._mat[li+ci+pii]==val)
|
||||||
|
return false;
|
||||||
|
ci++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que reinicia o vector com os valores do sudoku
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.clear=function(){
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
for(var i=0;i<dx*dy;i++){
|
||||||
|
this._mat[i]=-1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que efectua uma limpeza nos n valores anteriores à posição pos
|
||||||
|
* @param pos Posição para a qual se pretende iniciar o reset de valores
|
||||||
|
* @param n Número de celulas que irão ser limpas
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.clearLastValues=function(pos,n){
|
||||||
|
var min=Math.max(0,n);
|
||||||
|
for(var i=min;i<=pos;i++){
|
||||||
|
this._mat[i]=-1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Sudoku.DIMX=9;
|
||||||
|
Sudoku.DIMY=9;
|
||||||
|
Sudoku.BACK_TRACK_STEP=9;
|
||||||
|
Sudoku.EASY=1;
|
||||||
|
Sudoku.NORMAL=2;
|
||||||
|
Sudoku.HARD=3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que gera uma instância do sudoku;
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.buildSudoku=function(){
|
||||||
|
this.clear();
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
var num;
|
||||||
|
var maxit=100;
|
||||||
|
var maxitt=1000;
|
||||||
|
var it=0;
|
||||||
|
var step;
|
||||||
|
var itt=0;
|
||||||
|
for(var i=0;i<dx*dy;){
|
||||||
|
it++;
|
||||||
|
num=Math.floor(Math.random()*9)+1;
|
||||||
|
if(this.checkLine(i,num) && this.checkColum(i,num) && this.checkBlock(i, num)){//
|
||||||
|
it=0;
|
||||||
|
this._mat[i]=num;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(it>maxit){
|
||||||
|
pos=Math.max(0,i-Sudoku.BACK_TRACK_STEP);
|
||||||
|
this.clearLastValues(i, pos); //backtrack
|
||||||
|
i=pos; //retorna atrás nas iteracções
|
||||||
|
it=0; //inicia o contador
|
||||||
|
itt++;
|
||||||
|
}
|
||||||
|
if(itt>maxitt){
|
||||||
|
i=maxitt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i==maxitt)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que devolve os blocos do sudoku sob a forma de HTML
|
||||||
|
* @param x Ponto x do bloco
|
||||||
|
* @param y Ponto y do bloco
|
||||||
|
* @return String com o código em HTML do bloco
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.getHTMLBlock=function(x,y){
|
||||||
|
var pi,pj;//variaveis que identificam o bloco
|
||||||
|
if(x<3)pi=0;else if(x>=3 && x<6)pi=1;else pi=2;
|
||||||
|
if(y<3)pj=0;else if(y>=3 && y<6)pj=1;else pj=2;
|
||||||
|
var ci=0;
|
||||||
|
var pii=pi*3;
|
||||||
|
var li=pj*9*3;
|
||||||
|
var ncl=((x+y)%2==0)?"par":"impar";
|
||||||
|
var str="<table class=\""+ncl+"\">\n\t<tr>";
|
||||||
|
for(var i=0;i<9;i++){
|
||||||
|
if(i%3==0 && i!=0){
|
||||||
|
ci=0;
|
||||||
|
li+=9;
|
||||||
|
str+="\n\t</tr>\n\t<tr>";
|
||||||
|
}
|
||||||
|
str+="\n\t\t<td>"+this._mat[li+ci+pii]+"</td>";
|
||||||
|
ci++;
|
||||||
|
}
|
||||||
|
str+="\n\t</tr>\n</table>";
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que devolve uma instância do sudoku em função do seu nível de dificuldade
|
||||||
|
* @param level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.getSudoku=function(level){
|
||||||
|
if(BLauLib.isUndefined(level))
|
||||||
|
level=Sudoku.EASY;
|
||||||
|
var comp=this._mat.length;
|
||||||
|
var pb=0.5-level*0.12;
|
||||||
|
var ninst=new Sudoku();
|
||||||
|
var mclone=this._mat.clone();
|
||||||
|
for(var i=0;i<comp;i++){
|
||||||
|
if(Math.random()<pb){
|
||||||
|
mclone[i]=this._mat[i];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mclone[i]="_";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ninst._mat=mclone;
|
||||||
|
return ninst.toHTML();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que converte o sudoku para a sua representação sob a forma de código em HTML
|
||||||
|
* @return String em HTML
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.toHTML=function(){
|
||||||
|
var dx=Sudoku.DIMX;
|
||||||
|
var dy=Sudoku.DIMY;
|
||||||
|
var str="<table class='sudo_table'>";
|
||||||
|
for(var i=0;i<3;i++){
|
||||||
|
str+="<tr>";
|
||||||
|
for(var j=0;j<3;j++){
|
||||||
|
str+="<td>"+this.getHTMLBlock(1+j*3,1+i*3)+"</td>";
|
||||||
|
}
|
||||||
|
str+="</tr>";
|
||||||
|
}
|
||||||
|
str+="</table>";
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Método que devolve uma descrição do sudoku em forma de string
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
Sudoku.prototype.toString=function(){
|
||||||
|
var st="";
|
||||||
|
var cmp=this._mat.length;
|
||||||
|
var pl=1;
|
||||||
|
for(var i=0;i<cmp;i++){
|
||||||
|
if(i%3==0)
|
||||||
|
st+="|";
|
||||||
|
st+=this._mat[i]>0?this._mat[i]:" ";
|
||||||
|
if((i+1)%9==0){
|
||||||
|
pl++;
|
||||||
|
st+="|\n";
|
||||||
|
}
|
||||||
|
if(pl%4==0){
|
||||||
|
for(var j=0;j<9;j++){
|
||||||
|
st+="___";
|
||||||
|
}
|
||||||
|
st+="\n";
|
||||||
|
pl=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return st;
|
||||||
|
};
|
||||||
|
|
12
test.html
Normal file
12
test.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="corelib.js" language="JavaScript"></script>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Js Test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="paint" width="600" height="480">
|
||||||
|
</canvas>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue