J2 Velha
Uma Implementa¸c˜
ao 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
Prof
oJerˆ
onimo Pellegrini
1
Jogos em IA
1
1.1
Minimax - Algoritmo de Busca Competitiva . . . .
1
2
J2 Velha: Uma Abordagem Java ao Jogo da Velha
4
2.1
J2 Velha . . . .
4
2.2
Exemplos
. . . .
8
Anexos
16
A J2 Velha: C´
odigos
16
A.1 Classe Velha.java . . . .
16
A.2 Classe Tabuleiro.java
. . . .
18
A.3 Classe Sucessor.java . . . .
20
A.4 Classe Minimax.java . . . .
21
B J2 Velha: Novas Funcionalidades
27
B.1 Classe Velha.java . . . .
27
B.2 Classe Tabuleiro.java
. . . .
30
B.3 Classe Sucessor.java . . . .
34
B.4 Classe Minimax.java . . . .
35
Jogos em IA
Para a maioria das pessoas o termo jogo ´
e considerado como um passatempo do dia-a-dia.
Para as crian¸cas 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 estrat´
egias que lhes dˆ
eem vantagens sobre os advers´
arios. Ou
seja, o resultado do jogo ´
e determinado pelas estrat´
egias utilizadas pelos jogadores. O
ramo da Matem´
atica 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 s˜
ao uma das ´
areas mais antigas desenvolvidas em Inteligˆ
encia
Artificial (IA). Em 1950, desde que os computadores se tornaram program´
aveis, o primeiro
jogo de xadrez foi criado por Claude Shannon e por Alan Turing. Desde ent˜
ao diversos
progressos ocorreram nesta ´
area, de tal forma que os sistemas atuais s˜
ao capazes de
rivalizar e ganhar de um dos melhores jogadores de xadrez da hist´
oria, 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
c´
odigo de programa¸c˜
ao ´
e em linguagem C e ´
e executado no sistema operacional AIX. O
resultado ´
e uma m´
aquina escal´
avel capaz de calcular entre 100 e 200 bilh˜
oes de jogadas
em aproximadamente 3 minutos. No primeiro confronto entre os dois, a vit´
oria foi de
Kasparov. At´
e que em 1997 a IBM desdobrou-se em constantes desenvolvimentos e
atu-aliza¸c˜
oes de modo a melhorar o desempenho do Deep Blue. O resultado de tanto esfor¸co
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 situa¸c˜
oes de coopera¸c˜
ao e
compe-ti¸c˜
ao. Um ambiente competitivo ´
e aquele em que as metas dos agentes est˜
ao em constante
Figura 1.1: Cena de um Disputa de Kasparov versus DeepBlue
.
conflito. Para tais situa¸c˜
oes ´
e preciso desenvolver t´
ecnicas de busca competitiva entre os
agentes. ´
E neste ponto que a teoria dos jogos pode auxiliar na constru¸c˜
ao de um agente
racional.
Em IA os jogos normalmente s˜
ao de um tipo bastante especializados - algumas vezes
denominados determin´ısticos de revezamento de dois jogadores de soma zero com
infor-ma¸c˜
oes perfeitas. Isto representa ambiente determin´ısticos completamente observ´
aveis em
que existem dois agentes cujas a¸c˜
oes devem se alternar e em que os valores de utilidade no
fim do jogo s˜
ao sempre iguais e opostos. Por exemplo, se um jogador ganha um jogo de
xadrez (+1), o outro jogador necessariamente perde (-1). Essa oposi¸c˜
ao entre as fun¸c˜
oes
de utilidades dos agentes que gera a situa¸c˜
ao de competi¸c˜
ao.
O MiniMax ´
e um algoritmo de busca competitiva que seleciona a melhor a¸c˜
ao a ser
feita em uma situa¸c˜
ao ou em um jogo, onde dois jogadores se empenham em alcan¸car
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 princ´ıpio de que em cada jogada, o jogador ir´
a escolher o melhor movimento poss´ıvel.
A ´
arvore de jogo consiste de todas as jogadas poss´ıveis para o jogador atual como n´
os
filhos da raiz, e todas as jogadas dispon´ıveis para o pr´
oximo jogador como filhas destes n´
os
e assim por diante, at´
e o n´ıvel que se desejar. Cada ramifica¸c˜
ao da ´
arvore representa um
movimento que o jogador pode fazer em tal momento do jogo. Uma busca mais profunda
na ´
arvore fornece mais informa¸c˜
oes sobre as poss´ıveis vantagens ou armadilhas e portanto
resulta em uma jogada melhor.
O MiniMax faz uma busca que determina todas as poss´ıveis continua¸c˜
oes do jogo at´
e
o n´ıvel desejado, avaliando e atribuindo um valor a cada movimento poss´ıvel. A busca
ent˜
ao retorna na ´
arvore de jogo alternando entre escolher o valor mais alto e o valor mais
baixo entre os valores da jogadas em um n´ıvel. O m´
etodo de busca consiste na id´
eia de
maximizar a utilidade supondo que o advers´
ario vai tentar minimiz´
a-la. Em termos de
busca, ´
e realiza uma busca cega em profundidade, o agente ´
e o MAX e seu advers´
ario ´
e o
MIN.
Algoritmo 1 MINIMAX
fun¸
c˜
ao DECIS ˜
AO-MINIMAX(estado) retorna uma a¸c˜
ao
entradas: estado, estado corrente no jogo
v ← VALOR-MAX(estado)
retornar a a¸c˜
ao em SUCESSORES(estado) com valor v
fun¸
c˜
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) fa¸
ca
v ← MAX(v, VALOR-MIN(s))
retornar v
fun¸
c˜
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) fa¸
ca
v ← MAX(v, VALOR-MAX(s))
retornar v
Se fosse o caso de se tratar de uma busca normal, bastava percorrer-se a ´
arvore at´
e
aos n´
os terminais e escolher o caminho que levasse ao n´
o com maior valor de utilidade.
Mas n˜
ao ´
e assim, visto existir outro jogador. Assim, ´
e necess´
ario, escolher a partir de
cada n´
o filho, o menor valor de utilidade, e copia-lo para o n´
o pai, recursivamente at´
e ao
n´
o inicial. Este ´
e o algoritmo MiniMax. Isto deve-se ao fato, do jogador MIN tentar
minimizar o ganho do jogador MAX, pois ele tentar´
a escolher uma jogada, dentro das
poss´ıveis, que dˆ
e menos pontos ao jogador advers´
ario. Na Caixa de Algoritmo 1 tem-se o
algoritmo MiniMax.
No Cap´ıtulo que segue tem-se uma implementa¸c˜
ao do Jogo da Velha utilizando a
linguagem Java e o algoritmo MiniMax.
J2 Velha: Uma Abordagem Java ao
Jogo da Velha
Conhecido tamb´
em como “Jogo do Galo”, ou “Tic Tac Toe”, o jogo da velha ´
e um jogo
extremamente simples, que n˜
ao 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 n˜
ao terem mais condi¸c˜
oes de bordar em raz˜
ao
da fraqueza de suas vistas, jogavam este jogo simples.
O jogo da velha ´
e um dos exemplos mais cl´
assicos de utiliza¸c˜
ao do algoritmo Minimax.
O estado inicial e os movimentos v´
alidos para cada lado definem a ´
arvore do jogo
corres-pondente 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 poss´ıveis. O jogo se alterna entre
a coloca¸c˜
ao de um X por MAX e a coloca¸c˜
ao de um O por MIN at´
e que se alcance n´
os
de folhas correspondentes a estados terminais, tais que um jogador tem trˆ
es s´ımbolos em
uma linha, coluna ou ainda diagonal; ou at´
e que todos os quadrados estejam preenchidos.
O n´
umero em cada n´
o de folha indica o valor de utilidade do estado terminal, do ponto
de vista de MAX; valores altos s˜
ao 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 implementa¸c˜
ao do Jogo da Velha desenvolvida na
Lingua-gem Java utilizando o algoritmo MiniMax. Consiste de 4 classes, quais sejam:
1. Velha.java - Classe principal da Aplica¸c˜
ao;
2. Minimax.java - Classe respons´
avel em aplicar o algoritmo MiniMax;
3. Tabuleiro.java - Classe respons´
avel pela manipula¸c˜
ao do tabuleiro do jogo;
Figura 2.1: ´
Arvore de busca parcial para o jogo da velha
.
4. Sucessor.java - Classe respons´
avel em gerar os sucessores, utilizados no algoritmo
MiniMax.
O algoritmo Minimax desenvolvido no J2 Velha pode buscar por profundidade infinita
(at´
e que se encontre um estado terminal) ou por alguma profundidade determinada. A
implementa¸c˜
ao da escolha de profundidade deu-se em fun¸c˜
ao da complexidade do
algo-ritmo MiniMax. Se a profundidade m´
axima da ´
arvore ´
e m e existem b movimento v´
alidos
em cada ponto, a complexidade de tempo do algoritmo MiniMax ´
e O(b
m).
Na Caixa de C´
odigo XX tem-se um trecho do algoritmo MiniMax contido na classe
Minimax.java. ´
E poss´ıvel comparar esta implementa¸c˜
ao com o algoritmo apresentado no
Cap´ıtulo anterior.
C´
odigo 2.1: Implementa¸c˜
ao do Algoritmo MiniMax
/∗ ∗ M´etodo de d e c i s ˜a o do MiniMax 3 ∗/ 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 [ ] [ ] ta b ) { 6 /∗ ∗ Limpa o s s u c e s s o r e s
∗/ 9 s u c e s s o r e s . c l e a r ( ) ; /∗ 12 ∗ Recebe a u t i l i d a d e m´axima ∗/ i n t v = v a l o r m a x ( tab , t r u e , 1 ) ; 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 m´axima
18 ∗/ f o r ( S u c e s s o r s : s u c e s s o r e s ) i f ( s . u t i l i d a d e == v ) 21 r e t u r n s . t a b u l e i r o ; r e t u r n t a b ; 24 } p u b l i c i n t v a l o r m a x ( i n t [ ] [ ] tab , b o o l e a n prim , i n t p r o f ) 27 { /∗
∗ 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
30 ∗ u t i l i d a d e ∗/ i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( t a b ) ) 33 r e t u r n u t i l i d a d e ( ta b ) ; /∗ 36 ∗ 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 /∗ ∗ P e r c o r r e o s n˜ao s u c e s s o r e s de MAX 42 ∗/ 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 ) ) { 45 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 . u t i l i d a d e = v ; /∗ 48 ∗ 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 ) 51 s u c e s s o r e s . add ( s ) ; }
54 r e t u r n v ;
}
57 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 )
{ /∗
60 ∗ 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
∗ u t i l i d a d e ∗/ 63 i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( t a b ) ) r e t u r n u t i l i d a d e ( ta b ) ; 66 /∗ ∗ A t r i b u i +I n f i n i t o ∗/ 69 i n t v = I n t e g e r .MAX VALUE; /∗ 72 ∗ P e r c o r r e o s 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) ) 75 { v = Math . min ( v , v a l o r m a x ( s . t a b u l e i r o , f a l s e , p r o f ) ) ; s . u t i l i d a d e = v ; 78 } r e t u r n v ; 81 }
2.2
Exemplos
A seguir tem-se a execu¸c˜
ao de algumas jogadas. Primeiramente vamos utilizar um
tabu-leiro de tamanho 3x3. Para tal n˜
ao se faz necess´
aria a defini¸c˜
ao de uma profundidade
m´
axima, pois a resposta do algoritmo ´
e r´
apida. Executando o classe Velha.java tem-se
a seguinte sa´ıda 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 ent˜
ao o resultado da jogada do
computador:
...
Sua jogada:
Linha [0 - 2]: 0
Coluna [0 - 2]: 1
| o |
---+---+---|
|
---+---+---|
|
Jogada do Computador:
x | o |
---+---+---|
|
---+---+---|
|
Sua jogada:
Linha [0 - 2]:
Para decidir onde jogar, o computador efetuou todo o algoritmo minimax e escolheu
uma posi¸c˜
ao que lhe favore¸ca, ao mesmo tempo que prejudique (n˜
ao agora, pode ser nas
pr´
oximas jogadas) o advers´
ario. 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 posi¸c˜
ao que evita que o advers´
ario
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 ---+---+---|
Jogada do Computador:
x | o | o
---+---+---| o ---+---+---|
---+---+---x | ---+---+---x |
Sua jogada:
Linha [0 - 2]:
Observe que de qualquer forma o computador ganhar´
a a partida. O jogador decide
jogar na linha 2, coluna 2. Tem-se a vit´
oria 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!
Vocˆ
e pode verificar o funcionamento do jogo com um tabuleiro 4x4. Basta mudar as
vari´
aveis TAM e PROF na classe Velha. Devido `
a complexidade do algoritmo recomenda-se
utilizar uma profundidade 5 para que o tempo de execu¸c˜
ao do mesmo seja razo´
avel. A
seguir tem-se uma partida completa utilizando um tabuleiro 4x4:
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
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 |
|
|
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
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
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!
J2 Velha: C´
odigos
A seguir tem-se a codifica¸c˜
ao completa da aplica¸c˜
ao. 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 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 /∗
∗ CLASSE VELHA − CLASSE PRINCIPAL DA APLICACAO
12 ∗/ 15 // B i b l i o t e c a Scanner p a r a c a p t u r a da j o g a d a do u s u ´a r i o import j a v a . u t i l . S c a n n e r ; 18 public c l a s s Velha { /∗ 21 ∗ 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 a l g o r i t m o
24 ∗ minimax i r ´a b u s c a r a t ´e um e s t a d o t e r m i n a l .
∗/
s t a t i c i n t TAM = 3 , PROF = −1;
27
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
30 S c a n n e r e n t = new S c a n n e r ( 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) ;
33 // O b j e t o da C l a s s e Minimax
MiniMax mm = new MiniMax (TAM, PROF) ;
System . o ut . p r i n t l n ( " UFABC - J2VELHA \ nBem vindo ao Jogo !\ nBoa Sorte !\n\n " ) ; 36 // Imprime o t a b u l e i r o na T e l a t . i m p r i m i r ( ) ; do 39 { // Captura j o g a d a do u s u ´a r i o i n t l , c ;
System . o ut . p r i n t f ( " Sua jogada :\r\ nLinha [0 - %d]: " , (TAM−1) ) ;
42 l = e n t . n e x t I n t ( ) ;
System . o ut . p r i n t f ( " Coluna [0 - %d]: " , (TAM−1) ) ; c = e n t . n e x t I n t ( ) ; 45 // R e a l i z a j o g a d a do u s u ´a r i o t . f a z e r J o g a d a ( l , c ) ; t . i m p r i m i r ( ) ; 48 // V e r i f i c a s e n˜ao ´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 ) ) { 51 // 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 . o ut . p r i n t l n ( " Jogada do Computador :" ) ;
54 t . i m p r i m i r ( ) ;
}
} 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 ) ) ;
57 // 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 . o ut . p r i n t l n ( "O computador ganhou !" ) ;
60 e l s e i f (mm. ganhou ( t . t a b u l e i r o , −1) )
System . o ut . p r i n t l n ( " Voc^e ganhou !" ) ; e l s e
63 System . o ut . p r i n t l n ( " Empate !" ) ;
} }
A.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 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 /∗∗ CLASSE TABULEIRO − REPRESENTA O TABULEIRO NO JOGO DA VELHA
12 ∗/ 15 public c l a s s T a b u l e i r o { 18 /∗ ∗ Vetor de c o n v e r s ˜a o p a ra i m p r e s s ˜a o na t e l a ∗/ 21 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 24 ∗/ s t a t i c i n t [ ] [ ] t a b u l e i r o ; /∗ 27 ∗ Tamanho do t a b u l e i r o ∗/ i n t tam ; 30 /∗ ∗ D i v i s o r das l i n h a s na t e l a ∗/ 33 S t r i n g d i v i s o r ; /∗
36 ∗ O m´etodo c o n s t r u t o r r e c e b e como p a r a m e t r o o tamanho do t a b u l e i r o
∗/
public T a b u l e i r o ( i n t tam )
39 {
t h i s . tam = tam ;
t a b u l e i r o = new i n t [ tam ] [ tam ] ;
42 d i v i s o r = g e r a r D i v i s o r ( ) ;
}
∗ M´etodo i n v o c a d o p a ra a j o g a d a do J o g a d o r ∗/ 48 public void f a z e r J o g a d a ( i n t l , i n t c ) { i f ( t a b u l e i r o [ l ] [ c ] == 0 ) 51 t a b u l e i r o [ l ] [ c ] = −1; e l s e
System . o ut . p r i n t l n ( " Posicao ja ocupada , perdeu a vez !" ) ;
54 } /∗ 57 ∗ 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 ( ) 60 { f o r ( i n t i = 0 ; i < tam ; i ++) { 63 f o r ( i n t j = 0 ; j < tam ; j ++) { System . o ut . 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 == ( tam−1) ? ’ ’ : ’|’ ) ; 66 } i f ( i != ( tam−1) ) System . o ut . p r i n t l n ( d i v i s o r ) ; 69 } System . o ut . p r i n t l n ( "\r\n" ) ; } 72 /∗
∗ Metodo para Gerar o D i v i s o r de L i n h a s . S e r v e para a u x i l i o da v i s u a l i z a c a o 75 ∗ 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 ( ) 78 { S t r i n g d = new S t r i n g ( "\r\n" ) ; 81 f o r ( i n t i = 0 ; i < ( tam − 1 ) ; i ++) { d += " ---+" ; 84 } d += " ---" ; 87 return d ; } 90 }
A.3
Classe Sucessor.java
/∗ ∗ UFABC − U n v e r s i d a d e F e d e r a l do ABC 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 /∗∗ CLASSE SUCESSOR − GERA OS ESTADOS DO JOGO DA VELHA ∗/ 12 public c l a s s S u c e s s o r { 15 i n t [ ] [ ] t a b u l e i r o ; i n t u t i l i d a d e ; 18 /∗ ∗ Metodo C o n s t r u t o r ∗/ 21 public S u c e s s o r ( i n t [ ] [ ] ta b ) { /∗
24 ∗ 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
∗/
i n t tam = ta b . l e n g t h ;
27 t a b u l e i r o = new i n t [ tam ] [ tam ] ;
f o r ( i n t i = 0 ; i < tam ; i ++) 30 f o r ( i n t j = 0 ; j < tam ; j ++) t a b u l e i r o [ i ] [ j ] = ta b [ i ] [ j ] ; } 33 }
A.4
Classe Minimax.java
/∗ ∗ UFABC − U n v e r s i d a d e F e d e r a l do ABC 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 /∗∗ 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 { /∗ 21 ∗ L i s t a de S u c e s s o r e s . Esta l i s t a ˜A c armazenada u t i l i z a n d o ∗ um A r r a y L i s t ∗/ 24 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 > ( ) ; i n t tam , maxProf ; 27 /∗ ∗ 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 m ˜A¡xima da b u s c a ∗/
30 public MiniMax ( i n t tam , i n t maxProf )
{
t h i s . tam = tam ;
33 i f ( maxProf > 0 )
t h i s . maxProf = maxProf ; e l s e
36 t h i s . maxProf = I n t e g e r .MAX VALUE; // Recebe o maior v a l o r de um
i n t e i r o . } 39 /∗ ∗ Metodo de d e c i s a o do MiniMax ∗/ 42 public i n t [ ] [ ] d e c i s a o m i n i m a x ( i n t [ ] [ ] ta b ) {
/∗ 45 ∗ Limpa os s u c e s s o r e s ∗/ s u c e s s o r e s . c l e a r ( ) ; 48 /∗ ∗ Recebe a u t i l i d a d e m ˜A¡xima 51 ∗/ i n t v = v a l o r m a x ( tab , true , 1 ) ; 54 /∗ ∗ 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 ˜A¡xima ∗/ 57 f o r ( S u c e s s o r 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 ; 60 return ta b ; } 63
public i n t v a l o r m a x ( i n t [ ] [ ] tab , boolean prim , i n t p r o f ) {
66 /∗
∗ Se a p r o f u n d i d a d e f o r maior que a m ˜A¡xima ou o j o g o acabou , r e t o r n a a ∗ u t i l i d a d e 69 ∗/ i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( t a b ) ) return u t i l i d a d e ( ta b ) ; 72 /∗ ∗ 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 ) 75 ∗/ i n t v = I n t e g e r . MIN VALUE ; 78 /∗ ∗ P e r c o r r e os n´os s u c e s s o r e s de MAX ∗/ 81 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 ) ) ; 84 s . u t i l i d a d e = 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 . . . 87 ∗/ i f ( prim )
s u c e s s o r e s . add ( s ) ; 90 } return v ; 93 } public i n t v a l o r m i n ( i n t [ ] [ ] tab , i n t p r o f ) 96 { /∗
∗ 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
99 ∗ u t i l i d a d e ∗/ i f ( p r o f++ > maxProf | | t e s t e t e r m i n a l ( t a b ) ) 102 return u t i l i d a d e ( ta b ) ; /∗ 105 ∗ 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; 108 /∗ ∗ P e r c o r r e os n´os s u c e s s o r e s de MIN 111 ∗/ 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) ) { 114 v = Math . min ( v , v a l o r m a x ( s . t a b u l e i r o , f a l s e , p r o f ) ) ; s . u t i l i d a d e = v ; } 117 return v ; } 120 /∗ ∗ 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 123 ∗/ 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 ( i n t [ ] [ ] tab , i n t v ) { 126 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 ( i n t i = 0 ; i < tam ; i ++) { 129 f o r ( i n t j = 0 ; j < tam ; j ++) { i f ( t a b [ i ] [ j ] == 0 ) 132 { ta b [ i ] [ j ] = v ; s u c . add (new S u c e s s o r ( ta b ) ) ; 135 ta b [ i ] [ j ] = 0 ;
} } 138 } return s u c ; 141 } /∗ 144 ∗ V e r i f i c a s e ch ego u 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 j o g o ∗/ public boolean t e s t e t e r m i n a l ( i n t [ ] [ ] ta b ) 147 {
return ( ganhou ( tab , 1 ) | | ganhou ( tab , −1) | | semEspaco ( tab ) ) ; } 150 /∗ ∗ Retorna a u t i l i d a d e 153 ∗/ public i n t u t i l i d a d e ( i n t [ ] [ ] ta b ) { 156 i f ( ganhou ( tab , 1 ) ) return 1 ; e l s e i f ( ganhou ( tab , −1) ) 159 return −1; e l s e return 0 ; 162 } /∗ 165 ∗ V e r i f i c a s e j o g a d o r ganhou ∗/
public boolean ganhou ( i n t [ ] [ ] tab , i n t v )
168 {
f o r ( i n t i = 0 ; i < tam ; i ++)
i f ( ganhouLinha ( tab , i , v ) | | ganhouColuna ( tab , i , v ) )
171 return true ;
i f ( ganhouDiag1 ( tab , v ) | | ganhouDiag2 ( tab , v ) )
174 return true ; 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 ? ∗/
private boolean ganhouLinha ( i n t [ ] [ ] tab , i n t l , i n t v ) 183 { f o r ( i n t i = 0 ; i < tam ; i ++) i f ( t a b [ l ] [ i ] != v ) 186 return f a l s e ; return true ; 189 } /∗ 192 ∗ Ganhou na s e q u e n c i a de c o l u n a s ? ∗/
private boolean ganhouColuna ( i n t [ ] [ ] tab , i n t c , i n t v )
195 { f o r ( i n t i = 0 ; i < tam ; i ++) i f ( t a b [ i ] [ c ] != v ) 198 return f a l s e ; return true ; 201 } /∗ 204 ∗ 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 ( i n t [ ] [ ] tab , i n t v )
207 { f o r ( i n t i = 0 ; i < tam ; i ++) i f ( t a b [ i ] [ i ] != v ) 210 return f a l s e ; return true ; 213 } /∗ 216 ∗ 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 ( i n t [ ] [ ] tab , i n t v )
219 { f o r ( i n t i = 0 ; i < tam ; i ++) i f ( t a b [ ( tam−1)− i ] [ i ] != v ) 222 return f a l s e ; return true ; 225 } /∗
∗/
public boolean semEspaco ( i n t [ ] [ ] ta b )
231 { f o r ( i n t l = 0 ; l < tam ; l ++) f o r ( i n t c = 0 ; c < tam ; c++) 234 i f ( t a b [ l ] [ c ] == 0 ) return f a l s e ; 237 return true ; } }
J2 Velha: Novas Funcionalidades
A seguir tem-se a codifica¸c˜
ao completa de novas funcionalidades do J2 Velha. O
pro-grama agora realiza o algoritmo minimax juntamente com o mecanismo de Poda Alfa-Beta
(Alpha-beta pruning). Al´
em disto, existe a possibilidade de jogar com elementos de acaso,
isto ´
e, as pe¸cas podem deslizar em determinada jogada. Todo o c´
odigo est´
a 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 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 import j a v a . u t i l . S c a n n e r ; 12 public c l a s s Velha { /∗ 15 ∗ Pe¸cas e s c o r r e g a d i a s ? ∗/ s t a t i c boolean ESCORREGA; 18public s t a t i c void main ( S t r i n g [ ] a r g s ) {
21 S c a n n e r e n t = new S c a n n e r ( System . i n ) ;
System . o ut . p r i n t ( " Voc^e deseja jogar com pe¸cas escorregadias ? [s/n ]: " ) ; 24 S t r i n g e s c = e n t . n e x t L i n e ( ) ; i f ( e s c . charAt ( 0 ) == ’s’ | | e s c . charAt ( 0 ) == ’S’ ) 27 { ESCORREGA = true ;
System . o ut . p r i n t l n ( " Pe¸cas escorregadias ativadas ." ) ;
30 }
e l s e {
33 ESCORREGA = f a l s e ;
System . o ut . p r i n t l n ( " Pe¸cas escorregadias desativadas ." ) ; }
36
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) ;
39 t . i m p r i m i r ( ) ;
42 do
{
i n t l , c ;
45 System . o ut . p r i n t f ( " Sua jogada :\r\ nLinha [0 - 3]: " ) ;
l = e n t . n e x t I n t ( ) ; System . o ut . p r i n t f ( " Coluna [0 - 3]: " ) ; 48 c = e n t . n e x t I n t ( ) ; t . f a z e r J o g a d a ( l , c ) ; t . i m p r i m i r ( ) ; 51 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 t i m e = System . c u r r e n t T i m e M i l l i s ( ) ; 54 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 ) ; t i m e = System . c u r r e n t T i m e M i l l i s ( ) − t i m e ;
System . o ut . p r i n t l n ( " Jogada do Computador (" + time + " ms):" ) ;
57 t . i m p r i m i r ( ) ; } } 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 i n t u = mm. u t i l i d a d e ( t . t a b u l e i r o ) ; i f ( u < 0 )
63 System . o ut . p r i n t l n ( " Parabens ! Voce ganhou ... " ) ;
e l s e i f ( u == 0 )
System . o ut . p r i n t l n ( " Empatou !" ) ;
66 e l s e
System . o ut . p r i n t l n ( " Voc^e marcou " + mm. c o n t a P o n t o s ( t . t a b u l e i r o , −1) + " pontos ." ) ;
69 System . o ut . p r i n t l n ( "O computador marcou " + mm. c o n t a P o n t o s ( t . t a b u l e i r o ,
1 ) + " pontos ." ) ; }
72 }
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 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ / 9 import j a v a . u t i l . A r r a y L i s t ; 12 public c l a s s T a b u l e i r o { /∗ 15 ∗ Vetor de c o n v e r s ˜a o p a ra 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’ } ; 18 /∗ ∗ M a t r i z do t a b u l e i r o ∗/ 21 s t a t i c i n t [ ] [ ] t a b u l e i r o ; /∗ ∗ Pe ˜A§as E s c o r r e g a d i a s ? 24 ∗/ boolean e s c o r r e g a ; 27 /∗ ∗ C o n s t r u t o r ∗ e n t r a d a : tamanho do t a b u l e i r o 30 ∗/ public T a b u l e i r o ( boolean e s c o r r e g a ) { 33 t h i s . e s c o r r e g a = e s c o r r e g a ; t a b u l e i r o = new i n t [ 4 ] [ 4 ] ; } 36 /∗ ∗ M´etodo i n v o c a d o p a ra a j o g a d a do J o g a d o r ! 39 ∗/ public void f a z e r J o g a d a ( i n t l , i n t c ) { 42 i f ( t a b u l e i r o [ l ] [ c ] == 0 ) { /∗ 45 ∗ 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 . . .∗/
i f ( e s c o r r e g a )
48 {
/∗
∗ 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£o . .
51 ∗/
A r r a y L i s t <i n t [ ] > v i z i n h o s = v i z i n h o s L i v r e s ( l , c ) ;
54 /∗
∗ Se h o u v e r ao menos um v i z i n h o l i v r e , tem 20% de chance da pe¸ca ∗ e s c o r r e g a r . .
57 ∗/
i f ( v i z i n h o s . s i z e ( ) > 0 && Math . random ( ) <= 0 . 2 ) { 60 /∗ ∗ 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 . . ∗/ 63 i n t x = ( i n t ) ( 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 66 ∗ e s c o l h i d o . . ∗/ l = v i z i n h o s . g e t ( x ) [ 0 ] ; 69 c = v i z i n h o s . g e t ( x ) [ 1 ] ;
System . o ut . p r i n t l n ( "A pe¸ca escorregou e caiu na posi¸c~ao : " + l + " , " + c ) ; } 72 } t a b u l e i r o [ l ] [ c ] = −1; } 75 e l s e
System . o ut . p r i n t l n ( " Posi¸c~ao j´a ocupada , perdeu a vez !" ) ; } 78 /∗ ∗ M´etodo 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 a s d i a g o n a i s . . . 81 ∗/ public A r r a y L i s t <i n t [ ] > v i z i n h o s L i v r e s ( i n t l , i n t c ) {
84 A r r a y L i s t <i n t [ ] > v i z i n h o s = new A r r a y L i s t <i n t [ ] > ( ) ;
/∗
87 ∗ 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 v e 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 ) 93 v i z i n h o s . add (new i n t [ ] { l −1 , c −1}) ; i f ( t a b u l e i r o [ l − 1 ] [ c ] == 0 ) 96 v i z i n h o s . add (new i n t [ ] { l −1 , c } ) ; i f ( c < 3 ) 99 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 i n t [ ] { l −1 , c +1}) ; } 102 /∗ ∗ V i z i n h o s da mesma l i n h a . . . 105 ∗/ i f ( c > 0 ) i f ( t a b u l e i r o [ l ] [ c −1] == 0 ) 108 v i z i n h o s . add (new i n t [ ] { l , c −1}) ; i f ( c < 3 ) 111 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 i n t [ ] { l , c +1}) ; 114 /∗ ∗ 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 v e r . . . ∗/ 117 i f ( l < 3 ) { i f ( c > 0 ) 120 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 i n t [ ] { l +1 , c −1}) ; 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 i n t [ ] { 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 i n t [ ] { l +1 , c +1}) ; 129 } return v i z i n h o s ; 132 } /∗
135 ∗ M´etodo p a ra a impress ˜A£o do t a b u l e i r o na t e l a
∗/
138 { f o r ( i n t i = 0 ; i < 4 ; i ++) { 141 f o r ( i n t j = 0 ; j < 4 ; j ++) { System . o ut . 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 ? ’ ’ : ’|’ ) ; 144 } i f ( i != ( 3 ) ) System . o ut . p r i n t l n ( "\r\n ---+---+---+---" ) ; 147 } System . o ut . p r i n t l n ( "\r\n" ) ; } 150 }
B.3
Classe Sucessor.java
/∗ ∗ UFABC − U n v e r s i d a d e F e d e r a l do ABC 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 public c l a s s S u c e s s o r { i n t [ ] [ ] t a b u l e i r o ; 12 i n t u t i l i d a d e ; /∗ 15 ∗ C o n s t r u t o r ∗/ public S u c e s s o r ( i n t [ ] [ ] ta b ) 18 { /∗∗ 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
21 ∗/
i n t tam = ta b . l e n g t h ;
t a b u l e i r o = new i n t [ tam ] [ tam ] ;
24 f o r ( i n t i = 0 ; i < tam ; i ++) f o r ( i n t j = 0 ; j < tam ; j ++) 27 t a b u l e i r o [ i ] [ j ] = ta b [ i ] [ j ] ; } }
B.4
Classe Minimax.java
/∗ ∗ UFABC − U n v e r s i d a d e F e d e r a l do ABC 3 ∗ 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ˆonimo P e l l e g r i n i ∗ Alunos : 6 ∗ Andr´e F i l i p e de Moraes B a t i s t a ∗ L u´ıs Fernando de O l i v e i r a J a c i n t h o ∗/ 9 import j a v a . u t i l . A r r a y L i s t ; 12 public c l a s s MiniMax { /∗ 15 ∗ 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 > ( ) ; 18 /∗ ∗ J o g a r com p e ¸c a s e s c o r r e g a d i a s ? ∗/ 21 boolean e s c o r r e g a ; /∗ 24 ∗ C o n s t r u t o r ∗/public MiniMax ( boolean e s c o r r e g a )
27 { t h i s . e s c o r r e g a = e s c o r r e g a ; } 30 /∗ ∗ M´etodo de d e c i s ˜a o do MiniMax 33 ∗/ public i n t [ ] [ ] d e c i s a o m i n i m a x ( i n t [ ] [ ] ta b ) { 36 /∗ ∗ Limpa os s u c e s s o r e s ∗/ 39 s u c e s s o r e s . c l e a r ( ) ; /∗ 42 ∗ Recebe a u t i l i d a d e m´axima ∗/
i n t v = v a l o r m a x ( tab , I n t e g e r . MIN VALUE, I n t e g e r .MAX VALUE, true ) ;
/∗ ∗ 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 48 ∗/ f o r ( S u c e s s o r s : s u c e s s o r e s ) i f ( s . u t i l i d a d e == v ) 51 return s . t a b u l e i r o ; return ta b ; 54 }
public i n t v a l o r m a x ( i n t [ ] [ ] tab , i n t a l f a , i n t beta , boolean prim )
57 {
/∗
∗ 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
60 ∗ u t i l i d a d e ∗/ i f ( t e s t e t e r m i n a l ( t a b ) ) 63 return u t i l i d a d e ( ta b ) ; /∗ 66 ∗ 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 . MIN VALUE ; 69 /∗ ∗ P e r c o r r e os n´os s u c e s s o r e s de MAX 72 ∗/ 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 ) ) { 75 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 . u t i l i d a d e = v ; 78 /∗ ∗ 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 . . . ∗/ 81 i f ( prim ) s u c e s s o r e s . add ( s ) ; 84 /∗
∗ 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 . . ∗/
87 i f ( v >= b e t a )
return v ;
90 /∗
∗/ 93 a l f a = Math . max ( a l f a , v ) ; } 96 return v ; } 99 public i n t v a l o r m i n ( i n t [ ] [ ] tab , i n t a l f a , i n t b e t a ) { /∗
102 ∗ 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
∗ u t i l i d a d e ∗/ 105 i f ( t e s t e t e r m i n a l ( t a b ) ) return u t i l i d a d e ( ta b ) ; 108 /∗ ∗ A t r i b u i +I n f i n i t o ∗/ 111 i n t v = I n t e g e r .MAX VALUE; /∗ 114 ∗ P e r c o r r e os n´os 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) ) 117 {
v = Math . min ( v , v a l o r m a x ( s . t a b u l e i r o , a l f a , beta , f a l s e ) ) ; s . u t i l i d a d e = v ;
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 . . .
123 ∗/
i f ( v <= a l f a ) return v ;
126
/∗
∗ Se v a l o r menor que Beta , Beta o r e c e b e . . .
129 ∗/
b e t a = Math . min ( beta , v ) ; } 132 return v ; } 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 138 ∗/
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 ( i n t [ ] [ ] tab , i n t v ) { 141 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 ( i n t i = 0 ; i < 4 ; i ++) { 144 f o r ( i n t j = 0 ; j < 4 ; j ++) { i f ( t a b [ i ] [ j ] == 0 ) 147 { /∗ ∗ 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 . . . 150 ∗/ i f ( e s c o r r e g a ) { 153 /∗ ∗ 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 ˜a o . . ∗/ 156 A r r a y L i s t <i n t [ ] > 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 v e r ao menos um v i z i n h o l i v r e , tem 20% de chance da pe ˜A§a
159 ∗ e s c o r r e g a r . .
∗/
i f ( v i z i n h o s . s i z e ( ) > 0 && Math . random ( ) <= 0 . 2 )
162 { /∗ ∗ 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 . . 165 ∗/ i n t x = ( i n t ) ( Math . random ( ) ∗ v i z i n h o s . s i z e ( ) ) ; /∗ 168 ∗ 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 ∗ e s c o l h i d o . . ∗/ 171 i = v i z i n h o s . g e t ( x ) [ 0 ] ; j = v i z i n h o s . g e t ( x ) [ 1 ] ; } 174 } ta b [ i ] [ j ] = v ; 177 s u c . add (new S u c e s s o r ( ta b ) ) ; ta b [ i ] [ j ] = 0 ; } 180 } } 183 return s u c ;
} 186 /∗ ∗ M´etodo 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 a s d i a g o n a i s . . . ∗/ 189 public A r r a y L i s t <i n t [ ] > v i z i n h o s L i v r e s ( i n t [ ] [ ] t a b u l e i r o , i n t l , i n t c ) {
A r r a y L i s t <i n t [ ] > v i z i n h o s = new A r r a y L i s t <i n t [ ] > ( ) ;
192 /∗ ∗ 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 v e r . . . 195 ∗/ i f ( l > 0 ) { 198 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 i n t [ ] { 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 i n t [ ] { l −1 , c } ) ; 204 i f ( c < 3 ) i f ( t a b u l e i r o [ l − 1 ] [ c +1] == 0 ) 207 v i z i n h o s . add (new i n t [ ] { l −1 , c +1}) ; } 210 /∗ ∗ V i z i n h o s da mesma l i n h a . . . ∗/ 213 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 i n t [ ] { l , c −1}) ; 216 i f ( c < 3 ) i f ( t a b u l e i r o [ l ] [ c +1] == 0 ) 219 v i z i n h o s . add (new i n t [ ] { l , c +1}) ; /∗ 222 ∗ 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 v e r . . . ∗/ i f ( l < 3 ) 225 { i f ( c > 0 ) i f ( t a b u l e i r o [ l + 1 ] [ c −1] == 0 ) 228 v i z i n h o s . add (new i n t [ ] { l +1 , c −1}) ;
i f ( t a b u l e i r o [ l + 1 ] [ c ] == 0 ) 231 v i z i n h o s . add (new i n t [ ] { l +1 , c } ) ; i f ( c < 3 ) 234 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 i n t [ ] { l +1 , c +1}) ; } 237 return v i z i n h o s ; } 240 /∗ ∗ Fim de j o g o ? 243 ∗ O j o g o s´o t e r m i n a s e n˜ao h o u v e r mais e s p a ¸c o p a ra j o g a d a s . . . ∗/ public boolean t e s t e t e r m i n a l ( i n t [ ] [ ] ta b ) 246 { return ( semEspaco ( t a b ) ) ; } 249 /∗ ∗ Retorna a u t i l i d a d e . . . 252 ∗ 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˜ao d e s e j a a p e n a s v e n c e r , mas tamb´em h u m i l h a r =P ∗/ 255 public i n t u t i l i d a d e ( i n t [ ] [ ] ta b ) { i n t pc , u s r ; 258 pc = c o n t a P o n t o s ( tab , 1 ) ; u s r = c o n t a P o n t o s ( tab , −1) ; 261 return ( pc−u s r ) ; } 264 /∗ ∗ V e r i f i c a s e j o g a d o r ganhou 267 ∗/ public i n t c o n t a P o n t o s ( i n t [ ] [ ] tab , i n t v ) { 270 i n t p o n t o s = 0 ; f o r ( i n t i = 0 ; i < 4 ; i ++) 273 { p o n t o s += c o n t a L i n h a ( tab , i , v ) ;
p o n t o s += c o n t a C o l u n a ( tab , i , v ) ; 276 } p o n t o s += c o n t a D i a g 1 ( tab , v ) ; 279 p o n t o s += c o n t a D i a g 2 ( tab , v ) ; return p o n t o s ; 282 } /∗ 285 ∗ Pontos na s e q u e n c i a de l i n h a s ? ∗ ∗ M´etodo 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 r i o , p r e c i s a r i a a p e n a s
288 ∗ 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 a s 3 ∗ p o s s i b i l i d a d e s de marcar p o n t o s , 4 p o s i ¸c ˜o e s v i z i n h a s ( 1 1 1 1 ) ou 3
p o s i c o e s
291 ∗ v i z i n h a s (0111 ou 1110) . Q ua l qu er o u t r a combina¸c˜ao 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˜ao marcariam p o n t o s . ∗/ 294 private i n t c o n t a L i n h a ( i n t [ ] [ ] tab , i n t l , i n t v ) { byte soma = 0 ; 297 f o r ( i n t i = 0 ; i < 4 ; i ++) i f ( t a b [ l ] [ i ] == v ) 300 soma += ( 1 << i ) ; i f ( soma == 1 5 ) // 1111 303 return 3 ; e l s e i f ( ( soma == 7 ) | | ( soma == 1 4 ) ) // 0111 v 1110 return 1 ; 306 e l s e return 0 ; } 309 /∗ ∗ Pontos na s e q u e n c i a de c o l u n a s ? 312 ∗/ private i n t c o n t a C o l u n a ( i n t [ ] [ ] tab , i n t c , i n t v ) { 315 i n t soma = 0 ; f o r ( i n t i = 0 ; i < 4 ; i ++) 318 i f ( t a b [ i ] [ c ] == v )
soma += ( 1 << i ) ; 321 i f ( soma == 1 5 ) // 1111 return 3 ; e l s e i f ( ( soma == 7 ) | | ( soma == 1 4 ) ) // 0111 v 1110 324 return 1 ; e l s e return 0 ; 327 } /∗ 330 ∗ Ganhou na s e q u e n c i a d i a g o n a l ? ∗/ private i n t c o n t a D i a g 1 ( i n t [ ] [ ] tab , i n t v ) 333 { i n t soma = 0 ; i n t p e x t r a = 0 ; 336 f o r ( i n t i = 0 ; i < 4 ; i ++) i f ( t a b [ i ] [ i ] == v ) 339 soma += ( 1 << i ) ; /∗
342 ∗ 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 ,
∗ podendo−s e a d i c i o n a r e n t a o apenas 1 p o n t o . . . . ∗/ 345 i f ( t a b [ 1 ] [ 0 ] == v && ta b [ 2 ] [ 1 ] == v && t a b [ 3 ] [ 2 ] == v ) p e x t r a ++; i f ( t a b [ 0 ] [ 1 ] == v && ta b [ 1 ] [ 2 ] == v && t a b [ 2 ] [ 3 ] == v ) 348 p e x t r a ++; i f ( soma == 1 5 ) 351 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 ; 354 e l s e return 0 + p e x t r a ; } 357 /∗ ∗ Ganhou na s e q u e n c i a d i a g o n a l ? 360 ∗/ private i n t c o n t a D i a g 2 ( i n t [ ] [ ] tab , i n t v ) 363 { i n t soma = 0 ; i n t p e x t r a = 0 ;
366
f o r ( i n t i = 0 ; i < 4 ; i ++) i f ( t a b [3 − i ] [ i ] == v )
369 soma += ( 1 << i ) ;
/∗
372 ∗ 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 ,
∗ podendo−s e a d i c i o n a r e n t a o apenas 1 p o n t o . . . . ∗/ 375 i f ( t a b [ 0 ] [ 2 ] == v && ta b [ 1 ] [ 1 ] == v && t a b [ 2 ] [ 0 ] == v ) p e x t r a ++; i f ( t a b [ 1 ] [ 3 ] == v && ta b [ 2 ] [ 2 ] == v && t a b [ 3 ] [ 1 ] == v ) 378 p e x t r a ++; i f ( soma == 1 5 ) 381 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 ; 384 e l s e return 0 + p e x t r a ; } 387 /∗ ∗ 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 . . 390 ∗/
public boolean semEspaco ( i n t [ ] [ ] ta b ) { 393 f o r ( i n t l = 0 ; l < 4 ; l ++) f o r ( i n t c = 0 ; c < 4 ; c++) i f ( t a b [ l ] [ c ] == 0 ) 396 return f a l s e ; return true ; 399 } }