如何用棋子位置列表打印棋盘 [英] How to print chess board with list of positions of chess pieces

查看:50
本文介绍了如何用棋子位置列表打印棋盘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我坚持做家庭作业.我必须编写一个具有2 [String]的函数.列表字符串包含3个字符:

I'm stuck at doing my homework. I have to write a function that has 2 [String]. List string contains 3 chars:

  • 第一个棋子(例如'K'-King,'Q'-Queen,'R'-Rook,'B'-Bishops,'N'-Knights,'P'-Pawns)
  • 第二个指定列('a'-'h')
  • 第3个是行号('1'-'8')

第一个字符串列表用于BLACK件,第二个列表用于WHITE件.板的自由字段用."表示.黑色的棋子将大写,白色的棋子将小写.

First list of string is for BLACK pieces, the second is for WHITE pieces. Free fields of the boards are represented by '.'. Black chess pieces will be upper cased, white will be lower cased.

不需要在船上打印1-8和a-h.

Printing 1-8 and a-h on board isn't necessary.

这是必需的功能类型:

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

我们具有此打印功能

pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x))

这是IO示例:

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

我尝试了什么: 例如.

What have I tried: eg.

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"] ["Kb1","Ra8","Rh8","Pa7","Qd8","Bc8," Na1] 输出为:["K","R",.",.","B"]

Input was: chess["Ke1","Ra1","Rh1","Pa2","Be1"] ["Kb1","Ra8","Rh8","Pa7","Qd8","Bc8","Na1"] Output was: ["K","R",".",".","B"]

再来一次..

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"] ["Ke8","Ra8","Rh8","Pa7","Qd8","Bc8 ," Nb8] 输出: ķ [R R

Input: chess["Ke1","Ra1","Rh1","Pa2","Be1"] ["Ke8","Ra8","Rh8","Pa7","Qd8","Bc8","Nb8"] Output: K R R

他们都没有我想要的.我试过先检查一行,然后再检查每一列(ah)-我认为这是对的,因为我需要打印类似["K ... Q ...","P....... ]-每个元素都是一行. 如果我检查例如?黑色,如果没有黑色,则仍然会有白色,因此在打印."之前,我需要检查第二个字符串是否有白色碎片. 请帮助,我很困惑.我尝试编写类似4个函数的代码,但是它们花费了4个多小时.谢谢

None of them work as I wanted. I've tried checking one row first, then each column (a-h) - this is right I think, because I need to print something like ["K...Q...", "P......."] - each element is one row. What if I check eg. black, and if there's not black, there still can be white, so I need to check second string for white pieces before printing '.'. Please help, I'm confused. I've tried to code like 4 functions, but they took more than 4 hours. Thank you

推荐答案

前言.

我将为您提供概述,并允许我自己保留一些细节.请调整 我对您的建议.

Foreword.

I will give you an overview, and allow myself to leave some details unpolished. Please adjust my advice to your liking.

我的答案的结构如下:

  1. 解释这个想法.
  2. 决定策略.
  3. 起草类型.
  4. 填写定义.

在现实生活中,我的过程是方言" ,所有这些思路同时发展, 反复试验.

In real life my process is "dialectic", and all these lines of thought grow simultaneously, by trial and error.

我认为,给定两个字段,每个字段都有一些片段,我总是可以将这些字段放在顶部 彼此"",这样就可以在接收到的字段中找到与原样相同的每个部分 给定字段之一. (除非同一位置有两块,在这种情况下, 行为是不确定的.)一旦我可以通过这种方式添加两个字段,就可以添加任意数量的字段.而且它 用一块就不会产生太大的困难.这种技术称为"folding 一个monoid" ,您会发现它在Haskell中使用了很多.

I am thinking that, given two fields with some pieces each, I can always put these fields "on top of each other", so that every piece is found in the same place in the received field as it was in one of the given fields. (Unless there are two pieces on the same place, in which case the behaviour is undefined.) Once I can add two fields this way, I can add any number thereof. And it should not be too hard to produce a field with a single piece. This technique is called "folding a monoid" and you will see it used a lot in Haskell.

这是我将解决此问题的方法:

This is how I will solve this problem:

  • 定义getPiece函数以读取片段.
  • 定义putPiece函数以显示一个字段.
  • 定义一个overlay函数,该函数可以覆盖任意两个字段.
  • 使用此功能折叠作品列表.
  • Define a getPiece function to read a piece.
  • Define a putPiece function to display a field with one piece.
  • Define an overlay function that overlays any two fields.
  • Fold over the list of pieces with this function.
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

您可能需要花些时间来画些纸片,画出这些类型和功能可能如何连接的图片.

It may be worth your time to take a piece of paper and draw some pictures of how these types and functions may possibly connect.

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时,我毫不犹豫 认为它将使主要功能变得非常简单.

A tricky part here is how two zipWith functions are combined to achieve a "zip" effect on a list of lists. Notice also that I am not hesitating to define a helper function replaceAt when I think it will make the main function really simple.

我认为使用正确的工具箱来解决甚至是一个简单的问题也是最舒适的 抽象.在这种情况下,我们使用一个等号(由overlay定义)和一个递归 方案(List.foldl'是"catamorphism"的一个实例).我相信你会的 在您的编程实践中遇到了更多可以使用这些想法的情况.

I find it to be most comfortable to approach even a simple problem with the right toolbox of abstractions. In this case, we make use of a monoid (defined by overlay) and a recursion scheme (List.foldl' is an instance of "catamorphism"). I am sure you will meet many more cases in your programming practice where these ideas can be put to use.

如果无法解决或解释不清,请给我评论.

Leave me a comment if something is not approachable or poorly explained.

享受Haskell!

 

PS  另请参见,通过算法更快的方法来解决一个非常相似的问题.

P.S.   See also another, algorithmically faster approach to a very similar problem.

这篇关于如何用棋子位置列表打印棋盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