Você está na página 1de 45

Universidade Federal do ABC

ufabc

J2 Velha
Uma Implementacao Java do Jogo da Velha
Utilizando o Algoritmo MiniMax

Andr
e Filipe de Moraes Batista
andre.batista@ufabc.edu.br

Luis Fernando de Oliveira Jacintho


luis.jacintho@ufabc.edu.br

Disciplina de Intelig
encia Artificial
o
Prof Jeronimo Pellegrini
Santo Andre, Junho de 2008

Sum
ario
1 Jogos em IA
1.1 Minimax - Algoritmo de Busca Competitiva . . . . . . . . . . . . . . . . .

1
1

2 J2 Velha: Uma Abordagem Java ao Jogo da Velha


2.1 J2 Velha . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Exemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4
4
8

Anexos

16

A J2 Velha: C
odigos
A.1 Classe Velha.java . . .
A.2 Classe Tabuleiro.java
A.3 Classe Sucessor.java .
A.4 Classe Minimax.java . .

.
.
.
.

16
16
18
20
21

.
.
.
.

27
27
30
34
35

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

B J2 Velha: Novas Funcionalidades


B.1 Classe Velha.java . . . . . . .
B.2 Classe Tabuleiro.java . . . .
B.3 Classe Sucessor.java . . . . .
B.4 Classe Minimax.java . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

ii

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

Captulo 1
Jogos em IA
Para a maioria das pessoas o termo jogo e considerado como um passatempo do dia-a-dia.
Para as criancas serve como um modo de fugir aos trabalhos de casa e entrar em um mundo
virtual de infinitas possibilidades. Para os adultos o termo jogo pode invocar imagens de
jogadores que procuram estrategias que lhes deem vantagens sobre os adversarios. Ou
seja, o resultado do jogo e determinado pelas estrategias utilizadas pelos jogadores. O
ramo da Matematica que pensa de semelhante maneira e denominado Teoria dos Jogos.
A Teoria dos Jogos tem por objetivo visualizar qualquer ambiente multiagente como
um jogo, desde que o impacto de cada agente sobre os outros seja, de algum modo,
significativo. Os jogos sao uma das areas mais antigas desenvolvidas em Inteligencia
Artificial (IA). Em 1950, desde que os computadores se tornaram programaveis, o primeiro
jogo de xadrez foi criado por Claude Shannon e por Alan Turing. Desde entao diversos
progressos ocorreram nesta area, de tal forma que os sistemas atuais sao capazes de
rivalizar e ganhar de um dos melhores jogadores de xadrez da historia, Garry Kasparov.
Em meados de 1996 ocorreu o primeiro confronto entre Garry Kasparov e o Deep
Blue. Trata-se de um super computador de alta performance desenvolvido pela IBM, seu
codigo de programacao e em linguagem C e e executado no sistema operacional AIX. O
resultado e uma maquina escalavel capaz de calcular entre 100 e 200 bilhoes de jogadas
em aproximadamente 3 minutos. No primeiro confronto entre os dois, a vitoria foi de
Kasparov. Ate que em 1997 a IBM desdobrou-se em constantes desenvolvimentos e atualizacoes de modo a melhorar o desempenho do Deep Blue. O resultado de tanto esforco
foi que Garry Kasparov foi vencido em 1997 pelo Deep Blue. A Figura 1.1 mostra uma
cena desta disputa.

1.1

Minimax - Algoritmo de Busca Competitiva

Em um ambiente multiagente os agentes convivem com situacoes de cooperacao e competicao. Um ambiente competitivo e aquele em que as metas dos agentes estao em constante
1

1.1. Minimax - Algoritmo de Busca Competitiva

Figura 1.1: Cena de um Disputa de Kasparov versus DeepBlue


.

conflito. Para tais situacoes e preciso desenvolver tecnicas de busca competitiva entre os
neste ponto que a teoria dos jogos pode auxiliar na construcao de um agente
agentes. E
racional.
Em IA os jogos normalmente sao de um tipo bastante especializados - algumas vezes
denominados determinsticos de revezamento de dois jogadores de soma zero com informacoes perfeitas. Isto representa ambiente determinsticos completamente observaveis em
que existem dois agentes cujas acoes devem se alternar e em que os valores de utilidade no
fim do jogo sao sempre iguais e opostos. Por exemplo, se um jogador ganha um jogo de
xadrez (+1), o outro jogador necessariamente perde (-1). Essa oposicao entre as funcoes
de utilidades dos agentes que gera a situacao de competicao.
O MiniMax e um algoritmo de busca competitiva que seleciona a melhor acao a ser
feita em uma situacao ou em um jogo, onde dois jogadores se empenham em alcancar
objetivos mutuamente exclusivos. Ele se aplica especialmente na busca em arvores de
jogo para determinar qual a melhor jogada para o jogador atual. O algoritmo se baseia
no princpio de que em cada jogada, o jogador ira escolher o melhor movimento possvel.
A arvore de jogo consiste de todas as jogadas possveis para o jogador atual como nos
filhos da raiz, e todas as jogadas disponveis para o proximo jogador como filhas destes nos
e assim por diante, ate o nvel que se desejar. Cada ramificacao da arvore representa um
movimento que o jogador pode fazer em tal momento do jogo. Uma busca mais profunda
na arvore fornece mais informacoes sobre as possveis vantagens ou armadilhas e portanto
resulta em uma jogada melhor.
O MiniMax faz uma busca que determina todas as possveis continuacoes do jogo ate
o nvel desejado, avaliando e atribuindo um valor a cada movimento possvel. A busca

1.1. Minimax - Algoritmo de Busca Competitiva

entao retorna na arvore de jogo alternando entre escolher o valor mais alto e o valor mais
baixo entre os valores da jogadas em um nvel. O metodo de busca consiste na ideia de
maximizar a utilidade supondo que o adversario vai tentar minimiza-la. Em termos de
busca, e realiza uma busca cega em profundidade, o agente e o MAX e seu adversario e o
MIN.
Algoritmo 1 MINIMAX

func
ao DECISAO-MINIMAX(estado)
retorna uma acao
entradas: estado, estado corrente no jogo
v VALOR-MAX(estado)
retornar a acao em SUCESSORES(estado) com valor v
func
ao VALOR-MAX(estado) retorna um valor de utilidade
se TESTE-TERMINAL(estado) ent
ao retornar UTILIDADE(estado)
v
para a, s em SUCESSORES(estado) faca
v MAX(v, VALOR-MIN(s))
retornar v
func
ao VALOR-MIN(estado) retorna um valor de utilidade
se TESTE-TERMINAL(estado) ent
ao retornar UTILIDADE(estado)
v
para a, s em SUCESSORES(estado) faca
v MAX(v, VALOR-MAX(s))
retornar v

Se fosse o caso de se tratar de uma busca normal, bastava percorrer-se a arvore ate
aos nos terminais e escolher o caminho que levasse ao no com maior valor de utilidade.
Mas nao e assim, visto existir outro jogador. Assim, e necessario, escolher a partir de
cada no filho, o menor valor de utilidade, e copia-lo para o no pai, recursivamente ate ao
no inicial. Este e o algoritmo MiniMax. Isto deve-se ao fato, do jogador MIN tentar
minimizar o ganho do jogador MAX, pois ele tentara escolher uma jogada, dentro das
possveis, que de menos pontos ao jogador adversario. Na Caixa de Algoritmo 1 tem-se o
algoritmo MiniMax.
No Captulo que segue tem-se uma implementacao do Jogo da Velha utilizando a
linguagem Java e o algoritmo MiniMax.

