Olá, Billy e demais companheiros clippeiros, quem sabe podemos escrever um solucionador de sudokus em cooperação?
Comecei a estudar os sudokus e descobri que há técnicas básicas, intermediárias e avançadas de solução. A única que eu conhecia o pessoal chama de "varredura" e consiste no seguinte: considere que as células vazias não são realmente vazias mas contêm, antes de começar a solucionar o jogo, como "possibilidades" os números todos de 1 a 9. E para começar, então, eliminamos das possibilidades dessas células aparentemente vazias os números que já estão explícitos na mesma linha, na mesma coluna ou no mesmo bloco dessa célula. Por exemplo: digamos que as linhas sejam designadas com letras de A a I e as colunas, de 1 a 9. Digamos que a célula A1 esteja vazia. E que a célula A2 tenha o número 3. Ora, as "possibilidades" para a célula A1, em vez de "123456789" passam a ser "12456789", sem o "3". Digamos que a célula E1 tenha o número "4". As possibilidades para A1 passam a ser "1256789". Para finalizar, digamos que C9 tenha o número "7". A1 fica sendo "125689".
Por esse princípio, varrer linhas, colunas e boxes de cada célula, escrevi o "TESTE.PRG", que trago para sua apreciação.
Copiei sua ideia, Billy, de variáveis que contêm nomes de variáveis, o que salvou a pele na hora dos "FOR...NEXT". E eu já tinha até esquecido a poderosa macrosubstituição...
No fonte que escrevi há dois exemplos de sudokus, um médio e um difícil. O médio, essa técnica resolve. O difícil ainda está em elaboração. Estou trabalhando no seguinte, agora: digamos que num determinado bloco duas células tenham como possibilidades os mesmos (e apenas) dois números, por exemplo os números "1" e "2". Assim esses números só podem estar nessas duas células, logo podem ser retirados das "possibilidades" das outras célula no mesmo bloco. Se uma dessas outras célula contiver, como "possibilidades" os números "1", "2" e "3", pronto: resolvida essa célula com o número "3". Mas isso ainda está a caminho.
Eis o que escrevi, até agora:
Código: Selecionar todos
public pos_jogo11
public pos_jogo12
public pos_jogo13
public pos_jogo14
public pos_jogo15
public pos_jogo16
public pos_jogo17
public pos_jogo18
public pos_jogo19
public pos_jogo21
public pos_jogo22
public pos_jogo23
public pos_jogo24
public pos_jogo25
public pos_jogo26
public pos_jogo27
public pos_jogo28
public pos_jogo29
public pos_jogo31
public pos_jogo32
public pos_jogo33
public pos_jogo34
public pos_jogo35
public pos_jogo36
public pos_jogo37
public pos_jogo38
public pos_jogo39
public pos_jogo41
public pos_jogo42
public pos_jogo43
public pos_jogo44
public pos_jogo45
public pos_jogo46
public pos_jogo47
public pos_jogo48
public pos_jogo49
public pos_jogo51
public pos_jogo52
public pos_jogo53
public pos_jogo54
public pos_jogo55
public pos_jogo56
public pos_jogo57
public pos_jogo58
public pos_jogo59
public pos_jogo61
public pos_jogo62
public pos_jogo63
public pos_jogo64
public pos_jogo65
public pos_jogo66
public pos_jogo67
public pos_jogo68
public pos_jogo69
public pos_jogo71
public pos_jogo72
public pos_jogo73
public pos_jogo74
public pos_jogo75
public pos_jogo76
public pos_jogo77
public pos_jogo78
public pos_jogo79
public pos_jogo81
public pos_jogo82
public pos_jogo83
public pos_jogo84
public pos_jogo85
public pos_jogo86
public pos_jogo87
public pos_jogo88
public pos_jogo89
public pos_jogo91
public pos_jogo92
public pos_jogo93
public pos_jogo94
public pos_jogo95
public pos_jogo96
public pos_jogo97
public pos_jogo98
public pos_jogo99
public pos_box11:='pos_jogo11'
public pos_box12:='pos_jogo12'
public pos_box13:='pos_jogo13'
public pos_box21:='pos_jogo14'
public pos_box22:='pos_jogo15'
public pos_box23:='pos_jogo16'
public pos_box31:='pos_jogo17'
public pos_box32:='pos_jogo18'
public pos_box33:='pos_jogo19'
public pos_box14:='pos_jogo21'
public pos_box15:='pos_jogo22'
public pos_box16:='pos_jogo23'
public pos_box24:='pos_jogo24'
public pos_box25:='pos_jogo25'
public pos_box26:='pos_jogo26'
public pos_box34:='pos_jogo27'
public pos_box35:='pos_jogo28'
public pos_box36:='pos_jogo29'
public pos_box17:='pos_jogo31'
public pos_box18:='pos_jogo32'
public pos_box19:='pos_jogo33'
public pos_box27:='pos_jogo34'
public pos_box28:='pos_jogo35'
public pos_box29:='pos_jogo36'
public pos_box37:='pos_jogo37'
public pos_box38:='pos_jogo38'
public pos_box39:='pos_jogo39'
public pos_box41:='pos_jogo41'
public pos_box42:='pos_jogo42'
public pos_box43:='pos_jogo43'
public pos_box51:='pos_jogo44'
public pos_box52:='pos_jogo45'
public pos_box53:='pos_jogo46'
public pos_box61:='pos_jogo47'
public pos_box62:='pos_jogo48'
public pos_box63:='pos_jogo49'
public pos_box44:='pos_jogo51'
public pos_box45:='pos_jogo52'
public pos_box46:='pos_jogo53'
public pos_box54:='pos_jogo54'
public pos_box55:='pos_jogo55'
public pos_box56:='pos_jogo56'
public pos_box64:='pos_jogo57'
public pos_box65:='pos_jogo58'
public pos_box66:='pos_jogo59'
public pos_box47:='pos_jogo61'
public pos_box48:='pos_jogo62'
public pos_box49:='pos_jogo63'
public pos_box57:='pos_jogo64'
public pos_box58:='pos_jogo65'
public pos_box59:='pos_jogo66'
public pos_box67:='pos_jogo67'
public pos_box68:='pos_jogo68'
public pos_box69:='pos_jogo69'
public pos_box71:='pos_jogo71'
public pos_box72:='pos_jogo72'
public pos_box73:='pos_jogo73'
public pos_box81:='pos_jogo74'
public pos_box82:='pos_jogo75'
public pos_box83:='pos_jogo76'
public pos_box91:='pos_jogo77'
public pos_box92:='pos_jogo78'
public pos_box93:='pos_jogo79'
public pos_box74:='pos_jogo81'
public pos_box75:='pos_jogo82'
public pos_box76:='pos_jogo83'
public pos_box84:='pos_jogo84'
public pos_box85:='pos_jogo85'
public pos_box86:='pos_jogo86'
public pos_box94:='pos_jogo87'
public pos_box95:='pos_jogo88'
public pos_box96:='pos_jogo89'
public pos_box77:='pos_jogo91'
public pos_box78:='pos_jogo92'
public pos_box79:='pos_jogo93'
public pos_box87:='pos_jogo94'
public pos_box88:='pos_jogo95'
public pos_box89:='pos_jogo96'
public pos_box97:='pos_jogo97'
public pos_box98:='pos_jogo98'
public pos_box99:='pos_jogo99'
for i = 1 to 9 // todas as celulas estao 'vazias', ou seja, com todas as possibilidades intactas
for j = 1 to 9
var := 'pos_jogo' + str(i,1,0) + str(j,1,0)
&var := '123456789'
next
next
/* exemplo: medio
pos_jogo17 := '3'
pos_jogo18 := '4'
pos_jogo21 := '6'
pos_jogo24 := '5'
pos_jogo27 := '9'
pos_jogo31 := '5'
pos_jogo32 := '1'
pos_jogo35 := '2'
pos_jogo41 := '2'
pos_jogo46 := '5'
pos_jogo49 := '6'
pos_jogo51 := '8'
pos_jogo52 := '7'
pos_jogo54 := '3'
pos_jogo55 := '6'
pos_jogo57 := '2'
pos_jogo65 := '1'
pos_jogo68 := '8'
pos_jogo73 := '8'
pos_jogo76 := '1'
pos_jogo81 := '1'
pos_jogo82 := '3'
pos_jogo84 := '6'
pos_jogo85 := '9'
pos_jogo86 := '7'
pos_jogo91 := '7'
pos_jogo98 := '6'
pos_jogo99 := '1' */
// exemplo: dificil
pos_jogo11 := '8'
pos_jogo23 := '3'
pos_jogo24 := '6'
pos_jogo32 := '7'
pos_jogo35 := '9'
pos_jogo37 := '2'
pos_jogo42 := '5'
pos_jogo46 := '7'
pos_jogo55 := '4'
pos_jogo56 := '5'
pos_jogo57 := '7'
pos_jogo64 := '1'
pos_jogo68 := '3'
pos_jogo73 := '1'
pos_jogo78 := '6'
pos_jogo79 := '8'
pos_jogo83 := '8'
pos_jogo84 := '5'
pos_jogo88 := '1'
pos_jogo92 := '9'
pos_jogo97 := '4'
qtd_ok1 := 0 // quando o jogo estiver solucionado, havera apenas 1 numero em cada celula...
for i = 1 to 9
for j = 1 to 9
var := 'pos_jogo'+ str(i,1,0) + str(j,1,0)
qtd_ok1 := qtd_ok1 + len(&var)
next
next
feito := .f.
whil .not. feito
veri_lin()
veri_col()
veri_box()
qtd_ok := 0
for i = 1 to 9 // quando o jogo estiver solucionado, havera apenas 1 numero em cada celula...
for j = 1 to 9
var := 'pos_jogo'+ str(i,1,0) + str(j,1,0)
qtd_ok := qtd_ok + len(&var)
next
next
if qtd_ok = 81 // ... ou seja, qdt_ok, a soma da quantidade de numeros em cada celula, sera 81
feito := .t.
else
if qtd_ok = qtd_ok1
altd() // se depois de um ciclo de verificacoes nenhuma celula tiver mudado, o metodo usado e insuficiente
endi
endi
endd
altd() // para inspecionar o resultado, caso o jogo esteja resolvido
retu
func veri_lin
for i = 1 to 9
for j = 1 to 9
var := 'pos_jogo' + str(i,1,0) + str(j,1,0) // nome da celula em exame
if len(&var) > 1 // se a celula em exame tem mais de uma possibilidade...
for k = 1 to 9
if k <> j // e nao e ela mesma.
var1 := 'pos_jogo' + str(i,1,0) + str(k,1,0) // nome da proxima celula na mesma linha
if len(&var1) = 1 // so interessa comparar a proxima celula com a em exame se essa proxima estiver resolvida
onde := at(&var1,&var)
if onde > 0 // se a celula em exame tiver algum numero que coincida com a proxima celula...
novo := '' // contera os numeros da celula em exame exceto o que ja estava na proxima celula
for l = 1 to len(&var)
if l <> onde
novo := novo + subs(&var,l,1)
endi
next
&var := novo
endi
endi
endi
next
endi
next
next
retu .t.
func veri_col
for i = 1 to 9
for j = 1 to 9
var := 'pos_jogo' + str(j,1,0) + str(i,1,0)
if len(&var) > 1
for k = 1 to 9
if k <> j
var1 := 'pos_jogo' + str(k,1,0) + str(i,1,0)
if len(&var1) = 1
onde := at(&var1,&var)
if onde > 0
novo := ''
for l = 1 to len(&var)
if l <> onde
novo := novo + subs(&var,l,1)
endi
next
&var := novo
endi
endi
endi
next
endi
next
next
retu .t.
func veri_box
for i = 1 to 9
for j = 1 to 9
var := 'pos_box' + str(i,1,0) + str(j,1,0)
var1 := &var
if len(&var1) > 1
for k = 1 to 9
if k <> j
var2 := 'pos_box' + str(i,1,0) + str(k,1,0)
var3 := &var2
if len(&var3) = 1
onde := at(&var3,&var1)
if onde > 0
novo := ''
for l = 1 to len(&var1)
if l <> onde
novo := novo + subs(&var1,l,1)
endi
next
&var1 := novo
endi
endi
endi
next
endi
next
next
retu .t.
Em tempo: é muito bom relembrar o Clipper,
