Haskell实现井字棋ticktack函数生成游戏状态的问题
Fixing the
ticktack Function in Haskell: Generating a Single Game Board State Let's walk through fixing your ticktack function. Your current code has a few key issues:
- It recursively generates a new board for every move, resulting in a list of multiple boards instead of the final game state.
- It doesn't alternate between 'x' and 'o' players (all moves are marked as 'x').
- It doesn't add the required borders using '-' and '|'.
Here's a corrected implementation that addresses all these problems:
type Result = [String] ticktack :: (Int, Int) -> [(Int, Int)] -> Result ticktack (rows, cols) moves = -- Handle invalid board dimensions (like (0,0)) if rows <= 0 || cols <= 0 then [] else let -- Assign 'x' to even-indexed moves, 'o' to odd-indexed assignedMoves = zip moves (cycle ['x', 'o']) -- Create an empty board filled with spaces emptyBoard = replicate rows (replicate cols ' ') -- Update the empty board with all moves finalBoard = updateBoard emptyBoard assignedMoves in -- Add borders to the final board addBorders finalBoard where -- Update the board with a list of (position, player) pairs updateBoard :: [[Char]] -> [((Int, Int), Char)] -> [[Char]] updateBoard board [] = board updateBoard board (((row, col), player):rest) = -- Convert 1-based coordinates to 0-based for list indexing let updatedRow = take (row - 1) board ++ [updateColumn (board !! (row - 1)) (col - 1) player] ++ drop row board in updateBoard updatedRow rest -- Update a single column in a row updateColumn :: [Char] -> Int -> Char -> [Char] updateColumn row idx player = take idx row ++ [player] ++ drop (idx + 1) row -- Add borders using '-' and '|' addBorders :: [[Char]] -> [String] addBorders board = let colCount = length (head board) -- Generate the horizontal separator line separator = intercalate "+" (replicate colCount "---") -- Format a single row with vertical borders formatRow row = "|" ++ intercalate "|" (map (\c -> " " ++ [c] ++ " ") row) ++ "|" in -- Combine separator, formatted rows, and final separator [separator] ++ intercalate [separator] (map formatRow board) ++ [separator] -- Helper function to print the board pp :: Result -> IO () pp = putStr . unlines
Key Improvements Explained:
- Single Final Board: Instead of generating a new board for each move, we start with an empty board and apply all moves sequentially to get the final state.
- Alternating Players: Using
cycle ['x', 'o']ensures moves alternate between the two players correctly. - Border Generation:
- Horizontal separators (like
---+---+---for a 3-column board) are created withintercalate "+"to join segments of---. - Each row is wrapped in
|and individual cells are formatted as[c]to keep alignment consistent.
- Horizontal separators (like
- Coordinate Handling: Converts 1-based input coordinates to 0-based list indices (since Haskell lists use 0-based indexing).
Example Usage:
If you run:
pp $ ticktack (3,3) [(1,2), (2,1), (3,3)]
You'll get this output:
---+---+--- | | x | | ---+---+--- | o | | | ---+---+--- | | | x | ---+---+---
内容的提问来源于stack exchange,提问作者Weliras
相关产品推荐
相关产品推荐