Captulo 2
J2 Velha: Uma Abordagem Java ao
Jogo da Velha
Conhecido tambem como Jogo do Galo, ou Tic Tac Toe, o jogo da velha e um jogo
extremamente simples, que nao possui grandes dificuldades para seus jogadores. Seu nome
teria se originado na Inglaterra, quando nos finais de tarde, mulheres se reuniriam para
conversar e bordar. A mulheres idosas, por nao terem mais condicoes de bordar em razao
da fraqueza de suas vistas, jogavam este jogo simples.
O jogo da velha e um dos exemplos mais classicos de utilizacao do algoritmo Minimax.
O estado inicial e os movimentos validos para cada lado definem a arvore do jogo correspondente ao jogo. A Figura 2.1 mostra parte da arvore de jogo para o jogo da velha. A
partir do estado inicial, MAX tem nove movimentos possveis. O jogo se alterna entre
a colocacao de um X por MAX e a colocacao de um O por MIN ate que se alcance nos
de folhas correspondentes a estados terminais, tais que um jogador tem tres smbolos em
uma linha, coluna ou ainda diagonal; ou ate que todos os quadrados estejam preenchidos.
O n
umero em cada no de folha indica o valor de utilidade do estado terminal, do ponto
de vista de MAX; valores altos sao considerados bons para MAX e ruins para MIN. Cabe
a MAX usar a arvore de busca para determinar o melhor movimento.

2.1

J2 Velha

J2 Velha (Java 2 Velha) e uma implementacao do Jogo da Velha desenvolvida na Linguagem Java utilizando o algoritmo MiniMax. Consiste de 4 classes, quais sejam:
1. Velha.java - Classe principal da Aplicacao;
2. Minimax.java - Classe responsavel em aplicar o algoritmo MiniMax;
3. Tabuleiro.java - Classe responsavel pela manipulacao do tabuleiro do jogo;
4

2.1. J2 Velha

Figura 2.1: Arvore


de busca parcial para o jogo da velha
.

4. Sucessor.java - Classe responsavel em gerar os sucessores, utilizados no algoritmo


MiniMax.
O algoritmo Minimax desenvolvido no J2 Velha pode buscar por profundidade infinita
(ate que se encontre um estado terminal) ou por alguma profundidade determinada. A
implementacao da escolha de profundidade deu-se em funcao da complexidade do algoritmo MiniMax. Se a profundidade maxima da arvore e m e existem b movimento validos
em cada ponto, a complexidade de tempo do algoritmo MiniMax e O(bm ).
Na Caixa de Codigo XX tem-se um trecho do algoritmo MiniMax contido na classe
possvel comparar esta implementacao com o algoritmo apresentado no
Minimax.java. E
Captulo anterior.

Codigo 2.1: Implementacao do Algoritmo



/
Metodo de d e c i s
a o do MiniMax
/
p u b l i c i n t [ ] [ ] d e c i s a o m i n i m a x ( i n t [ ] [ ] tab )
{
/
Limpa o s s u c e s s o r e s

MiniMax

2.1. J2 Velha

/
sucessores . clear () ;

/
Recebe a u t i l i d a d e m
axima
/
i n t v = valor max ( tab , t r u e , 1 ) ;

12

15

/
P e r c o r r e a l i s t a em busca do p r i m e i r o s u c e s s o r com u t i l i d a d e maxima
/
for ( Sucessor s : sucessores )
i f ( s . u t i l i d a d e == v )
return s . tabuleiro ;

18

21

r e t u r n tab ;
24

27

30

33

36

}
p u b l i c i n t valor max ( i n t [ ] [ ] tab , b o o l e a n prim , i n t p r o f )
{
/
Se a p r o f u n d i d a d e f o r maior que a maxima ou o j o g o acabou , r e t o r n a a
utilidade
/
i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( tab ) )
r e t u r n u t i l i d a d e ( tab ) ;
/
A t r i b u i o menor v a l o r de um i n t e i r o para v ( i n f i n i t o )
/
i n t v = I n t e g e r . MIN VALUE ;

39

42

45

48

51

/
P e r c o r r e o s n
a o s u c e s s o r e s de MAX
/
f o r ( S u c e s s o r s : g e r a r s u c e s s o r e s ( tab , 1 ) )
{
v = Math . max( v , v a l o r m i n ( s . t a b u l e i r o , p r o f ) ) ;
s . utilidade = v;
/
Se forem o s p r i m e i r o s s u c e s s o r e s , a d i c i o n a na l i s t a de s u c e s s o r e s
...
/
i f ( prim )
s u c e s s o r e s . add ( s ) ;
}

2.1. J2 Velha

return v ;

54

}
p u b l i c i n t v a l o r m i n ( i n t [ ] [ ] tab , i n t p r o f )
{
/
Se a p r o f u n d i d a d e f o r maior que a maxima ou o j o g o acabou , r e t o r n a a
utilidade
/
i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( tab ) )
r e t u r n u t i l i d a d e ( tab ) ;

57

60

63

/
A t r i b u i +I n f i n i t o
/
i n t v = I n t e g e r .MAX VALUE;

66

69

/
Percorre os n
o s s s u c e s s o r e s de MIN
/
f o r ( S u c e s s o r s : g e r a r s u c e s s o r e s ( tab , 1) )
{
v = Math . min ( v , valor max ( s . t a b u l e i r o , f a l s e , p r o f ) ) ;
s . utilidade = v;
}

72

75

78

return v ;
81

2.2. Exemplos

2.2

Exemplos

A seguir tem-se a execucao de algumas jogadas. Primeiramente vamos utilizar um tabuleiro de tamanho 3x3. Para tal nao se faz necessaria a definicao de uma profundidade
maxima, pois a resposta do algoritmo e rapida. Executando o classe Velha.java tem-se
a seguinte sada no prompt de comando:
UFABC - J2VELHA
Bem vindo ao Jogo!
Boa Sorte!

|
|
---+---+--|
|
---+---+--|
|
Sua jogada:
Linha [0 - 2]:
O jogador decide jogar na linha 0, coluna 1. Tem-se entao o resultado da jogada do
computador:
...
Sua jogada:
Linha [0 - 2]: 0
Coluna [0 - 2]: 1
| o |
---+---+--|
|
---+---+--|
|
Jogada do Computador:
x | o |
---+---+--|
|
---+---+--|
|

2.2. Exemplos

