【发布时间】:2021-03-06 21:04:12
【问题描述】:
module TicTacToe (tictactoe) where
import Control.Applicative
import Control.Monad
import Control.Monad.State
import Data.Char
import Data.List
import Text.Printf
tictactoe :: IO ()
tictactoe = do
let grid = [' ',' ',' ',' ',' ',' ',' ',' ',' ']
let count = 0
output_grid grid count
output_grid :: String -> Int -> IO()
output_grid grid count = do
putStr ".---.---.---.\n"
printf "| %c | %c | %c |\n" (grid !! 0) (grid !! 1) (grid !! 2)
putStr ".---.---.---.\n"
printf "| %c | %c | %c |\n" (grid !! 3) (grid !! 4) (grid !! 5)
putStr ".---.---.---.\n"
printf "| %c | %c | %c |\n" (grid !! 6) (grid !! 7) (grid !! 8)
putStr ".---.---.---.\n" -- output grid
if count `mod` 2 == 0
then putStr "O MOVE\n"
else putStr "X MOVE\n" -- tell player which to move
if count `mod` 2 == 0
then player_input grid 'O' count
else player_input grid 'X' count
player_input :: String -> Char -> Int -> IO()
player_input grid sym count = do
inp <- getLine
let x = (read (takeWhile (/= ' ') inp) :: Int)
let y = (read (drop 1 (dropWhile (/= ' ') inp)) :: Int)
if (x < 1) || (x > 3) || (y < 1) || (y > 3)
then putStr "INVALID POSITION \n"
else return ()
if (x < 1) || (x > 3) || (y < 1) || (y > 3)
then player_input grid sym count
else return ()
let target = (x - 1) * 3 + (y - 1)
if (grid !! target /= ' ')
then putStr "INVALID POSITION \n"
else return ()
if (grid !! target /= ' ')
then player_input grid sym count
else return ()
let new_grid = (take target grid) ++ [sym] ++ (drop (target + 1) grid)
if (check_win new_grid sym)
then output_terminate new_grid sym
else if count == 8
then output_terminate new_grid 'D'
else output_grid new_grid (count + 1)
check_win :: String -> Char -> Bool
check_win grid sym = do
if (grid !! 0 == sym) && (grid !! 1 == sym) && (grid !! 2 == sym)
then True
else if (grid !! 3 == sym) && (grid !! 4 == sym) && (grid !! 5 == sym)
then True
else if (grid !! 6 == sym) && (grid !! 7 == sym) && (grid !! 8 == sym)
then True
else if (grid !! 0 == sym) && (grid !! 3 == sym) && (grid !! 6 == sym)
then True
else if (grid !! 1 == sym) && (grid !! 4 == sym) && (grid !! 7 == sym)
then True
else if (grid !! 2 == sym) && (grid !! 5 == sym) && (grid !! 8 == sym)
then True
else if (grid !! 0 == sym) && (grid !! 4 == sym) && (grid !! 8 == sym)
then True
else if (grid !! 2 == sym) && (grid !! 4 == sym) && (grid !! 6 == sym)
then True
else False
output_terminate :: String -> Char -> IO()
output_terminate grid winner = do
putStr ".---.---.---.\n"
printf "| %c | %c | %c |\n" (grid !! 0) (grid !! 1) (grid !! 2)
putStr ".---.---.---.\n"
printf "| %c | %c | %c |\n" (grid !! 3) (grid !! 4) (grid !! 5)
putStr ".---.---.---.\n"
printf "| %c | %c | %c |\n" (grid !! 6) (grid !! 7) (grid !! 8)
putStr ".---.---.---.\n"
if winner == 'D'
then putStr "DRAW \n"
else printf "%c WINS \n" winner
我是 Haskell 的初学者,我正在开发一个小型井字游戏。这是我用来让玩家输入符号坐标的函数,比如2 2(这意味着符号位于中心),他们想要放入。我想在上面添加一些验证功能。到目前为止,它只能处理 12 2 等超出范围的输入,并避免覆盖已占用的网格。但我想做更多。例如,2(只有 1 个输入)、1 2 xy(xy 不应该在这里)和 abcde(随机输入不做感觉)。我想让程序也能够处理这些无效输入。
【问题讨论】:
-
能否包含其他函数(
output_terminate、output_grid、main和check_win)以便我们运行程序?这对测试有很大帮助。 -
1.
return意味着与大多数其他语言不同的东西,它不会提前退出。 2. 解析,不验证。 lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate -
我已经用其他函数更新了代码
标签: validation parsing haskell types io