You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 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.
  2. Alternating Players: Using cycle ['x', 'o'] ensures moves alternate between the two players correctly.
  3. Border Generation:
    • Horizontal separators (like ---+---+--- for a 3-column board) are created with intercalate "+" to join segments of ---.
    • Each row is wrapped in | and individual cells are formatted as [c] to keep alignment consistent.
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:38:08