Estou criando uma simples implementação MiniMax na linguagem de programação funcional Elixir. Como existem muitos jogos de conhecimento perfeito (jogo da velha, jogo quatro, damas, xadrez, etc), essa implementação pode ser uma estrutura para criar AIs de jogos para qualquer um desses jogos.
Um problema que estou enfrentando, no entanto, é como armazenar adequadamente um estado de jogo em uma linguagem funcional. Esses jogos lidam principalmente com tabuleiros de jogo bidimensionais, onde as seguintes operações são frequentes:
- Leia o conteúdo de um local específico do quadro
- Atualize o conteúdo de um local específico do quadro (ao retornar uma nova possibilidade de movimento)
- Considerando o conteúdo de um ou mais locais conectados ao local atual (ou seja, o próximo ou anterior local horizontal, vertical ou diagonal)
- Considerando o conteúdo de vários locais conectados em qualquer direção.
- Considerando o conteúdo de arquivos inteiros, classificações e diagonais.
- Girar ou espelhar a placa (para verificar simetrias que fornecem o mesmo resultado que algo já calculado).
A maioria das linguagens funcionais usa listas e tuplas vinculadas como blocos básicos de construção de estruturas de dados com vários elementos. No entanto, estes parecem muito mal feitos para o trabalho:
- As listas vinculadas têm tempo de pesquisa O (n) (linear). Além disso, como não podemos 'digitalizar e atualizar o quadro' em uma única varredura, usar listas parece muito impraticável.
- As tuplas têm tempo de pesquisa O (1) (constante). No entanto, representar o quadro como uma tupla de tamanho fixo dificulta a iteração sobre classificações, arquivos, diagonais ou outros tipos de quadrados consecutivos. Além disso, tanto Elixir, e Haskell (que são as duas línguas funcionais que eu conheço) falta sintaxe para ler o n º elemento de uma tupla. Isso tornaria impossível escrever uma solução dinâmica que funcionasse para placas de tamanho arbitrário.
O Elixir possui uma estrutura de dados de mapa incorporada (que a Haskell possui Data.Map
) que permite acesso a O (log n) (logarítmico) aos elementos. Agora eu uso um mapa, com x, y
tuplas que representam a posição como chaves.
Isso 'funciona', mas parece errado abusar dos mapas dessa maneira, embora eu não saiba exatamente o porquê. Estou procurando uma maneira melhor de armazenar um tabuleiro de jogo bidimensional em uma linguagem de programação funcional.