チェッカーのポーンのジャンプを分析する関数を書く方法を知らないので、私は助けを求めたいと思います。 私は立ち往生しており、非常に感謝しています。ハスケルチェッカー - 可能なジャンプのリストを返す関数を書く方法
チェス盤とチェス盤を表すタプルのリストをリストとして作成しました。
これは、チェス盤を画面に表示するためのフォームです。 "\" pppp \ npppp \ np.ppp \ n ........ \ n ........ \ nP.PPP \ nPPPP \ nP.PPP \ n ""
これは私が作品の可能な動きを分析するために使用する形式です: [((1、 1)、 'p')、((1,2)、 '。')、((1,3)、 'p')、((1,4)、 '。')、((1,5) 、(p))、((1,6)、 '。')、((1,7)、 'p')、((1,8)、 '。')、((2,1) ((2,3)、 '。')、((2,4)、 'p')、((2,5)、 '。')、((2,2)、 'p' )、((2,6)、 'p')、((2,7)、 '。')、((2,8)、 'p')、((3,1)、 'p')、 ((3,3)、 'p')、((3,4)、 '。')、((3,5)、 'p')、((3,2)、 ' (3、6)、(7)、(8)、(9)、(10) ((4,4)、 '。')、((4,5)、 '。')、((4,6)、 ' ((5,1)、 '。')、((5,2)、 '')、((4,7)、 ' ')、((5,3)、'。 ')、((5,4)、'。 ')、((5,5)、'。 ')、((5,6)、'。 )、(( ((6,1)、 '。')、((6,2)、 '。')、((6,7)、 ((6,6)、 '。')、((6,5)、 '。')、((6,6)、 '。')、((6,7) ((7,1)、 'P')、((7,2)、 '。')、((7,3)、 ' (7,6)、 '。')、((7,7)、 'P')、((7,4)、 ' )、((8,8)、 '。')、((8,1)、 '。')、((8,2)、 'P')、((8,3)、 ' ((8,4)、 'P')、((8,5)、 '。')、((8,6)、 'P')、((8,7)、 ' 8,8)、 'P')]
これは私がこれまでに書いたコードです:
module Checkers where
import Test.HUnit
import Test.QuickCheck
import Data.Char
import Data.Maybe (fromJust)
import Control.Error.Util (note)
import Data.Maybe (listToMaybe)
import Data.Char(isDigit)
import Data.String
import Data.List
import Prelude
type Board = [[Square]]
type Square = Maybe Piece
data Piece = Piece PColor PType deriving (Show)
data PColor = White | Black deriving (Show)
data PType = Pawn | Queen deriving (Show)
typeList:: [(Char, PType)]
typeList = [('p', Pawn), ('q', Queen)]
initialBoard = unlines ["p.p.p.p."
,".p.p.p.p"
,"p.p.p.p."
,"........"
,"........"
,"........"
,"P.P.P.P."
,".P.P.P.P"
,"P.P.P.P." ]
board2 = unlines ["p.p.p.p."
,".p.p.p.p"
,"p.p.p.p."
,".P.P.P.."
,"........"
,"........"
,"P...P.P."
,".P.P.P.P"
,"P.P.P.P."]
showBoard :: Board -> String
showBoard = unlines. map showRow
where showRow = map showSquare
readBoard :: String -> Either String Board
readBoard = (mapM . mapM) readSquare . lines
showSquare:: Square -> Char
-- showSquare Nothing = ' '
-- showSquare (Just p) = showPiece p
showSquare = maybe ' ' showPiece
readSquare:: Char -> Either String Square
readSquare '.' = return Nothing
readSquare c = note errorMsg $ fmap return (readPiece c)
where errorMsg = "Error reading square '" ++ show C++ "' is not a valid square"
--readSquare:: Char -> Square
--readSquare c = readPiece c
showPiece:: Piece -> Char
showPiece (Piece White Pawn) = 'P'
showPiece (Piece Black Pawn) = 'p'
showPiece (Piece White Queen) = 'Q'
showPiece (Piece Black Queen) = 'q'
readPiece:: Char -> Maybe Piece
readPiece c = fmap makePiece lookupType
where color = if isUpper c then White else Black
lookupType = lookup (toLower c) typeList
makePiece = Piece color
--readPiece 'P' = Just (Piece White Pawn)
--readPiece 'p' = Just (Piece Black Pawn)
--readPiece 'Q' = Just (Piece White Queen)
--readPiece 'q' = Just (Piece Black Queen)
--readPiece _ = Nothing
--transform chessboard into a list of tuples to analyze possible kills
--String or Int?
testString = "hello world 13 i am a new 37 developer 82"
data StringOrInt = S String | I Int
deriving (Eq,Ord,Show)
readInt :: String -> Int
readInt = read
--convert String into tuples
--1. convert chessBoard into a list
myShow :: String -> String
myShow s = concat ["[", intersperse ',' s, "]"]
isSlash x = x=='\\'
deleteAllInstances :: Eq a => a -> [a] -> [a]
deleteAllInstances a xs = filter (/= a) xs
clearBoardList_ s = deleteAllInstances '\n' $ myShow $ s
clearBoardList__ s = deleteAllInstances '[' $ clearBoardList_ s
clearBoardList s = deleteAllInstances ',' $ clearBoardList__ s
--2 zip with coordinates (1,1), (1,2).... (8,8)
makeL = [(x,y)| x<-[1..8], y<-[1..8]]
makeTuplesBoard s = zip makeL s
testList = makeList initialBoard
testList2 = makeList board2
--3 all together
makeList s = makeTuplesBoard $ clearBoardList s --xy coordinates of pawns
--is there my Pawn?
isMyPawn ((x,y),z) = (z=='p' || z=='q')
matchFirst (a,b) ((c,d),_) = (a,b) == (c,d)
whatIsThere (a,b) list = eliminate $ find (matchFirst (a,b)) list --test: whatIsThere (1,1) $ makeList initialBoard
eliminate (Just a) = a
whichPiece (a,b) list = snd $ snd (whatIsThere (a,b) $ makeTuplesBoard list) --shows what is on a specific field
isThereSth (a,b) list = whichPiece (a,b) list == 'p' || whichPiece (a,b) list == 'P' || whichPiece (a,b) list == 'q' ||whichPiece (a,b) list == 'Q' --isThereSth (1,1) $ makeList initialBoard
isThereMyPawn (a,b) list = ((whichPiece (a,b) list == 'p'), list) --whichPiece (a,b) list == ((a,b),'p')
isThereMyQueen (a,b) list = ((whichPiece (a,b) list == 'q'), list)
isThereOtherPawn (a,b) list = ((whichPiece (a,b) list == 'P'), list)
isThereOtherQueen (a,b) list = ((whichPiece (a,b) list == 'Q'), list)
--remove a figure from its place and put somewhere else
removePiece (a,b) list = map (\ x -> if matchFirst (a,b) x then ((a,b),'.') else x) list
removeMyPawn (a,b) list = removePiece (a,b) list
removeMyQueen (a,b) list = removePiece (a,b) list
removeOtherPawn (a,b) list = removePiece (a,b) list
removeOtherQueen (a,b) list = removePiece (a,b) list
isWithinLimit (a,b)
| not ((a>0) && (a<9) && (b>0) && (b<9)) = False
| otherwise = True
isWithinLimit1 (a,b) list
| not ((a>0) && (a<9) && (b>0) && (b<9)) = (False, list)
| otherwise = (True, list)
putPiece (a,b) piece list = map (\ x -> if matchFirst (a,b) x then ((a,b),piece) else x) list --map (\ x -> if matchFirst (a,b) x then ((a,b),'.') else x) list
--test: movePiece (1,1) (1,2) $ makeTuplesBoard initialBoard
movePiece (a,b) (c,d) list = removePiece (a,b) $ putPiece (c,d) (whichPiece (a,b) $ makeTuplesBoard initialBoard) (makeTuplesBoard initialBoard)
--putADot (a,b) list = replace (matchFirst (a,b)) list
--swapTuples (a,b) (c,d) list =
--move (a,b) (c,d) list =
-- | (isThereSth (a,b) == False) = list
-- | otherwise =
isThereOtherPawn2 (a,b) list x
| (x==True) = fst $ isThereOtherPawn (a,b) list
| otherwise = False
isWithinLimit2 (a,b) list x
| (x==True) = fst $ isWithinLimit1 (a,b) list
| otherwise = False
isFree2 (a,b) list x
| (x==True) = isFree (a,b) list
| otherwise = False
isThereMyPawn2 (a,b) list x
| (x==True) = fst $ isThereMyPawn (a,b) list
| otherwise = False
isFree (a,b) list = not (isThereSth (a,b) list)
isJumpLFPossible (a,b) list = isThereMyPawn2 (a,b) list $ (isFree2 (a+2,b-2) list $ isWithinLimit2 (a+2,b-2) testList $ isThereOtherPawn2 (a+1,b-1) list $ fst $ isWithinLimit1 (a+1,b-1) list) --test: isFree2 (3,4) testList $ isWithinLimit2 (3,4) testList $ isThereOtherPawn2 (3,4) testList $ fst $ isWithinLimit1 (2,3) testList
isJumpRFPossible (a,b) list = isThereMyPawn2 (a,b) list $ (isFree2 (a+2,b+2) list $ isWithinLimit2 (a+2,b+2) testList $ isThereOtherPawn2 (a+1,b+1) list $ fst $ isWithinLimit1 (a+1,b+1) list) --test: isFree2 (3,4) testList $ isWithinLimit2 (3,4) testList $ isThereOtherPawn2 (3,4) testList $ fst $ isWithinLimit1 (2,3) testList
-- checking whether my Pawn has any jump possiblitiy - one move
canJumpLF (a,b) list
| (isJumpLFPossible (a,b) list) = [(a,b),(a+2, b-2)]
| otherwise = [] --test: canJump (1,1) testBoard
canJumpRF (a,b) list
| (isJumpRFPossible (a,b) list) = [(a,b),(a+2, b+2)]
| otherwise = [] --test: canJump (1,1) testBoard
isFree (a,b) list = not (isThereSth (a,b) list)
-- recursive check whether and which kills are possible for my Pawn
--canJump (a,b) list
-- | (fst (canJumpLF (a,b) list)) = snd (canJump (a+2, b-2) list)
-- | (fst (canJumpRF (a,b) list)) = snd (canJump (a+2, b+2) list)
-- | otherwise = []
replaceTuple tups old new = map check tups where
check tup | tup == old = new
| otherwise = tup
--movePawn (x,y) (a,b) = if (isMyPawn(x,y)
--replacePawn list = replaceTuple $ ((x,y),_) ((x,y),'.') list
--analyze possible moves of pawn
--Tests
tests:: Test
tests = TestList $ map TestCase
[assertEqual "odd tests here" 1(1 :: Int)]
prop_empty :: Int -> Bool
prop_empty c1 = (c1::Int) == c1
runTest = do
return()
main:: IO()
main = runTest
次のように私の問題があります。すべての可能なジャンプシーケンスのリストを返す関数が必要です。私はそれが再帰関数である必要があると思う。 (1)右、左へのジャンプが可能かどうかを確認する。 (2)それが可能であれば、ポーンが(1) (3)の後に取る位置から再帰的に実行する[(a、b)、(c、d)、(e、f)、(g、h)]、[(a、b)、(p、r)]のジャンプシーケンスを表すタプルリストのリスト(4)ポーンがチェス盤の反対側に到達した場合、可能なジャンプがあれば後方にジャンプすることができる (5)ifポーンはボードの終わりに達し、ジャンプができないので、それは女王に変わる(これはこの機能に含めるべきかどうかわからない - おそらくない) -
つまり、位置から(a、b)可能な限りすべて分析したいすべての可能なジャンプシーケンスのリストを返す関数を作成します。 ... 変更後に問題は残りますが、簡単に説明できます:
機能canOneJump(a、b)ボードは、ジャンプした後にポーンができる可能性のある場所のリストを返します。つまり、関数はジャンプの後にポーンができる行と列を表す各タプルを返す[(1,2)、(2,3)、(4,5)]。 私は、ポーンの最初の位置(a、b)からのジャンプのリストを(リストとして与えられたチェス盤の状況に基づいて)作成するはずですが、機能しません。おそらく、誰かが私にこの機能を修正してもらえるように助けてくれるかもしれません。 異なるジャンプシーケンスを表すジャンプシーケンス[[(3,3)、(5,5)、(7,3)]、[(3,3)、(5,1)]]利用可能です。
canJump v board =
map (v:) w
where
list = listPlacesAfterMyPawnJump v board
w = concat $ map (flip canJump board) list
私は、1つのジャンプを記述するタプルのリストを生成する関数を作成しました。それらはcanJumpLFとcanJumpRFと呼ばれます。私の問題は、タプルのリストの大きなリストを生成する再帰関数を書く方法を知らないということです。 canJump(a、b)リスト | (canJumpLF(a、b)list)== [])=(canJumpLF(a、b)リスト):(canJump(a + 2、b-2)リスト) | (canJumpRF(a、b)リスト)== []))=(canJumpRF(a、b)リスト):(canJump(a + 2、b + 2)リスト) |そうでなければ= [] 可能なジャンプの最初のシーケンスのみを返し、残りはスキップします。 – Joanna
最初に 'singleJumps'関数で作業し、次にマルチジャンプ/再帰問題を解きます。 – ErikR
このバージョンの関数は、開始点から2つの可能なジャンプを返しますが、シーケンスを生成しません:canJump1(a、b)list =((canJumpLF(a、b)list):(canJump(a + 2、b-2) )list))++((canJumpRF(a、b)list):(canJump(a + 2、b + 2)list)) – Joanna