리버시 엔진 구현


12

이 골프에서 당신의 임무는 리버시 게임 (othello) 의 움직임을 취하고 그 결과를 사용자에게 표시 하는 프로그램을 작성하는 것 입니다.

입력

[0-7] 범위에서 가져온 일련의 숫자. 각 숫자 쌍은 먼저 X 좌표를 나타내고 Y 좌표를 나타냅니다. 해당 범위에없는 문자는 무시해야합니다.

산출

입력이 끝날 때 누가 이끄는가를 포함하여 게임 결과의 시각적 표현. 그래픽 또는 키 스트로크 출력 일 수 있지만 게임의 시각적 격자 여야하며 검은 색, 흰색 및 빈에 대한 고유 한 문자 / 그래픽 기호가 있어야합니다.

또한 코드는 오류 메시지를 출력하고 불법 이동이 입력 될 때 중지됩니다 (동일한 사각형 또는 타일이 뒤집 히지 않는 사각형).

건너 뛰기 는 정상적으로 처리해야합니다. 스킵은 한 컬러가 합법적으로 움직이지 않고 턴을 스킵하고 다른 플레이어가 플레이 할 때 발생합니다.

항상 검은 색이 먼저갑니다.

23
........
........
........
..bbb...
...bw...
........
........
........
b

232425140504032627
........
........
........
b.bbb...
bbbww...
b.b.....
..b.....
..b.....
b

2324322513
........
........
........
..bbb...
..www...
........
........
........
e

23242555
........
........
........
..bbb...
..bbw...
..b.....
........
........
e

조각이 이동 한 지점을 어떻게 알 수 있습니까? 첫 번째 예에서는 가능성이 1이지만 항상 가능성이 1이라고 가정하는 것이 안전합니까?
Teun Pronk

질문을 이해하지 못해 죄송합니다
durron597

3
@TeunPronk는 리버시로 이동하지 않습니다. 각 플레이어는 차례대로 보드에 조각을 추가합니다. 나는 그것이 당신의 질문에 대답해야한다고 생각합니다.
shiona

둘 이상의 숫자 쌍을 어떻게 해석해야합니까?
golfer9338

불법 이동이 입력 된 경우, 마지막 유효 이동에서 필드 상태를 표시해야합니까, 아니면 오류 메시지 만 표시하기에 충분합니까?
marinus 2018 년

답변:


2

하스켈-1493 바이트

이 버전에는 자세한 오류 메시지가 없으며 출력이 훨씬 기본적입니다. 주요 변화는 교체되었다 Either String aMaybe a그들은 모두 모나드이기 때문에, 이것은 단순히 교환에 의해 acheived 한 Right aJust aLeft String함께 Nothing.

