1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

[Dúvida] HASKELL

Discussão em 'Programação' iniciada por kripton2007, 22 de Dezembro de 2008. (Respostas: 29; Visualizações: 1836)

  1. kripton2007

    kripton2007 Power Member

    Boas...

    Ja expus as minhas dúvidas sobre este assunto num outro tópico que não era meu mas que era sobre o mesmo trabalho, no entanto as dúvidas do criador desse tópico foram esclarecidas e como tal o tópico foi dado como [Resolvido].
    Tendo em conta que ainda estou à rasca nesta matéria decidi por bem criar um tópico novo para esclarecer tudo aquilo em que tenho dúvidas.

    Então aqui vai informação:

    É o seguinte, tenho um trabalho prático para fazer até dia 4 de Janeiro para a disciplina de Laboratórios de Informática de LEI 1º Ano. Este trabalho consiste em fazer um jogo em Haskell, sendo ele o conhecido 4 em Linha. Em cada jogada, o jogador pode colocar uma das suas peças numa coluna não cheia. A posição dessa coluna que é ocupada é a seguinte à última que foi ocupada.

    No entanto, fazer o jogo tal como o conhecemos não basta... o prof. quer que implementemos uma variante do jogo a qual se vai dar o nome "Segmentos". O objectivo do jogo é acumular o maior número de pontos possível. Os pontos são conseguidos quando se obtêm linhas de n peças iguais. Essas linhas podem ser verticais, horizontais ou na diagonal. A pontuação será diferente, consoante o número de peças em linha. Fica aqui o exemplo:

    2 peças = 1 ponto
    3 peças = 3 pontos
    4 peças = 6 pontos
    5 peças = 10 pontos
    6 peças = 15 pontos
    7 peças = 21 pontos
    ...

    Desta forma, o jogo não termina assim que um jogador faça o 4 em linha, mas sim quando o tabuleiro do jogo ficar cheio... sendo que os pontos acumulados por cada jogador serão contabilizados no decorrer do jogo, e ganha o jogador com maior número de pontos.


    Ora, o 1º passo sugerido para a elaboração do trabalho passa por definir os tipos apropriados para representar tabuleiros e jogadas e definir o tipo dos tabuleiros como uma instância de classes (a mais apropriada, por exemplo: SHOW).

    Posto isto, comecei por definir os tipos para o tabuleiro:

    Código:
    type J            = Int 
    type Jogada    = (J)
    type Coluna    = [Jogada]
    type Tabuleiro = [Coluna]

    De seguida, e seguindo as indicações do prof. decidi elaborar o tabuleiro como sendo uma lista de listas, o que iria dar algo deste género:

    Código:
    tabuleiroJogo :: Int -> Int -> Tabuleiro                
    tabuleiroJogo coluna linha = (tabela coluna linha)      
    tabela l c = [ [(0) | y <- [1..c] ] | x<- [1..l] ] 
    em que o seu resultado seria o seguinte:

    > tabuleiroJogo 2 2
    > [[0,0],[0,0]]


    Acontece que agora não consigo passar daqui, bloqueei por completo. A ideia é passar o tabuleiro para um modo gráfico do género:

    |___|___|___|___|
    |_X_|_X_|_O_|___|
    |_O_|_X_|_O_|_X_|


    Tenho também algum código que um colega meu escreveu para esse efeito, mas acontece que não sei bem como implementá-lo no programa. No entanto aqui fica ele:

    Código:
    type BoardLine = [FieldValue]
    type Board     = [BoardLine]
     
    data FieldValue = Null
                          | P1
                          | P2
     
    drawBoard :: Board -> IO ()
    drawBoard []    = return ()
    drawBoard (line:lines) = do drawBoardLine line
                                         drawBoard lines
     
    drawBoardLine :: BoardLine -> IO ()
    drawBoardLine []     = putStrLn ("|")
    drawBoardLine (c:cs) = do
                             drawBoardField c
                             drawBoardLine cs
     
    drawBoardField :: FieldValue -> IO ()
    drawBoardField value = putStr ("|_"++ signal ++ "_")
                                    where signal = case (value) of
                                                            Null -> "_"
                                                            P1   -> "X"
                                                            P2   -> "O"
    

    Gostava que alguém me pudesse ajudar com isto... visto estar a ficar com pouco tempo!

    Obrigado


    Cumps kripton2007
     
  2. kripton2007

    kripton2007 Power Member

    Ajudas plz...

    :S
     
  3. kripton2007

    kripton2007 Power Member

    Yah.. eu ja passei por la, mas não consegui obter nada de concreto! :S
    e o k é certo é k estou a dar em maluco com a carrada de trabalhos que tenho para entregar em tão curto período de tempo!

    eu não queria chegar a estes termos, mas não se consegue arranjar algum programa relativamente parecido com o trbalho proposto para que eu possa fazer uma adaptação ou para que possa modificar alguma coisa.

    Estou mesmo a ficar desesperado! :(
     
  4. Baderous

    Baderous Banido

    Quanto aos tipos que definiste, não os podes definir como instâncias de Show, pois estas têm de ter como tipo parâmetro um tipo polimórfico do tipo T a b c, ou seja, daqueles tipos definidos com a keyword "data".
     
  5. kripton2007

    kripton2007 Power Member

    estás a falar do 1º código que aparece neste post certo?
     
  6. kripton2007

    kripton2007 Power Member

    pois... disseram-me k não preciso desses tipos para nada, que posso fazer tudo através daquilo que fiz no ultimo código aqui apresentado!

    é verdade?
     
  7. kripton2007

    kripton2007 Power Member

    Ora então precisava de ajuda para o seguinte. Utilizando esta solução para fazer o tabuleiro, pretendo criar uma função "comecarJogo" em que vai chamar a função de um jogo com um tabuleiro vazio.
    De seguida criar a função "jogar" que irá verificar se é possivel jogar, ou seja, se o tabuleiro està ou não cheio, e vai fazendo a alternância entre o jogador 1 e 2.
    É também necessário criar a função "pedeJogada" que vai perguntar qual a coluna em que o jogador pretende colocar a peça, e de seguida coloca a peça desse jogador na coluna pretendida e apresenta o tabuleiro actualizado.

    Código:
    type BoardLine = [FieldValue]
    type Board     = [BoardLine]
     
    data FieldValue = Null
                          | P1
                          | P2
     
    drawBoard :: Board -> IO ()
    drawBoard []    = return ()
    drawBoard (line:lines) = do drawBoardLine line
                                         drawBoard lines
     
    drawBoardLine :: BoardLine -> IO ()
    drawBoardLine []     = putStrLn ("|")
    drawBoardLine (c:cs) = do
                             drawBoardField c
                             drawBoardLine cs
     
    drawBoardField :: FieldValue -> IO ()
    drawBoardField value = putStr ("|_"++ signal ++ "_")
                                    where signal = case (value) of
                                                            Null -> "_"
                                                            P1   -> "X"
                                                            P2   -> "O"
    

    Resumindo eu sei aquilo que tenho que fazer, mas o que é certo é k não sei como fazer, uma vez que não percebo muito de Haskell e tenho dificuldades com o código! :S

    Alguém me pode ajudar com o código disto??


    Cumps
     
  8. kripton2007

    kripton2007 Power Member

  9. Baderous

    Baderous Banido

    Na função "jogar" tens de percorrer a lista de listas e verificar se existe pelo menos um valor Null, o que te indica se há ou não uma casa para ser preenchida.
    Para a função "pedeJogada", o ideal seria dividir em 2: uma em que, dado um tabuleiro e as coordenadas de uma posição, insere uma peça no tabuleiro conforme as coordenadas; outra em que pede ao utilizador para inserir as coordenadas e depois chama a função que referi com as tais coordenadas como parâmetro. No fim, basta invocar a função que desenha o tabuleiro. Não te esqueças que tens de verificar se a posição escolhida pelo jogador já está preenchida (outra função).
    Depois a função "começarJogo" basicamente seria a função que ia chamando estas auxiliares até acabar o jogo.
     
  10. kripton2007

    kripton2007 Power Member

    pois.. o meu problema está mesmo em escrever o código! Como ja disse não percebo praticamente nada de Haskell (o facto de não gostar também ajuda), o que faz com que tenha dificuldade em programar nesta linguagem!

    Não podem dar uma ajudinha aì com o código??

    Cumps
    Obrigado


    edit: Entretanto fiz isto com ajuda de um colega meu


    --Criar Tabuleiro Novo
    criarTabuleiro :: Int -> Int -> [[Int]]
    criarTabuleiro 0 _ = []
    criarTabuleiro altura largura = (criarLinha largura) : (criarTabuleiro (altura-1) largura)

    criarLinha :: Int -> [Int]
    criarLinha 0 = []
    criarLinha largura = 0 : criarLinha (largura -1)

    --Verificar se o tabuleiro está cheio
    estaCheio :: [[Int]] -> Bool
    estaCheio (x:xs) = (length listaFiltrada) == 0
    where listaFiltrada = filter (==0) x


    com isto, falta a função para jogar, a função para pedir a jogada, para começar o jogo, da pontuação e para associar tudo isto à parte gráfica que está acima descrita.
     
    Última edição: 27 de Dezembro de 2008
  11. Baderous

    Baderous Banido

    Tens aqui um exemplo, em point-free (sem usar variáveis), da função "jogar":

    Código:
    isNull Null = True
    isNull _ = False
    
    jogar = not . null . filter (isNull) . concat
    Se quiseres com variáveis basta:

    Código:
    jogar t = not $ null $ filter (isNull)$ concat t
    O que faço é apenas a verificação de existência de um valor Null. Primeiro junto a lista de listas numa lista só com o concat, depois filtro numa lista os valores que são Null e depois verifico se essa lista é vazia através do null. O not só está lá para negar o resultado do null, isto é, se houver posições para jogar, a função "joga" retorna verdadeiro (porque como o null, nesse caso retorna falso, pois a lista não é vazia, então o not do null retorna True).
     
  12. kripton2007

    kripton2007 Power Member

    sendo assim, a tua solução para verificar se é ou não vazio é melhor que o código que coloquei agora em cima certo???
    pelo menos está mais direccionado para o restante codigo...
     
  13. Baderous

    Baderous Banido

    Eu fiz a função de acordo com os tipos de dados que me forneceste há uns posts atrás. O que tu fizeste com o teu colega está certo (supondo que a lista de listas representa um conjunto de linhas do tabuleiro. de cima para baixo e que, como tal, para verificar se o tabuleiro está cheio, basta verificar se a primeira linha está preenchida) , mas ele está a considerar uma forma de representar o tabuleiro em que as posições vazias são indicadas pelo valor 0, enquanto que eu considerei que era quando existisse o valor Null.
     
  14. kripton2007

    kripton2007 Power Member

    exacto... ja percebi!

    agora como faço para começar a jogar? suponho que faltam apenas as funções para ler a jogada, verificar se a jogada é valida, alternar de jogador, colocar a peça correspondente no tabuleiro e gerar um tabuleiro actualizado. Vou esquecer por enquanto as pontuações.

    Como faço em relação ao código dessas funções?
     
  15. MPalhas

    MPalhas Power Member

    ler a jogada pode ser tão simples como fazer um getLine para ler um valor do ecrã. se quiseres validar esse valor, para impedir erros é que já pode complicar mais. podes ver no tópico que eu criei a uns dias que eu pus lá uma parte do código que uso para isso.

    para verificar se a jogada é valida, basta verificar se a coluna escolhida tem espaço livre. como é uma lista de linhas, fica ainda mais simples. basta ver se o elemento dessa coluna na primeira linha é vazio.

    Código:
    eValida :: [[Int]] -> Int -> Bool
    eValida (linha1:linhas) col = (linha1 !! (col-1)) == 0
    
    -- ou, como não nos chegaram a ensinar aquele !!, isto faz o mesmo:
    
    eValida (linha1:linhas) col = last (take col linha1) == 0
    
    no segundo caso, pega na lista até ao elemento pretendido, e verifica se o ultimo elemento (que é o da coluna que se quer) é igual a 0. se for, quer dizer que essa coluna não está cheia e a jogada é valida


    para alternar entre os jogadores, basta que a função que vai pedindo as jogadas receba um parametro que vá alternando entre dois valores (1 e 0, True e False, qualquer coisa). um deles irá corresponder ao jogador 1 e o outro ao jogador 2 e assim saberás sempre quem é o proximo a jogar
     
  16. Baderous

    Baderous Banido

    Se fosse a ti, primeiro fazia as funções de verificar se a jogada é válida e colocar a peça no tabuleiro. Para a 1ª tens de receber o tabuleiro e as coordenadas e verificar se essa posição já está preenchida ou não. Para a 2ª é inserir um elemento numa lista.
     
  17. casdio

    casdio Power Member

    A parte da jogada ja conseguimos fazer, mas so pela consola.

    temos que fazer "jogada it (para chamar o tabuleiro modificado) 3 (nº da coluna) P1 (jogador)"

    Agora o problema e por isto a funcionar com IO's... Ai e que n tamos a ver como se faz :S
     
  18. kripton2007

    kripton2007 Power Member

    e como faço isso?
     

Partilhar esta Página