Sua jogada:
Linha [0 - 2]:
Para decidir onde jogar, o computador efetuou todo o algoritmo minimax e escolheu
uma posicao que lhe favoreca, ao mesmo tempo que prejudique (nao agora, pode ser nas
proximas jogadas) o adversario. O jogador agora decide jogar na linha 1, coluna 1. Tem-se
a seguinte jogada do computador:
...
Linha [0 - 2]: 1
Coluna [0 - 2]: 1
x | o |
---+---+--| o |
---+---+--|
|
Jogada do Computador:
x | o |
---+---+--| o |
---+---+--| x |
Sua jogada:
Linha [0 - 2]:
Observe que o computador decidiu jogar em uma posicao que evita que o adversario
ganhe. O jogador decide jogar na linha 0, coluna 2. Tem-se a jogada do computador:
...
Linha [0 - 2]: 0
Coluna [0 - 2]: 2
x | o | o
---+---+--| o |
---+---+--| x |

2.2. Exemplos

10

Jogada do Computador:
x | o | o
---+---+--| o |
---+---+--x | x |
Sua jogada:
Linha [0 - 2]:
Observe que de qualquer forma o computador ganhara a partida. O jogador decide
jogar na linha 2, coluna 2. Tem-se a vitoria do computador:
...
Linha [0 - 2]: 2
Coluna [0 - 2]: 2
x | o | o
---+---+--| o |
---+---+--x | x | o
Jogada do Computador:
x | o | o
---+---+--x | o |
---+---+--x | x | o
O computador ganhou!

