首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何打印棋盘及棋子位置表

如何打印棋盘及棋子位置表
EN

Stack Overflow用户
提问于 2019-11-03 20:24:01
回答 2查看 921关注 0票数 1

我被困在做作业上了。我必须编写一个包含两个字符串的函数。列表字符串包含3个字符:

  • 1是国际象棋棋子。'K‘- King,'Q’- Queen,'R‘- Rook,'B’-主教,'N‘-骑士,'P’-卒)
  • 第2列('a‘-’h‘)
  • 第3列是行号('1’- '8')

第一个字符串列表用于黑色片段,第二个字符串列表用于白片。板的自由字段由“.”表示。黑色棋子将上装,白色棋子将下套。

在船上打印1-8和and是不必要的。

这是必需的函数类型:

代码语言:javascript
复制
chess :: [String] -> [String] -> [String]

我们有这个打印功能

代码语言:javascript
复制
pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x))

这是IO示例:

代码语言:javascript
复制
Prelude> pp( chess["Ke1","Ra1","Rh1","Pa2","Be5"] ["Ke8","Ra8","Rh8","Pa7","Qd8","Bc8","Nb8"])
8rnbqk..r
7p.......
6........
5....B...
4........
3........
2P.......
1R...K..R
 abcdefgh

我试过什么?

代码语言:javascript
复制
chess :: [String] -> [String] -> [String]
chess _ [] = []
chess [] _ = []
chess ((x1:x2:x3:_):xs) ((y1:y2:y3:y3s):ys) 
    | 'a' == x2 && '1' == x3 = [x1] : chess xs ys
    | 'a' == y2 && '1' == y3 = [y1] : chess xs ys
    | 'b' == x2 && '1' == x3 = [x1] : chess xs ys
    | 'c' == x2 && '1' == x3 = [x1] : chess xs ys
    | 'd' == x2 && '1' == x3 = [x1] : chess xs ys
    | 'e' == x2 && '1' == x3 = [x1] : chess xs ys
    | 'e' == x2 && '1' == x3 = [x1] : chess xs ys
    | 'g' == x2 && '1' == x3 = [x1] : chess xs ys
    | otherwise = ['.'] : chess xs ys

输入为:国际象棋“Ke1”、"Ra1“、"Rh1”、"Pa2“、"Be1”输出:"K“、"R”、".“、".”、"B“。

再来一个..。

代码语言:javascript
复制
chess :: [String] -> [String] -> [String]
chess _ [] = []
chess [] _ = []
chess ((x1:x2:x3:_):xs) ((y1:y2:y3:y3s):ys) 
    | (x2 == 'a' && x3 == ['1']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['2']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['3']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['4']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['5']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['6']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['7']) = [x1] : chess (xs) (ys)
    | (x2 == 'a' && x3 == ['8']) = [x1] : chess (xs) (ys)
    | otherwise =  chess (xs) (ys)

输入:国际象棋“Ke1”、"Ra1“、"Rh1”、"Pa2“、"Be1”输出:K

他们都不像我想的那样工作。我试过先检查一行,然后检查每一列( each )--我认为这是对的,因为我需要打印“K.q.”、“P.”之类的内容--每个元素都是一行。如果我检查一下。黑色,如果没有黑色,也可以是白色的,所以我需要在打印'.‘之前检查第二个字符串中的白色片段。帮帮忙,我很困惑。我试过像4个函数那样编写代码,但它们花了超过4个小时。谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-03 22:16:23

前言。

我会给你一个概述,并允许我留下一些细节未打磨。请根据你的喜好调整我的建议。

我的回答将是这样的:

  1. 解释这个想法。
  2. 决定类型。
  3. 填入定义。

在现实生活中,我的过程是“辩证法”,所有这些思路都是通过尝试和错误同时成长的。

好主意。

我在想,给定两个字段,每个字段都有一些部分,我总是可以将这些字段“放在一起”,这样每个字段在接收到的字段中的位置都与在给定字段中的位置相同。(除非同一地方有两块,在这种情况下,行为是没有定义的。)一旦我可以用这种方式添加两个字段,我就可以添加任意数量的字段。而且用一块一块来生产一块地也不应该太难。这种技术被称为“折叠一个单样体”,你会看到它在Haskell中的大量使用。

