2016-05-29 4 views
2

チェッカーのポーンのジャンプを分析する関数を書く方法を知らないので、私は助けを求めたいと思います。 私は立ち往生しており、非常に感謝しています。ハスケルチェッカー - 可能なジャンプのリストを返す関数を書く方法

チェス盤とチェス盤を表すタプルのリストをリストとして作成しました。

これは、チェス盤を画面に表示するためのフォームです。 "\" 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 

答えて

3

まず私は、コードスタイル、組織、および他のチップ上のいくつかのポインタを取得するためにCode Review Stackexchangeにあなたのコードを投稿お勧めしたいです。彼らは作業コードの見直しに関するルールしか持っていないので、あなたが持っているコードを見直すよう依頼してください。

ここでは、どのように進むのかの概要を説明します。

ソリューションは、これらの型定義を理解することが非常に簡単になります:あなたが既に持っている機能を使用して

type Coord = (Int,Int) 
type CoordBoard = [ (Coord, Char) ] 

ステップ1、特定の広場からのすべての可能な単一のジャンプを返すように関数を記述:

singleJumps :: (Coord, CoordBoard) -> [ (Coord, CoordBoard) ] 

更新されたCoordBoardを返すことに注意してください。つまり、ジャンプした部分が削除され、ジャンパーが移動したボードです。起こりうるジャンプがない場合は空のリストを返します。

ステップ2.そして出発正方形からすべての可能なジャンプをパスを見つけるために関数を書く:

multiJumps :: (Coord, CoordBoard) -> [ ([Coord], CoordBoard) ] 

これはまた、実行ジャンプ移動とCoordBoardを返します。 multiJumpsの背後にある考え方は次のとおりです。

for each possible single jump (rc, b): 
    for each possible multi jump (path, b') starting from (rc,b): 
    return the path (rc:path) and ending board configuration b' 

これは再帰が起こる場所です。

+0

私は、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

+0

最初に 'singleJumps'関数で作業し、次にマルチジャンプ/再帰問題を解きます。 – ErikR

+0

このバージョンの関数は、開始点から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

0

最後に、私は問題を解決しましたが、いくつかの機能を変更したり、新しい機能を書き込んだりする必要がありました(ヒント:multijumpsはリストの理解として書くことができます)。

canJumpLB (a,b) list 
     | (isJumpLBPossible (a,b) list) = [(a,b),(a-2, b-2)] 
     | otherwise = [] 

canJumpRB (a,b) list 
     | (isJumpRBPossible (a,b) list) = [(a,b),(a-2, b+2)] 
     | otherwise = [] 

canOneJump (a,b) list =filter (/=[]) $filter (/=[]) $filter (/=[]) [canJumpLF (a,b) list] ++ [canJumpRF (a,b) list] 


canImakeAnotherJump list listOfLists = concat $ [canOneJump (x!!((length x)-1)) list | x <- listOfLists] 
anotherJump list listOfLists = combine (canImakeAnotherJump list listOfLists) listOfLists [] 

jumpSequences v list [] 
     | (canOneJump v list == []) = [] 
     | otherwise = jumpSequences v list (canOneJump v list) 

jumpSequences v list results 
     | ((canImakeAnotherJump list results) == []) = results 
     | otherwise = jumpSequences v list (anotherJump list results) 

jumpSequences関数は、特定の位置からのジャンプのすべてのシーケンスを示します。私のポニーは後方にジャンプしないので、私はチェス盤を更新しません。

関連する問題