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

[Resolvido] Haskell - Dúvida ao compilar

Discussão em 'Programação' iniciada por MPalhas, 13 de Dezembro de 2008. (Respostas: 11; Visualizações: 1931)

  1. MPalhas

    MPalhas Power Member

    tenho um programa em Haskell que estou a fazer para o trabalho de Programação Funcional, que consiste num jogo parecido com o 4 em linha.

    estou a programar no Ubuntu, e daquilo que tenho feito até agora, corre tudo sem problemas no GHCi.
    mas quando tento compilar com o GHC o que acontece é que sempre que o programa tem que escrever uma string e depois pedir um valor, o que ele faz é o contrário, ou seja primeiro pede o valor e só depois escreve a string que deveria ter escrito antes

    o comando que uso para compilar é: ghc --make Main.hs
    muito provavelmente o problema está aqui, já que não encontrei nenhuma informação sobre qual o comando correcto, e após algumas tentativas este foi o primeiro que não deu erro ao compilar


    outra dúvida que queria aproveitar para esclarecer era sobre números aleatórios. já estive a procurar no Hoogle mas não não consegui perceber quais as funções que tenho que chamar e com que parametros (além de que fazer "import Random" parece não funcionar)
     
    Última edição: 18 de Dezembro de 2008
  2. Baderous

    Baderous Banido

    Como é que estás a fazer esse processamento do I/O? Isso está dentro de um bloco do {...} (supondo que isso está feito com Monad IO)?
    Para gerar os números aleatórios podes usar as funções randomR e getStdRandom em conjunto:
    Código:
    num = getStdRandom(randomR (1,6))
    Isto gera um monad IO com um integer lá dentro, que está no intervalo [1,6].
    Tenta também fazer "import System.Random".
     
  3. MPalhas

    MPalhas Power Member

    para o IO criei uma função que me serve para a maioria dos casos que preciso. ela escreve a string com a pergunta, le o valor, verifica se ele está no intervalo permitido e se pode ser convertido para inteiro. caso seja devolve esse valor, senão volta a pedir

    Código:
    readOption :: String -> Int -> Int -> IO Int
    readOption question min max = do
                            putStr question 
                            op <- getChar
                            getLine
                            let opInt = (read [op])::Int
                            if (isValidInt [op] && opInt>=min && (opInt <=max || max<0)) then return (opInt)
                                                 else do
                                                        putStrLn "Invalid value!"
                                                        readOption question min max
    
    
    ----------------------------------------
    ----------------------------------------
    -- checks a string to see if it can be converted to Int.
    -- note, an empty string is not considered a correct value
    isValidInt :: String -> Bool
    isValidInt [] = False
    isValidInt (x:xs) = (ord x >= ord '0') && (ord x <= ord '9') &&
                        (if (xs==[]) then True
                                     else (isValidInt xs))
    já agora aquele getLine que eu pus a seguir ao getChar é para apanhar o ENTER que não é recebido pelo getChar. caso contrário iria interferir com o getChar/getLine que viesse a seguir. não sei se é a maneira mais correcta de fazer isso, mas funciona (também já verifiquei e não é isso que está a causar o problema)


    para ajudar a perceber o que acontece, isto é o aspecto do programa correndo pelo GHCi
    [​IMG]

    e isto é o que acontece ao correr exactamente a mesma versão, mas compilada pelo GHC (com o comando referido no outro post)
    [​IMG]
     
  4. Baderous

    Baderous Banido

    Relativamente a esta parte, não precisas desse artifício. Basta leres o valor com getLine em vez de getChar e depois tratas op como uma String:

    Código:
    readOption question min max = do
                            putStr question 
                            op <- getLine
                            let opInt = (read op)::Int
                            if (isValidInt op && opInt>=min && (opInt <=max || max<0)) then return (opInt)
    Quanto ao problema que te dá, não sei qual a causa, mas de certeza que não é do comando de compilação porque esse está correcto. Eu como costumo correr sempre o programa a partir do GHCi, não tenho desses problemas.
     
  5. MPalhas

    MPalhas Power Member

    só para ficar esclarecido... falei ontem com a prof e ela disse-me para usar o seguinte comando no inicio da função main:

    hSetBuffering stdout NoBuffering
     
  6. kripton2007

    kripton2007 Power Member

    Podem-me explicar como fazer o "modo gráfico" do programa???
    Por exemplo os menus e coisas assim...

    Cumps
     
  7. Baderous

    Baderous Banido

    É feito com o uso do monad IO, que é a forma que Haskell fornece para input/output. Podes usar a notação "do" para o efeito. Ficaria algo do género:

    Código:
    menu :: IO()
    menu = do { putStrLn "Menu principal\n";
            putStrLn "1 - Comecar a jogar";
            putStrLn "2 - Carregar jogo";
            putStrLn "3 - Sair";
            opcao <- getLine;
            case opcao of "1" -> putStrLn "Opcao 1 escolhida";
                  "2" -> putStrLn "Opcao 2 escolhida";
                  "3" -> putStrLn "Leaving..."
                  }
     
  8. kripton2007

    kripton2007 Power Member

    não consigo colocar isso a funcionar! :S
    Porque será?

    Já agora aplica-se o mesmo método para o tabuleiro?
     
  9. Baderous

    Baderous Banido

    É por causa de que aqui as coisas ficam desalinhadas. Aquelas 3 opções que vêm a seguir ao case têm de estar alinhadas.
     
  10. kripton2007

    kripton2007 Power Member

    yah yah.. ja reparei nisso! ;)
    obrigado

    e em relação ao tabuleiro do jogo? para o transformar num aspecto gráfico semelhante recorro ao mesmo método?


    edit: outra questão, ao correr o programa este não abre automaticamente o menu principal... sendo que tenho que introduzir a função "menu" para que este apareça. COmo faço para que ele apareça automaticamente?
     
    Última edição: 20 de Dezembro de 2008
  11. Baderous

    Baderous Banido

    Para isso, precisas de definir o tipo do tabuleiro como uma instância da classe Show e, nessa definição é que dizes como mostras o tabuleiro. A partir daí, sempre que numa função, devolveres o tipo do tabuleiro, ele aparecerá desenhado tal como tu o definiste na instância de Show.

    Experimenta ver aqui no 5.6.4.
     
  12. kripton2007

    kripton2007 Power Member

    Exacto, a dificuldade está mesmo em definir o tipo do tabuleiro como uma instância da classe Show... pois de instâncias e classes não percebo praticamente nada!

    :S

    Cumps
     

Partilhar esta Página