{-# LANGUAGE OverloadedStrings #-}
import Prelude hiding ((>>=),concatMap,filter,foldl,head,last,map,null,replicate)
import Control.Applicative hiding (empty)
import Control.Monad hiding (replicateM)
import Data.Vector hiding ((++),concat,foldM,reverse,zip)
main=getLine>>= \s->h$t<$>(zip$cycle[w,v])<$>b s>>= \m->u(\b(c,x)->case d b x c of r@(Just _)->r;Nothing->if not$null$findIndices(\y->e$d b y c)$t[(x,y)|x<-[0..7],y<-[0..7]];then é;else d b x$not c)k$n m
 where b(x:y:s)=(:)(read [x],read [y])<$>b s;b(_:_)=é;b[]=è[];d b z c=let d=join$m(f b z c)$m(\v->(head v,last v))$replicateM 2$t[-1,0,1];in if null d;then Nothing;else u(\b (x,y)->case b!?y of Just r->(case r!?x of Just _->è$b//[(y,r//[(x c)])];Nothing->é);Nothing->é)b$n$d`snoc`z;e(Nothing)=w;e(Just _)=v;f b(x,y)c z@(u,v)=let r=x+u;s=y+v;t=(r,s);in (case g b t of Just(Just d)->if d==c;then l;else (case g b (r+u,s+v) of Just(Just _)->t`cons`f b t c z;_->l);Just(Nothing)->l;Nothing->l);g b(x,y)=(case b!?y of Just col->col!?x;Nothing->é);h(Just b)=p$(o$n$m(\r->o(n$m(\c->case c of Just False->"B";Just True->"W";Nothing->".")r)++"\n")b)++i(q(\(w,b)(rw,rb)->(w+rw,b+rb))(0,0)$m(\r->q(\s@(w,b)c->case c of Just True->(w+1,b);Just False->(w,b+1);_->s)(0,0)r)b);h Nothing=p"e";i(w,b)|w>b="W"++s w|b>w="B"++s b|v="N"++s(w+b);j=r 8 é;k=r 8 j//[(3,j//[(3 v),(4 w)]),(4,j//[(3 w),(4 v)])];l=empty;m=map;n=toList;o=concat;p=putStrLn;q=foldl;r=replicate;s=show;t=fromList;u=foldM;v=True;w=False;é=Nothing;è=Just
$ printf "232425140504032627" | ./nano-rve 
........
........
........
B.BBB...
BBBWW...
B.B.....
..B.....
..B.....
B11

원본 버전-4533 바이트

경쟁이있을 때는 골프를하겠습니다! 편집 이 도착했습니다

{-# LANGUAGE OverloadedStrings #-}
import Prelude hiding ((>>=),concatMap,filter,foldl,map,null,replicate)
import Control.Applicative hiding (empty)
import Control.Monad
import Data.Either
import Data.Vector hiding ((++),concat,foldM,reverse,zip)

type Case = Maybe Bool
type Board = Vector (Vector Case)
type Coord = (Int,Int)

-- fmap (toList) $ replicateM 2 [-1,0,1] -- minus (0,0)
directions :: Vector Coord
directions = fromList [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]

--  [(x,y) | x <- [0..7], y <- [0..7]]
allCoords :: Vector Coord
allCoords = fromList [(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(2,0),(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(3,0),(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(3,7),(4,0),(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(5,0),(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(6,0),(6,1),(6,2),(6,3),(6,4),(6,5),(6,6),(6,7),(7,0),(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7)]


initBoard :: Board
initBoard = vs // [(3,v1),(4,v2)]
    where va = replicate 8 Nothing
          v1 = va // [(3,Just True),(4,Just False)]
          v2 = va // [(3,Just False),(4,Just True)]
          vs = replicate 8 va

showBoard :: Board -> String
showBoard b = (concat $ toList $ map (showRow) b) ++ (showScore b)
    where showCase :: Case -> String
          showCase c = case c of 
              Just False -> "░B"
              Just True -> "▓W"
              Nothing -> "██"
          showRow :: Vector Case -> String
          showRow r = concat (toList $ map (showCase) r) ++ "\n"

showScore :: Board -> String
showScore b = winner score ++ "\n"
    where scoreCase :: (Int,Int) -> (Maybe Bool) -> (Int,Int)
          scoreCase (w,b) (Just True) = (w+1,b)
          scoreCase (w,b) (Just False) = (w,b+1)
          scoreCase s _ = s
          scoreRow :: Vector Case -> (Int,Int)
          scoreRow r = foldl (scoreCase) (0,0) r
          score :: (Int,Int)
          score = foldl (\(w,b) (rw,rb) -> (w+rw,b+rb)) (0,0) $ map (scoreRow) b
          winner :: (Int,Int) -> String
          winner (w,b) | w > b = "White with " ++ show w ++ " against Black with " ++ show b ++ "."
                       | b > w = "Black with " ++ show b ++ " against White with " ++ show w ++ "."
                       | otherwise = "Nobody with " ++ show (w+b) ++ "."

printBoard :: Board -> IO ()
printBoard b = putStrLn $ showBoard b
pm :: Either String Board -> IO ()
pm (Right b) = printBoard b
pm (Left s)  = putStrLn s

lookupBoard :: Board -> Coord -> Either String Case
lookupBoard b (x,y) = case b !? y of
    Just col -> case col !? x of
        Just c -> Right c
        Nothing -> Left "x is out of bounds"
    Nothing -> Left "y is out of bounds"

updateBoard :: Board -> Coord -> Bool -> Either String Board
updateBoard b (x,y) c = case b !? y of
    Just r -> case r !? x of
        Just _ -> Right $ b // [(y,r // [(x,Just c)])] 
        Nothing -> Left "x is out of bounds"
    Nothing -> Left "y is out of bounds"

makePath :: Board -> Coord -> Bool -> Coord -> Vector Coord
makePath b (x,y) c (px,py) = case lookupBoard b (nx,ny) of
        Right (Just pc) -> if pc == c
            then empty
            else case lookupBoard b (nx+px,ny+py) of
                Right (Just _) -> (nx,ny) `cons` makePath b (nx,ny) c (px,py)
                _ -> empty
        Right (Nothing) -> empty
        Left _ -> empty
    where nx = x+px
          ny = y+py

makeMove :: Board -> Coord -> Bool -> Either String Board
makeMove b xy@(x,y) c = if null cases 
        then Left $ "impossible move " ++ show xy ++ "."
        else foldM (\ob (cx,cy) -> updateBoard ob (cx,cy) c) b $ toList $ cases `snoc` (x,y)
    where cases = join $ map (makePath b (x,y) c) directions

makeMoves :: Board -> Vector (Bool,Coord) -> Either String Board
makeMoves b ms = foldM (\ob (c,xy) -> case makeMove ob xy c of
    rb@(Right _) -> rb
    Left _ -> if not $ null $ findIndices (\xy -> isRight $ makeMove ob xy c) allCoords
        then Left $ "wrong move " ++ show xy ++ "."
        else makeMove ob xy (not c)) b $ toList ms


movesFromString :: String -> Either String (Vector (Bool,Coord))
movesFromString cs = fromList <$> (zip $ cycle [False,True]) <$> coords cs
    where coords (x:y:cs) = (:) (read [x],read [y]) <$> coords cs
          coords (_:cs) = Left "invalid coordinates string"
          coords [] = Right []

isRight :: Either a b -> Bool
isRight (Left _) = False
isRight (Right _) = True

main=getLine>>= \s->pm$movesFromString s>>=makeMoves initBoard

참고 : 두 번째 예는 2324251 4 0504032627이어야합니다.

테스트

눈 화상을 방지하기위한 스크린 샷

$ printf "232425140504032627" | ./rve

시험 1

$ printf "2324" | ./rve

테스트 2

$ printf "1" | ./rve
invalid coordinates string
$ printf "24" | ./rve
wrong move (2,4).

당신이 impossible move (x,y)innardics (프로그램의 내장 함수에서 사용하지 말아야 할 함수)를 사용할 때 얻을 수 있습니다 x/y is out of bounds.


1

자바 스크립트 (E6) 399 412 450

편집 : 보드 표시가 짧고 좋으며 일부 문자를 자릅니다.

V=(p,b)=>b[p]==(r=0)&&[1,8,9,10].map(d=>r|=(A=(p,d,c=0)=>b[p+=d]==-v?A(p,d,1)&&(b[p]=v):c&b[p]==v)(p,d)|A(p,-d))|r&&(b[p]=v)
L=console.log
l=prompt().replace(/[^0-7]/g,'')
for(i=B=[];++i<73;)B[i]=i%9?i-31&&i-41?i-32&&i-40?0:1:-1:-B
for(v=i=1;l[i];i+=2,v=-v)V(p=l[i]*9+-~l[i-1],B)||!B.some((x,i)=>V(i,[...B]))&&(V(p,B,v=-v))||L(l='Err')
t=0,L(B.map(x=>(t+=~~x,'\nO ☻'[x+2|0]))+(t?t<0?'O':'☻'+t:'='))

언 골프

V = (p, b) =>      // Verify a move and if it is legal, apply the move to the board
b[p]==(r=0) &&     // check if empty cell and init accumulator r
[1,8,9,10].map(d=> // Execute flip check for each of 4 positive direction (and 4 negative too)
  r |= (            
  A=(p,d,c=0) =>   // Recursive function for flip check, if find it valid modify the board during return phase
  b[p+=d] == -v    // If position contains a disk of other color
   ? A(p,d,1) && (b[p]=v) // recursive call. Then if returns true, set the cell in the flip sequence
   : c & b[p]==v   // at end of check, if find the righe disk and if not the first call, return true
  )                // Definition of A function ends here
  (p,d)|A(p,-d)    // Call A 2 times with d and -2 to get all 8 directions
) | r              // now, r is true if any of the 8 flip checks has gone well
&& (b[p]=v);       // if true, set the verified cell too

L=console.log;

l=prompt().replace(/[^0-7]/g,'');            // Get input & discard invalid chars

for (i=B=[];++i<73;) // Create empty board as a single dimension array, NaN mark a row end
  B[i] = i%9 
    ? i-31 && i-41 
      ? i-32 && i-40 
        ? 0: 1: -1: -B //starting values at center, -B evaluate to NaN

for(v=i=1;    // v is the disk color, init to 1 == black
  l[i];       // repeat while inside input string
  i+=2, v=-v) // to char of input at time, set color to opposite
    V( p=l[i]*9+-~l[i-1], B)      // calc position in p from the input, and call Verify
    ||                            // if not valid, could be Error or Skip
      !B.some((x,i)=>V(i,[...B])) // Check if there are no moves for the current color, for each cell call V on a copy of the board
      &&
      (V(p,B,v=-v)) // If no moves found, try to apply the move for the opposite color
    ||
      L(l='Err');   // If failed, it is Error. Change variable l to end the loop

t=0, // Display the board while counting disk difference into 't'
L( 
  B.map(x=>(t+=~~x,'\nO ☻'[x+2|0])) // map array elements to suitable chars, then auto conversion to string give a nice effect
  + (t?t<0?'O':'☻'+t:'=')
) // Display leading and count difference or '='

테스트

자바 스크립트 콘솔 (FireFox)에서 테스트 : 232425140504032627 , , , , , , , , , , , , , , , , , , , , , , , , , , , ,☻, ,☻,☻,☻, , , , ,☻,☻,☻,O,O, , , , ,☻, ,☻, , , , , , , , ,☻, , , , , , , , ,☻, , , , , , ☻9

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.