Voce pode verificar o funcionamento do jogo com um tabuleiro 4x4. Basta mudar as
variaveis TAM e PROF na classe Velha. Devido `a complexidade do algoritmo recomenda-se
utilizar uma profundidade 5 para que o tempo de execucao do mesmo seja razoavel. A
seguir tem-se uma partida completa utilizando um tabuleiro 4x4:

2.2. Exemplos

UFABC - J2VELHA
Bem vindo ao Jogo!
Boa Sorte!

|
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|
Sua jogada:
Linha [0 - 3]: 0
Coluna [0 - 3]: 0
o |
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|
Jogada do Computador:
o | x |
|
---+---+---+--|
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|

Sua jogada:
Linha [0 - 3]: 1
Coluna [0 - 3]: 0

11

2.2. Exemplos

o | x |
|
---+---+---+--o |
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|
Jogada do Computador:
o | x | x |
---+---+---+--o |
|
|
---+---+---+--|
|
|
---+---+---+--|
|
|

Sua jogada:
Linha [0 - 3]: 2
Coluna [0 - 3]: 0
o | x | x |
---+---+---+--o |
|
|
---+---+---+--o |
|
|
---+---+---+--|
|
|
Jogada do Computador:
o | x | x |
---+---+---+--o |
|
|
---+---+---+--o |
|
|
---+---+---+--x |
|
|

12

2.2. Exemplos

Sua jogada:
Linha [0 - 3]: 1
Coluna [0 - 3]: 1
o | x | x |
---+---+---+--o | o |
|
---+---+---+--o |
|
|
---+---+---+--x |
|
|
Jogada do Computador:
o | x | x | x
---+---+---+--o | o |
|
---+---+---+--o |
|
|
---+---+---+--x |
|
|
Sua jogada:
Linha [0 - 3]: 2
Coluna [0 - 3]: 2
o | x | x | x
---+---+---+--o | o |
|
---+---+---+--o |
| o |
---+---+---+--x |
|
|
Jogada do Computador:
o | x | x | x
---+---+---+--o | o |
|
---+---+---+--o |
| o |
---+---+---+--x |
|
| x

13

2.2. Exemplos

Sua jogada:
Linha [0 - 3]: 1
Coluna [0 - 3]: 2
o | x | x | x
---+---+---+--o | o | o |
---+---+---+--o |
| o |
---+---+---+--x |
|
| x
Jogada do Computador:
o | x | x | x
---+---+---+--o | o | o | x
---+---+---+--o |
| o |
---+---+---+--x |
|
| x
Sua jogada:
Linha [0 - 3]: 2
Coluna [0 - 3]: 3
o | x | x | x
---+---+---+--o | o | o | x
---+---+---+--o |
| o | o
---+---+---+--x |
|
| x
Jogada do Computador:
o | x | x | x
---+---+---+--o | o | o | x
---+---+---+--o | x | o | o
---+---+---+--x |
|
| x

14

2.2. Exemplos

Sua jogada:
Linha [0 - 3]: 3
Coluna [0 - 3]: 2
o | x | x | x
---+---+---+--o | o | o | x
---+---+---+--o | x | o | o
---+---+---+--x |
| o | x
Jogada do Computador:
o | x | x | x
---+---+---+--o | o | o | x
---+---+---+--o | x | o | o
---+---+---+--x | x | o | x
Empate!

O codigo completo da implementacao encontra-se no Anexo I.

15

Anexo A
J2 Velha: C
odigos
A seguir tem-se a codificacao completa da aplicacao. Esta foi desenvolvida utilizando a
IDE NetBeans e JDK 1.6.

A.1

Classe Velha.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/

12

/
CLASSE VELHA CLASSE PRINCIPAL DA APLICACAO
/

15

// B i b l i o t e c a Scanner para c a p t u r a da j o g a d a do u s u
ario
import j a v a . u t i l . Scanner ;

18

public c l a s s Velha
{
/
CONSTANTES UTILIDAZAS
TAM > Tamanho do T a b u l e i r o
PROF > P r o f u n d i d a d e m
axima da b u s c a no MiniMax . Se PROF = 1 o
algoritmo
minimax i r
a b u s c a r a te um e s t a d o t e r m i n a l .
/

21

24

16

A.1. Classe Velha.java

17

s t a t i c int TAM = 3 , PROF = 1;


27

public s t a t i c void main ( S t r i n g [ ] a r g s )


{
Scanner e n t = new Scanner ( System . i n ) ;
// O b j e t o da C l a s s e T a b u l e i r o
T a b u l e i r o t = new T a b u l e i r o (TAM) ;
// O b j e t o da C l a s s e Minimax
MiniMax mm = new MiniMax (TAM, PROF) ;
System . out . p r i n t l n ( " UFABC - J2VELHA \nBem vindo ao Jogo !\ nBoa Sorte !\n\n
") ;
// Imprime o t a b u l e i r o na Tela
t . imprimir ( ) ;
do
{ // Captura j o g a d a do u s u
ario
int l , c ;
System . out . p r i n t f ( "Sua jogada :\r\ nLinha [0 - %d]: " , (TAM1) ) ;
l = ent . nextInt ( ) ;
System . out . p r i n t f ( " Coluna [0 - %d]: " , (TAM1) ) ;
c = ent . nextInt ( ) ;
// R e a l i z a j o g a d a do u s u
ario
t . fazerJogada ( l , c ) ;
t . imprimir ( ) ;
// V e r i f i c a s e n
a o e um e s t a d o t e r m i n a l
i f ( !mm. t e s t e t e r m i n a l ( t . t a b u l e i r o ) )
{
// A p l i c a o a l g o r i t m o minimax ao t a b u l e i r o
t . t a b u l e i r o = mm. d e c i s a o m i n i m a x ( t . t a b u l e i r o ) ;
System . out . p r i n t l n ( " Jogada do Computador :" ) ;
t . imprimir ( ) ;
}
} while ( !mm. t e s t e t e r m i n a l ( t . t a b u l e i r o ) ) ;
// V e r i f i c a o ganhador , ou um empate
i f (mm. ganhou ( t . t a b u l e i r o , 1 ) )
System . out . p r i n t l n ( "O computador ganhou !" ) ;
e l s e i f (mm. ganhou ( t . t a b u l e i r o , 1) )
System . out . p r i n t l n ( "Voc^
e ganhou !" ) ;
else
System . out . p r i n t l n ( " Empate !" ) ;
}

30

33

36

39

42

45

48

51

54

57

60

63

}


A.2. Classe Tabuleiro.java

A.2

18

Classe Tabuleiro.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/

12

/
CLASSE TABULEIRO REPRESENTA O TABULEIRO NO JOGO DA VELHA
/

15

18

21

24

27

30

33

36

39

42

45

public c l a s s T a b u l e i r o
{
/
Vetor de c o n v e r s
a o para i m p r e s s
a o na t e l a
/
s t a t i c char [ ] c o n v e r s a o = { o , , x } ;
/
M a t r i z do t a b u l e i r o
/
s t a t i c int [ ] [ ] t a b u l e i r o ;
/
Tamanho do t a b u l e i r o
/
int tam ;
/
D i v i s o r das l i n h a s na t e l a
/
String divisor ;
/
O me todo c o n s t r u t o r r e c e b e como parametro o tamanho do t a b u l e i r o
/
public T a b u l e i r o ( int tam )
{
t h i s . tam = tam ;
t a b u l e i r o = new int [ tam ] [ tam ] ;
divisor = gerarDivisor () ;
}
/

A.2. Classe Tabuleiro.java

19

Metodo i n v o c a d o para a j o g a d a do Jogador


/
public void f a z e r J o g a d a ( int l , int c )
{
i f ( t a b u l e i r o [ l ] [ c ] == 0 )
t a b u l e i r o [ l ] [ c ] = 1;
else
System . out . p r i n t l n ( " Posicao ja ocupada , perdeu a vez!" ) ;
}

48

51

54

/
Metodo para a i m p r e s s
a o do t a b u l e i r o na t e l a
/
public void i m p r i m i r ( )
{
f o r ( int i = 0 ; i < tam ; i ++)
{
f o r ( int j = 0 ; j < tam ; j ++)
{
System . out . p r i n t f ( " %c %c" , c o n v e r s a o [ t a b u l e i r o [ i ] [ j ] + 1 ] , j == (
tam1) ? : | ) ;
}
i f ( i != ( tam1) )
System . out . p r i n t l n ( d i v i s o r ) ;
}
System . out . p r i n t l n ( "\r\n" ) ;
}

57

60

63

66

69

72

/
Metodo para Gerar o D i v i s o r de Linhas . S e r v e para a u x i l i o da
visualizacao
g r a f i c a do t a b u l e i r o
/
public S t r i n g g e r a r D i v i s o r ( )
{
S t r i n g d = new S t r i n g ( "\r\n" ) ;

75

78

f o r ( int i = 0 ; i < ( tam 1 ) ; i ++)


{
d += " ---+" ;
}

81

84

d += " ---" ;
87

return d ;
}
90

}


A.3. Classe Sucessor.java

A.3

20

Classe Sucessor.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/
/
CLASSE SUCESSOR GERA OS ESTADOS DO JOGO DA VELHA
/

12

15

public c l a s s S u c e s s o r
{
int [ ] [ ] t a b u l e i r o ;
int u t i l i d a d e ;
/
Metodo C o n s t r u t o r
/
public S u c e s s o r ( int [ ] [ ] tab )
{
/
Cria um novo t a b u l e i r o , b a s e a d o no que f o i p a s s a d o
/
int tam = tab . l e n g t h ;
t a b u l e i r o = new int [ tam ] [ tam ] ;

18

21

24

27

f o r ( int i = 0 ; i < tam ; i ++)


f o r ( int j = 0 ; j < tam ; j ++)
t a b u l e i r o [ i ] [ j ] = tab [ i ] [ j ] ;

30

}
33

}


A.4. Classe Minimax.java

A.4

21

Classe Minimax.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/
/
CLASSE MINIMAX ALGORITMO DE BUSCA COMPETITIVA
/

12

15

import j a v a . u t i l . A r r a y L i s t ;
import j a v a . u t i l . C o l l e c t i o n s ;

18

public c l a s s MiniMax
{
/
armazenada u t i l i z a n d o
L i s t a de S u c e s s o r e s . Esta l i s t a Ac
um A r r a y L i s t
/
s t a t i c A r r a y L i s t <S u c e s s o r > s u c e s s o r e s = new A r r a y L i s t <S u c e s s o r > ( ) ;
int tam , maxProf ;

21

24

27

30

33

36

39

42

C o n s t r u t o r r e c e b e o tamanho do t a b u l e i r o e a p r o f u n d i d a d e mAxima
da
busca
/
public MiniMax ( int tam , int maxProf )
{
t h i s . tam = tam ;
i f ( maxProf > 0 )
t h i s . maxProf = maxProf ;
else
t h i s . maxProf = I n t e g e r .MAX VALUE; // Recebe o maior v a l o r de um
inteiro .
}
/
Metodo de d e c i s a o do MiniMax
/
public int [ ] [ ] d e c i s a o m i n i m a x ( int [ ] [ ] tab )
{

A.4. Classe Minimax.java

22

/
Limpa os s u c e s s o r e s
/
sucessores . clear () ;

45

48

Recebe a u t i l i d a d e mAxima
/
int v = valor max ( tab , true , 1 ) ;

51

P e r c o r r e a l i s t a em b u s c a do p r i m e i r o s u c e s s o r com u t i l i d a d e mAxima
/
for ( Sucessor s : s u c e s s o r e s )
i f ( s . u t i l i d a d e == v )
return s . t a b u l e i r o ;

54

57

60

return tab ;
}
63

66

69

public int valor max ( int [ ] [ ] tab , boolean prim , int p r o f )


{
/

Se a p r o f u n d i d a d e f o r maior que a mAxima


ou o j o g o acabou , r e t o r n a
a
utilidade
/
i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( tab ) )
return u t i l i d a d e ( tab ) ;

72

75

78

81

84

87

/
A t r i b u i o menor v a l o r de um i n t e i r o para v ( i n f i n i t o )
/
int v = I n t e g e r . MIN VALUE ;
/
P e r c o r r e os n
o s s u c e s s o r e s de MAX
/
f o r ( S u c e s s o r s : g e r a r s u c e s s o r e s ( tab , 1 ) )
{
v = Math . max( v , v a l o r m i n ( s . t a b u l e i r o , p r o f ) ) ;
s . utilidade = v;
/
Se forem os p r i m e i r o s s u c e s s o r e s , a d i c i o n a na l i s t a de s u c e s s o r e s
...
/
i f ( prim )

A.4. Classe Minimax.java

23

s u c e s s o r e s . add ( s ) ;
}

90

return v ;
93

96

99

102

}
public int v a l o r m i n ( int [ ] [ ] tab , int p r o f )
{
/
Se a p r o f u n d i d a d e f o r maior que a m
axima ou o j o g o acabou , r e t o r n a a
utilidade
/
i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( tab ) )
return u t i l i d a d e ( tab ) ;
/
A t r i b u i +I n f i n i t o
/
int v = I n t e g e r .MAX VALUE;

105

108

/
P e r c o r r e os n
o s s u c e s s o r e s de MIN
/
f o r ( S u c e s s o r s : g e r a r s u c e s s o r e s ( tab , 1) )
{
v = Math . min ( v , valor max ( s . t a b u l e i r o , f a l s e , p r o f ) ) ;
s . utilidade = v;
}

111

114

117

return v ;
}
120

123

126

129

132

135

/
Gera os s u c e s s o r e s de um j o g a d o r , a p a r t i r do e s t a d o a t u a l
/
public A r r a y L i s t <S u c e s s o r > g e r a r s u c e s s o r e s ( int [ ] [ ] tab , int v )
{
A r r a y L i s t <S u c e s s o r > s u c = new A r r a y L i s t <S u c e s s o r > ( ) ;
f o r ( int i = 0 ; i < tam ; i ++)
{
f o r ( int j = 0 ; j < tam ; j ++)
{
i f ( tab [ i ] [ j ] == 0 )
{
tab [ i ] [ j ] = v ;
s u c . add (new S u c e s s o r ( tab ) ) ;
tab [ i ] [ j ] = 0 ;

A.4. Classe Minimax.java

24

}
}
}

138

return s u c ;
141

144

147

}
/
V e r i f i c a s e chegou em algum e s t a d o t e r m i n a l e c a s o a f i r m a t i v o f i n a l i z a
o jogo
/
public boolean t e s t e t e r m i n a l ( int [ ] [ ] tab )
{
return ( ganhou ( tab , 1 ) | | ganhou ( tab , 1) | | semEspaco ( tab ) ) ;
}

150

153

156

159

162

165

168

171

/
Retorna a u t i l i d a d e
/
public int u t i l i d a d e ( int [ ] [ ] tab )
{
i f ( ganhou ( tab , 1 ) )
return 1 ;
e l s e i f ( ganhou ( tab , 1) )
return 1;
else
return 0 ;
}
/
V e r i f i c a s e j o g a d o r ganhou
/
public boolean ganhou ( int [ ] [ ] tab , int v )
{
f o r ( int i = 0 ; i < tam ; i ++)
i f ( ganhouLinha ( tab , i , v ) | | ganhouColuna ( tab , i , v ) )
return true ;
i f ( ganhouDiag1 ( tab , v ) | | ganhouDiag2 ( tab , v ) )
return true ;

174

return f a l s e ;
177

180

/
Ganhou na s e q u e n c i a de l i n h a s ?
/

A.4. Classe Minimax.java

186

private boolean ganhouLinha ( int [ ] [ ] tab , int l , int v )


{
f o r ( int i = 0 ; i < tam ; i ++)
i f ( tab [ l ] [ i ] != v )
return f a l s e ;

189

183

return true ;

198

/
Ganhou na s e q u e n c i a de c o l u n a s ?
/
private boolean ganhouColuna ( int [ ] [ ] tab , int c , int v )
{
f o r ( int i = 0 ; i < tam ; i ++)
i f ( tab [ i ] [ c ] != v )
return f a l s e ;

201

192

195

return true ;

210

/
Ganhou na s e q u e n c i a d i a g o n a l p r i n c i p a l ?
/
private boolean ganhouDiag1 ( int [ ] [ ] tab , int v )
{
f o r ( int i = 0 ; i < tam ; i ++)
i f ( tab [ i ] [ i ] != v )
return f a l s e ;

213

204

207

return true ;

216

219

222

/
Ganhou na s e q u e n c i a d i a g o n a l s e c u n d a r i a ?
/
private boolean ganhouDiag2 ( int [ ] [ ] tab , int v )
{
f o r ( int i = 0 ; i < tam ; i ++)
i f ( tab [ ( tam1) i ] [ i ] != v )
return f a l s e ;
return true ;

225

228

/
Nao tem mais e s p a c o s r e s t a n t e s no t a b u l e i r o . .

25

A.4. Classe Minimax.java

26

/
public boolean semEspaco ( int [ ] [ ] tab )
{
f o r ( int l = 0 ; l < tam ; l ++)
f o r ( int c = 0 ; c < tam ; c++)
i f ( tab [ l ] [ c ] == 0 )
return f a l s e ;

231

234

return true ;

237

}
}


Anexo B
J2 Velha: Novas Funcionalidades
A seguir tem-se a codificacao completa de novas funcionalidades do J2 Velha. O programa agora realiza o algoritmo minimax juntamente com o mecanismo de Poda Alfa-Beta
(Alpha-beta pruning). Alem disto, existe a possibilidade de jogar com elementos de acaso,
isto e, as pecas podem deslizar em determinada jogada. Todo o codigo esta comentado
para que estas funcionalidades sejam entendidas mais facilmente.

B.1

Classe Velha.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/

import j a v a . u t i l . Scanner ;
12

15

public c l a s s Velha
{
/
Pec as e s c o r r e g a d i a s ?
/
s t a t i c boolean ESCORREGA;

18

21

public s t a t i c void main ( S t r i n g [ ] a r g s )


{
Scanner e n t = new Scanner ( System . i n ) ;

27

B.1. Classe Velha.java

24

27

30

33

28

System . out . p r i n t ( "Voc^


e deseja jogar com pe
c as escorregadias ? [s/n]: " )
;
String esc = ent . nextLine ( ) ;
i f ( e s c . charAt ( 0 ) == s | | e s c . charAt ( 0 ) == S )
{
ESCORREGA = true ;
System . out . p r i n t l n ( " Pe
c as escorregadias ativadas ." ) ;
}
else
{
ESCORREGA = f a l s e ;
System . out . p r i n t l n ( " Pe
c as escorregadias desativadas ." ) ;
}

36

39

42

45

48

51

54

57

T a b u l e i r o t = new T a b u l e i r o (ESCORREGA) ;
MiniMax mm = new MiniMax (ESCORREGA) ;
t . imprimir ( ) ;

do
{
int l , c ;
System . out . p r i n t f ( "Sua jogada :\r\ nLinha [0 - 3]: " ) ;
l = ent . nextInt ( ) ;
System . out . p r i n t f ( " Coluna [0 - 3]: " ) ;
c = ent . nextInt ( ) ;
t . fazerJogada ( l , c ) ;
t . imprimir ( ) ;
i f ( !mm. t e s t e t e r m i n a l ( t . t a b u l e i r o ) )
{
long time = System . c u r r e n t T i m e M i l l i s ( ) ;
t . t a b u l e i r o = mm. d e c i s a o m i n i m a x ( t . t a b u l e i r o ) ;
time = System . c u r r e n t T i m e M i l l i s ( ) time ;
System . out . p r i n t l n ( " Jogada do Computador (" + time + " ms):" ) ;
t . imprimir ( ) ;
}
} while ( !mm. t e s t e t e r m i n a l ( t . t a b u l e i r o ) ) ;

60

63

66

int u = mm. u t i l i d a d e ( t .
i f (u < 0)
System . out . p r i n t l n
e l s e i f ( u == 0 )
System . out . p r i n t l n
else
System . out . p r i n t l n

tabuleiro ) ;
( " Parabens ! Voce ganhou ..." ) ;
( " Empatou !" ) ;
( "Voce realmente e pior que um computador ..." ) ;

B.1. Classe Velha.java

29

System . out . p r i n t l n ( "Voc^


e marcou " + mm. co ntaP onto s ( t . t a b u l e i r o , 1) + "
pontos ." ) ;
System . out . p r i n t l n ( "O computador marcou " + mm. co nta Ponto s ( t . t a b u l e i r o ,
1 ) + " pontos ." ) ;

69

}
72

}


B.2. Classe Tabuleiro.java

B.2

Classe Tabuleiro.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/ /

import j a v a . u t i l . A r r a y L i s t ;
12

15

18

21

24

27

30

33

public c l a s s T a b u l e i r o
{
/
Vetor de c o n v e r s
a o para i m p r e s s
a o na t e l a
/
s t a t i c char [ ] c o n v e r s a o = { o , , x } ;
/
M a t r i z do t a b u l e i r o
/
s t a t i c int [ ] [ ] t a b u l e i r o ;
/

Pe Aas
Escorregadias ?
/
boolean e s c o r r e g a ;
/
Construtor

e n t r a d a : tamanho do t a b u l e i r o
/
public T a b u l e i r o ( boolean e s c o r r e g a )
{
this . escorrega = escorrega ;
t a b u l e i r o = new int [ 4 ] [ 4 ] ;
}

36

39

42

45

/
Metodo i n v o c a d o para a j o g a d a do Jogador !
/
public void f a z e r J o g a d a ( int l , int c )
{
i f ( t a b u l e i r o [ l ] [ c ] == 0 )
{
/
Se e s t i v e r j o g a n d o com p e c a s e s c o r r e g a d i a s . . .

30

B.2. Classe Tabuleiro.java

31

/
if ( escorrega )
{
/
Ao

V e r i f i c a os v i z i n h o s l i v r e da posi A
..
/
A r r a y L i s t <int [] > v i z i n h o s = v i z i n h o s L i v r e s ( l , c ) ;

48

51

/
Se h o u ve r ao menos um v i z i n h o l i v r e , tem 20% de chance da pec a
escorregar . .
/
i f ( v i z i n h o s . s i z e ( ) > 0 && Math . random ( ) <= 0 . 2 )
{
/
E s c o l h e um dos v i z i n h o s a l e a t o r i a m e n t e . .
/
int x = ( int ) ( Math . random ( ) v i z i n h o s . s i z e ( ) ) ;
/
Transforma as c o o r d e n a d a s a t u a i s nas c o o r d e n a d a s do v i z i n h o
escolhido . .
/
l = vizinhos . get (x) [ 0 ] ;
c = vizinhos . get (x) [ 1 ] ;
System . out . p r i n t l n ( "A pe
c a escorregou e caiu na posi
c~
ao : " + l +
", " + c ) ;
}

54

57

60

63

66

69

}
t a b u l e i r o [ l ] [ c ] = 1;

72

}
else
System . out . p r i n t l n ( " Posi
c~
a o j
a ocupada , perdeu a vez!" ) ;

75

}
78

81

84

87

90

/
Metodo que v e r i f i c a s e h
a v i z i n h o s l i v r e s , c o n s i d e r a n d o as d i a g o n a i s
...
/
public A r r a y L i s t <int [] > v i z i n h o s L i v r e s ( int l , int c )
{
A r r a y L i s t <int [] > v i z i n h o s = new A r r a y L i s t <int [] > ( ) ;
/
V i z i n h o s da l i n h a a n t e r i o r , s e h o u ve r . . .
/
i f ( l > 0)
{

B.2. Classe Tabuleiro.java

93

i f ( c > 0)
i f ( t a b u l e i r o [ l 1 ] [ c 1] == 0 )
v i z i n h o s . add (new int [ ] { l 1, c 1}) ;

96

i f ( t a b u l e i r o [ l 1 ] [ c ] == 0 )
v i z i n h o s . add (new int [ ] { l 1, c } ) ;
i f ( c < 3)
i f ( t a b u l e i r o [ l 1 ] [ c +1] == 0 )
v i z i n h o s . add (new int [ ] { l 1, c +1}) ;

99

}
102

/
V i z i n h o s da mesma l i n h a . . .
/
i f ( c > 0)
i f ( t a b u l e i r o [ l ] [ c 1] == 0 )
v i z i n h o s . add (new int [ ] { l , c 1}) ;

105

108

i f ( c < 3)
i f ( t a b u l e i r o [ l ] [ c +1] == 0 )
v i z i n h o s . add (new int [ ] { l , c +1}) ;

111

/
V i z i n h o s da l i n h a p o s t e r i o r , s e h o u ve r . . .
/
i f ( l < 3)
{
i f ( c > 0)
i f ( t a b u l e i r o [ l + 1 ] [ c 1] == 0 )
v i z i n h o s . add (new int [ ] { l +1, c 1}) ;

114

117

120

123

i f ( t a b u l e i r o [ l + 1 ] [ c ] == 0 )
v i z i n h o s . add (new int [ ] { l +1, c } ) ;

126

i f ( c < 3)
i f ( t a b u l e i r o [ l + 1 ] [ c +1] == 0 )
v i z i n h o s . add (new int [ ] { l +1, c +1}) ;
}

129

return v i z i n h o s ;
132

135

}
/

Metodo para a impress Ao


do t a b u l e i r o na t e l a
/
public void i m p r i m i r ( )

32

B.2. Classe Tabuleiro.java

33

138

f o r ( int i = 0 ; i < 4 ; i ++)


{
f o r ( int j = 0 ; j < 4 ; j ++)
{
System . out . p r i n t f ( " %c %c" , c o n v e r s a o [ t a b u l e i r o [ i ] [ j ] + 1 ] , j == 3
? : | ) ;
}
i f ( i != ( 3 ) )
System . out . p r i n t l n ( "\r\n---+---+---+---" ) ;
}
System . out . p r i n t l n ( "\r\n" ) ;

141

144

147

}
150

}


B.3. Classe Sucessor.java

B.3

12

34

Classe Sucessor.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/
public c l a s s S u c e s s o r
{
int [ ] [ ] t a b u l e i r o ;
int u t i l i d a d e ;
/
Construtor
/
public S u c e s s o r ( int [ ] [ ] tab )
{
/
Cria um novo t a b u l e i r o , b a s e a d o no que f o i p a s s a d o
/
int tam = tab . l e n g t h ;
t a b u l e i r o = new int [ tam ] [ tam ] ;

15

18

21

24

f o r ( int i = 0 ; i < tam ; i ++)


f o r ( int j = 0 ; j < tam ; j ++)
t a b u l e i r o [ i ] [ j ] = tab [ i ] [ j ] ;

27

}
}


B.4. Classe Minimax.java

B.4

35

Classe Minimax.java


/
UFABC U n v e r s i d a d e F e d e r a l do ABC
MC 3303 I n t e l i g e n c i a A r t i f i c i a l
P r o f e s s o r Jer
o nimo P e l l e g r i n i
Alunos :

Andre F i l i p e de Moraes B a t i s t a

L us Fernando de O l i v e i r a J a c i n t h o
/

import j a v a . u t i l . A r r a y L i s t ;
12

15

18

21

24

27

public c l a s s MiniMax
{
/
L i s t a dos n
os s u c e s s o r e s
/
s t a t i c A r r a y L i s t <S u c e s s o r > s u c e s s o r e s = new A r r a y L i s t <S u c e s s o r > ( ) ;
/
Jogar com p e c a s e s c o r r e g a d i a s ?
/
boolean e s c o r r e g a ;
/
Construtor
/
public MiniMax ( boolean e s c o r r e g a )
{
this . escorrega = escorrega ;
}

30

33

36

39

42

45

/
Metodo de d e c i s
a o do MiniMax
/
public int [ ] [ ] d e c i s a o m i n i m a x ( int [ ] [ ] tab )
{
/
Limpa os s u c e s s o r e s
/
sucessores . clear () ;
/
Recebe a u t i l i d a d e m
axima
/
int v = valor max ( tab , I n t e g e r . MIN VALUE, I n t e g e r .MAX VALUE, true ) ;

B.4. Classe Minimax.java

36

/
P e r c o r r e a l i s t a em b u s c a do p r i m e i r o s u c e s s o r com u t i l i d a d e m
axima
/
for ( Sucessor s : s u c e s s o r e s )
i f ( s . u t i l i d a d e == v )
return s . t a b u l e i r o ;

48

51

return tab ;
54

57

60

63

66

}
public int valor max ( int [ ] [ ] tab , int a l f a , int beta , boolean prim )
{
/
Se a p r o f u n d i d a d e f o r maior que a m
axima ou o j o g o acabou , r e t o r n a a
utilidade
/
i f ( t e s t e t e r m i n a l ( tab ) )
return u t i l i d a d e ( tab ) ;
/
Atribui I n f i n i t o
/
int v = I n t e g e r . MIN VALUE ;

69

72

75

78

81

84

87

90

/
P e r c o r r e os n
o s s u c e s s o r e s de MAX
/
f o r ( S u c e s s o r s : g e r a r s u c e s s o r e s ( tab , 1 ) )
{
v = Math . max( v , v a l o r m i n ( s . t a b u l e i r o , a l f a , b e t a ) ) ;
s . utilidade = v;
/
Se forem os p r i m e i r o s s u c e s s o r e s , a d i c i o n a na l i s t a de s u c e s s o r e s
...
/
i f ( prim )
s u c e s s o r e s . add ( s ) ;
/
Poda Beta Se o v a l o r f o r maior que b e t a , r e t o r n a o v a l o r . .
/
i f ( v >= b e t a )
return v ;
/
Se o v a l o r f o r maior que Alfa , A l f a r e c e b e o v a l o r . . .

B.4. Classe Minimax.java

37

/
a l f a = Math . max( a l f a , v ) ;

93

}
return v ;

96

}
99

102

105

public int v a l o r m i n ( int [ ] [ ] tab , int a l f a , int b e t a )


{
/
Se a p r o f u n d i d a d e f o r maior que a m
axima ou o j o g o acabou , r e t o r n a a
utilidade
/
i f ( t e s t e t e r m i n a l ( tab ) )
return u t i l i d a d e ( tab ) ;
/
A t r i b u i +I n f i n i t o
/
int v = I n t e g e r .MAX VALUE;

108

111

/
P e r c o r r e os n
o s s u c e s s o r e s de MIN
/
f o r ( S u c e s s o r s : g e r a r s u c e s s o r e s ( tab , 1) )
{
v = Math . min ( v , valor max ( s . t a b u l e i r o , a l f a , beta , f a l s e ) ) ;
s . utilidade = v;

114

117

120

/
Poda A l f a Se o v a l o r f o r menor que a l f a , r e t o r n a o v a l o r . . .
/
i f ( v <= a l f a )
return v ;

123

126

/
Se v a l o r menor que Beta , Beta o r e c e b e . . .
/
b e t a = Math . min ( beta , v ) ;

129

}
132

return v ;
}
135

138

/
Gera os s u c e s s o r e s de um j o g a d o r , a p a r t i r do e s t a d o a t u a l
/

B.4. Classe Minimax.java

141

144

147

150

153

156

public A r r a y L i s t <S u c e s s o r > g e r a r s u c e s s o r e s ( int [ ] [ ] tab , int v )


{
A r r a y L i s t <S u c e s s o r > s u c = new A r r a y L i s t <S u c e s s o r > ( ) ;
f o r ( int i = 0 ; i < 4 ; i ++)
{
f o r ( int j = 0 ; j < 4 ; j ++)
{
i f ( tab [ i ] [ j ] == 0 )
{
/
Se e s t i v e r j o g a n d o com p e c a s e s c o r r e g a d i a s . . .
/
if ( escorrega )
{
/
V e r i f i c a os v i z i n h o s l i v r e da p o s i c
ao . .
/
A r r a y L i s t <int [] > v i z i n h o s = v i z i n h o s L i v r e s ( tab , i , j ) ;
/
Se h o u ve r ao menos um v i z i n h o l i v r e , tem 20% de chance da

pe Aa
escorregar . .
/
i f ( v i z i n h o s . s i z e ( ) > 0 && Math . random ( ) <= 0 . 2 )
{
/
E s c o l h e um dos v i z i n h o s a l e a t o r i a m e n t e . .
/
int x = ( int ) ( Math . random ( ) v i z i n h o s . s i z e ( ) ) ;
/
Transforma as c o o r d e n a d a s a t u a i s nas c o o r d e n a d a s do
vizinho
escolhido . .
/
i = vizinhos . get (x) [ 0 ] ;
j = vizinhos . get (x) [ 1 ] ;
}

159

162

165

168

171

174

177

tab [ i ] [ j ] = v ;
s u c . add (new S u c e s s o r ( tab ) ) ;
tab [ i ] [ j ] = 0 ;
}
}

180

}
183

38

return s u c ;

B.4. Classe Minimax.java

39

}
186

189

/
Metodo que v e r i f i c a s e h
a v i z i n h o s l i v r e s , c o n s i d e r a n d o as d i a g o n a i s
...
/
public A r r a y L i s t <int [] > v i z i n h o s L i v r e s ( int [ ] [ ] t a b u l e i r o , int l , int c )
{
A r r a y L i s t <int [] > v i z i n h o s = new A r r a y L i s t <int [] > ( ) ;

192

195

198

/
V i z i n h o s da l i n h a a n t e r i o r , s e h o u ve r . . .
/
i f ( l > 0)
{
i f ( c > 0)
i f ( t a b u l e i r o [ l 1 ] [ c 1] == 0 )
v i z i n h o s . add (new int [ ] { l 1, c 1}) ;

201

i f ( t a b u l e i r o [ l 1 ] [ c ] == 0 )
v i z i n h o s . add (new int [ ] { l 1, c } ) ;
204

i f ( c < 3)
i f ( t a b u l e i r o [ l 1 ] [ c +1] == 0 )
v i z i n h o s . add (new int [ ] { l 1, c +1}) ;

207

}
210

213

/
V i z i n h o s da mesma l i n h a . . .
/
i f ( c > 0)
i f ( t a b u l e i r o [ l ] [ c 1] == 0 )
v i z i n h o s . add (new int [ ] { l , c 1}) ;

216

219

222

225

228

i f ( c < 3)
i f ( t a b u l e i r o [ l ] [ c +1] == 0 )
v i z i n h o s . add (new int [ ] { l , c +1}) ;
/
V i z i n h o s da l i n h a p o s t e r i o r , s e h o u ve r . . .
/
i f ( l < 3)
{
i f ( c > 0)
i f ( t a b u l e i r o [ l + 1 ] [ c 1] == 0 )
v i z i n h o s . add (new int [ ] { l +1, c 1}) ;

B.4. Classe Minimax.java

40

i f ( t a b u l e i r o [ l + 1 ] [ c ] == 0 )
v i z i n h o s . add (new int [ ] { l +1, c } ) ;

231

i f ( c < 3)
i f ( t a b u l e i r o [ l + 1 ] [ c +1] == 0 )
v i z i n h o s . add (new int [ ] { l +1, c +1}) ;

234

}
237

return v i z i n h o s ;
}
240

243

246

/
Fim de j o g o ?
O j o g o s
o termina s e n
a o h o u v er mais e s p a c o para j o g a d a s . . .
/
public boolean t e s t e t e r m i n a l ( int [ ] [ ] tab )
{
return ( semEspaco ( tab ) ) ;
}

249

252

255

/
Retorna a u t i l i d a d e . . .
Aqui a u t i l i d a d e c o n s i d e r a d a e a d i f e r e n c a de p o n t o s e n t r e o
computador e
o j o g a d o r , o computador n
a o d e s e j a apenas vencer , mas tambem h u m i l h a r
=P
/
public int u t i l i d a d e ( int [ ] [ ] tab )
{
int pc , u s r ;

258

pc = co ntaPo nto s ( tab , 1 ) ;


u s r = co nta Ponto s ( tab , 1) ;
261

return ( pcu s r ) ;
}
264

267

270

273

/
V e r i f i c a s e j o g a d o r ganhou
/
public int co ntaP onto s ( int [ ] [ ] tab , int v )
{
int p o n t o s = 0 ;
f o r ( int i = 0 ; i < 4 ; i ++)
{
p o n t o s += c o nta L inh a ( tab , i , v ) ;

B.4. Classe Minimax.java

41

p o n t o s += contaColuna ( tab , i , v ) ;
276

279

p o n t o s += contaDiag1 ( tab , v ) ;
p o n t o s += contaDiag2 ( tab , v ) ;
return p o n t o s ;

282

285

288

291

294

}
/
Pontos na s e q u e n c i a de l i n h a s ?

Metodo de contagem b i n
a r i a . . um b y t e e d e s n e c e s s a
rio , precisaria
apenas
de 4 b i t s . . Basicamente , para cada p o s i c
a o a t r i b u i s e o v a l o r 1 na
mesma
p o s i c a
o do b y t e , i n d i c a n d o que a l i e d e l e . No f i n a l checamos as 3
p o s s i b i l i d a d e s de marcar pontos , 4 p o s i c
o e s v i z i n h a s ( 1 1 1 1 ) ou 3
posicoes
v i z i n h a s (0111 ou 1110) . Qualquer o u t r a combinac
a o t e r i a menos do que
3 p o s i c
o e s v i z i n h a s e n
a o marcariam p o n t o s .
/
private int c o nt a L in ha ( int [ ] [ ] tab , int l , int v )
{
byte soma = 0 ;

297

f o r ( int i = 0 ; i < 4 ; i ++)


i f ( tab [ l ] [ i ] == v )
soma += ( 1 << i ) ;

300

i f ( soma == 1 5 ) // 1111
return 3 ;
e l s e i f ( ( soma == 7 ) | |
return 1 ;
else
return 0 ;

303

306

( soma == 1 4 ) ) // 0111 v 1110

}
309

312

315

318

/
Pontos na s e q u e n c i a de c o l u n a s ?
/
private int contaColuna ( int [ ] [ ] tab , int c , int v )
{
int soma = 0 ;
f o r ( int i = 0 ; i < 4 ; i ++)
i f ( tab [ i ] [ c ] == v )

B.4. Classe Minimax.java

42

soma += ( 1 << i ) ;
i f ( soma == 1 5 ) // 1111
return 3 ;
e l s e i f ( ( soma == 7 ) | | ( soma == 1 4 ) ) // 0111 v 1110
return 1 ;
else
return 0 ;

321

324

327

330

333

}
/
Ganhou na s e q u e n c i a d i a g o n a l ?
/
private int contaDiag1 ( int [ ] [ ] tab , int v )
{
int soma = 0 ;
int p e x t r a = 0 ;

336

f o r ( int i = 0 ; i < 4 ; i ++)


i f ( tab [ i ] [ i ] == v )
soma += ( 1 << i ) ;

339

/
Nas duas d i a g o n a i s a s e g u i r s
o e p o s s v e l formar s e q u e n c i a s de 3 ,
podendos e a d i c i o n a r e n t a o apenas 1 ponto . . . .
/
i f ( tab [ 1 ] [ 0 ] == v && tab [ 2 ] [ 1 ] == v && tab [ 3 ] [ 2 ] == v )
p e x t r a ++;
i f ( tab [ 0 ] [ 1 ] == v && tab [ 1 ] [ 2 ] == v && tab [ 2 ] [ 3 ] == v )
p e x t r a ++;

342

345

348

i f ( soma == 1 5 )
return 3 + p e x t r a ;
e l s e i f ( ( soma == 7 ) | | ( soma == 1 4 ) )
return 1 + p e x t r a ;
else
return 0 + p e x t r a ;

351

354

}
357

360

/
Ganhou na s e q u e n c i a d i a g o n a l ?
/

363

private int contaDiag2 ( int [ ] [ ] tab , int v )


int soma = 0 ;
int p e x t r a = 0 ;

B.4. Classe Minimax.java

43

366

f o r ( int i = 0 ; i < 4 ; i ++)


i f ( tab [3 i ] [ i ] == v )
soma += ( 1 << i ) ;

369

/
Nas duas d i a g o n a i s a s e g u i r s
o e p o s s v e l formar s e q u e n c i a s de 3 ,
podendos e a d i c i o n a r e n t a o apenas 1 ponto . . . .
/
i f ( tab [ 0 ] [ 2 ] == v && tab [ 1 ] [ 1 ] == v && tab [ 2 ] [ 0 ] == v )
p e x t r a ++;
i f ( tab [ 1 ] [ 3 ] == v && tab [ 2 ] [ 2 ] == v && tab [ 3 ] [ 1 ] == v )
p e x t r a ++;

372

375

378

i f ( soma == 1 5 )
return 3 + p e x t r a ;
e l s e i f ( ( soma == 7 ) | | ( soma == 1 4 ) )
return 1 + p e x t r a ;
else
return 0 + p e x t r a ;

381

384

}
387

396

/
N
ao tem mais e s p a c o s r e s t a n t e s no t a b u l e i r o . .
/
public boolean semEspaco ( int [ ] [ ] tab )
{
f o r ( int l = 0 ; l < 4 ; l ++)
f o r ( int c = 0 ; c < 4 ; c++)
i f ( tab [ l ] [ c ] == 0 )
return f a l s e ;

399

390

393

return true ;
}