战略。

我就是这样解决这个问题的:

piece.

  • Define

  • 定义了一个getPiece函数来读取一个getPiece函数,一个putPiece函数显示一个带有一个piece.

  • Define的字段,一个覆盖任意两个字段的overlay函数。

  • 折叠在这个函数的片段列表上。

类型。

代码语言:javascript
复制
type Piece = (Char, Int, Int)  -- Piece, row, column.

type Field = [String]  -- Rows.

getPiece :: String -> Piece

putPiece :: Piece -> Field

overlay :: Field -> Field -> Field

chess :: [String] -> [String] -> Field

这可能是值得你的时间,采取一张纸,并画一些图片,这些类型和功能如何可能连接。

定义。

代码语言:javascript
复制
getPiece :: String -> Piece
getPiece [v, x, y] = (piece, row, column)
  where
    piece  = v
    row    = (Char.ord y - 48)
    column = (Char.ord x - 96)

putPiece :: Piece -> Field
putPiece (v, x, y) = reverse
                   $ replaceAt (x - 1) (replaceAt (y - 1) v blank) (replicate 8 blank)
  where
    blank = replicate 8 ' '

    replaceAt :: Int -> a -> [a] -> [a]
    replaceAt i y xs =
      let (before, (_: after)) = List.splitAt i xs
      in  before ++ y: after

overlay :: Field -> Field -> Field
overlay u v = zipWith (zipWith overlayOne) u v
  where
    overlayOne ' ' y = y
    overlayOne  x  _ = x

chess :: [String] -> [String] -> Field
chess white black = List.foldl1' overlay . fmap putPiece $ pieces
  where
    pieces = fmap (makeWhite . getPiece) white ++ fmap getPiece black

    makeWhite :: Piece -> Piece
    makeWhite (c, x, y) = (Char.toLower c, x, y)

这里一个棘手的部分是如何将两个zipWith函数组合起来,以实现列表列表上的"zip“效果。还请注意,当我认为帮助函数replaceAt将使主函数变得非常简单时,我毫不犹豫地定义它。

结论。

我发现用正确的抽象工具箱来处理一个简单的问题是最舒服的。在这种情况下,我们使用了一个单半群(由overlay__定义)和一个递归方案(__List.foldl'是“变态”的一个实例)。我相信,在您的编程实践中,您会遇到更多的情况,在这些情况下,可以使用这些思想。

如果有些事情是不平易近人的,或者解释得不好,请给我留言。

好好享受Haskell!

P.S.也看到了另一个,algorithmically faster approach到一个非常相似的问题。

票数 2
EN

Stack Overflow用户

发布于 2022-11-01 13:19:49

考虑以这种方式构造代码:

代码语言:javascript
复制
-- given the three characters you describe, figure out the position and
-- piece name (do whatever you want with nonsense)
--
-- e.g. decode "Ke8" would return ((5, 8), 'k')
--      decode "Kz92" and decode "f" can return anything convenient
decode :: String -> ((Int, Int), Char)
decode = undefined

-- given a key, find all the values in a list associated with that key
--
-- e.g. assoc (5, 8) [((3, 4), 'q'), ((5, 8), 'k'), ((1, 2), 'p')]
-- would return ['k']
--
-- in non-homeworks, don't use this; instead, use the pre-existing
-- Prelude.lookup or the containers' package's Data.Map
assoc :: Eq k => k -> [(k, v)] -> [v]
assoc = undefined

-- if there's a single good choice for character at a given board position,
-- return it; otherwise, use a . to mark an empty space
--
-- e.g. choose ['k']      would return 'k'
--      choose []         would return '.'
--      choose ['k', 'P'] can return anything convenient
choose :: String -> Char
choose = undefined

chess :: [String] -> [String] -> [String]
chess white_ black_ = [[undefined | col <- [1..8]] | row <- [8,7..1]] where
    white = [(pos, toUpper piece) | (pos, piece) <- decode white_]
    black = [(pos, toLower piece) | (pos, piece) <- decode black_]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58684290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档