系列: haskell
haskell
187 行
· 更新于 2026-02-03
ChessGraphics.hs
haskell/ChessGraphics.hs
-----------------------------------------------------------------------
-- This module is heavily inspired by the graphics module in:
-- Haskell: The Craft of Functional Programming, 3e
-- Simon Thompson
-- (c) Addison-Wesley, 1996-2011.
--
-- This code developed by Liam O'Connor for the Australian National University
-- (c) 2025
-----------------------------------------------------------------------
-- | This module defines a graphics library for COMP1100 assignments.
-- The 'Picture' type represents images that can be displayed with 'render'.
-- Use 'above', 'beside', and 'over' to combine images together.
-- Use 'flipH', 'flipV', and 'invert' to change the appearance of images.
-- See the final section of this module for a list of built-in 'Picture's.
module ChessGraphics
( Picture
, render
-- * Combining pictures
, above, beside, over
-- * Altering pictures
, flipH, flipV, invert
-- * Built-in pictures
, empty, whiteSquare, king, queen, bishop, knight, rook, pawn
) where
import System.IO ( hClose, openFile, hPutStrLn, IOMode(WriteMode) )
import Data.Set (fromList)
-- | A type for 'Picture's.
data Picture
= Img String (Int, Int) Filter
| Above Picture Picture
| Beside Picture Picture
| Over Picture Picture
| Empty
deriving (Show)
-- A Filter represents which of the actions of flipH, flipV
-- and invert is to be applied to an image.
data Filter = Filter {fH, fV, neg :: Bool}
deriving (Show, Eq, Ord)
instance Eq Picture where
(==) x y = fromList (flatten (0,0) x) == fromList (flatten (0,0) y)
-- Coordinates are pairs (x,y) of integers
--
-- o------> x axis
-- |
-- |
-- V
-- y axis
type Point = (Int,Int)
--
-- The functions over Pictures
--
-- | Given two 'Picture's @e1@ and @e2@, @above e1 e2@ produces a
-- 'Picture' where @e1@ is placed directly above @e2@
above :: Picture -> Picture -> Picture
above = Above
-- | Given two 'Picture's @e1@ and @e2@, @beside e1 e2@ produces a
-- 'Picture' where @e1@ is placed directly to the left of @e2@
beside :: Picture -> Picture -> Picture
beside = Beside
-- | Given two 'Picture's @e1@ and @e2@, @over e1 e2@ produces a
-- 'Picture' where @e1@ is placed directly on top of @e2@
over :: Picture -> Picture -> Picture
over = Over
-- | The empty picture, containing no image.
empty :: Picture
empty = Empty
-- | Given a 'Picture', 'flipH' produces a 'Picture' which is flipped along the horizontal axis.
flipH :: Picture -> Picture
flipH pic = case pic of
Above pic1 pic2 -> Above (flipH pic2) (flipH pic1)
Beside pic1 pic2 -> Beside (flipH pic1) (flipH pic2)
Over pic1 pic2 -> Over (flipH pic1) (flipH pic2)
Img fn sz fil -> Img fn sz (fil {fH = not (fH fil)})
Empty -> Empty
-- | Given a 'Picture', 'flipV' produces a 'Picture' which is flipped along the vertical axis.
flipV :: Picture -> Picture
flipV pic = case pic of
Above pic1 pic2 -> Above (flipV pic1) (flipV pic2)
Beside pic1 pic2 -> Beside (flipV pic2) (flipV pic1)
Over pic1 pic2 -> Over (flipV pic1) (flipV pic2)
Img fn sz fil -> Img fn sz (fil {fV = not (fV fil)})
Empty -> Empty
-- | Given a 'Picture', 'invert' produces a 'Picture' which has each pixel colour inverted
-- (i.e. white becomes black and vice versa).
invert :: Picture -> Picture
invert pic = case pic of
Above pic1 pic2 -> Above (invert pic1) (invert pic2)
Beside pic1 pic2 -> Beside (invert pic1) (invert pic2)
Over pic1 pic2 -> Over (invert pic1) (invert pic2)
Img fn sz fil -> Img fn sz (fil {neg = not (neg fil)})
Empty -> Empty
width :: Picture -> Int
width pic = case pic of
Img _ (x,_) _ -> x
Above pic1 pic2 -> max (width pic1) (width pic2)
Beside pic1 pic2 -> width pic1 + width pic2
Over pic1 pic2 -> max (width pic1) (width pic2)
Empty -> 0
height :: Picture -> Int
height pic = case pic of
Img _ (_,y) _ -> y
Above pic1 pic2 -> height pic1 + height pic2
Beside pic1 pic2 -> max (height pic1) (height pic2)
Over pic1 pic2 -> max (height pic1) (height pic2)
Empty -> 0
-- Converting pictures to a list of basic images.
data Basic = Basic String (Int, Int) Point Filter
deriving (Show, Ord, Eq)
-- Flatten a picture into a list of Basic pictures.
-- The Point argument gives the origin for the coversion of the
-- argument.
flatten :: Point -> Picture -> [Basic]
flatten (x,y) pic = case pic of
Img image sz fil -> [Basic image sz (x,y) fil]
Above pic1 pic2 -> flatten (x,y) pic1 ++ flatten (x, y + height pic1) pic2
Beside pic1 pic2 -> flatten (x,y) pic1 ++ flatten (x + width pic1 , y) pic2
Over pic1 pic2 -> flatten (x,y) pic2 ++ flatten (x,y) pic1
Empty -> []
-- Convert a Basic picture to an SVG image, represented by a String.
convert :: Basic -> String
convert (Basic piece (w, h) (x,y) (Filter fH fV neg))
= "\n <image x=\"" ++ show x ++
"\" y=\"" ++ show y ++ "\" width=\"" ++ show w ++
"\" height=\"" ++ show h ++ "\" xlink:href=\"" ++ piece ++ "\"" ++
flipPart ++ negPart ++ "/>\n"
where
flipPart
| fH && not fV = " transform=\"translate(0," ++ show (2*y + h) ++ ") scale(1,-1)\" "
| fV && not fH = " transform=\"translate(" ++ show (2*x + w) ++ ",0) scale(-1,1)\" "
| fV && fH = " transform=\"translate(" ++ show (2*x + w) ++ "," ++
show (2*y + h) ++ ") scale(-1,-1)\" "
| otherwise = ""
negPart
| neg = " filter=\"url(#negative)\""
| otherwise = ""
-- | Outputting a picture. Given a 'Picture' @pic@, the command @render pic@ will
-- save an image to a SVG file called @svgOut.svg@.
--
-- The provided @showPic.html@ file can be used, when opened in a browser, to view
-- the produced SVG image.
render :: Picture -> IO ()
render pic = do
outh <- openFile "svgOut.svg" WriteMode
hPutStrLn outh newFile
hClose outh
where
picList = flatten (0,0) pic
svgString = concat (map convert picList)
newFile = preamble ++ svgString ++ postamble
preamble =
"<svg width=\"100%\" height=\"100%\" version=\"1.1\"\n" ++
"xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n" ++
"<filter id=\"negative\" color-interpolation-filters=\"sRGB\">"++
"<feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"" ++
"-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0\"/> </filter>\n"
postamble = "\n</svg>\n"
whiteSquare,king,queen,bishop,knight,rook,pawn :: Picture
whiteSquare = Img "images/white.png" (50,50) (Filter False False False)
king = Img "images/king.png" (50,50) (Filter False False False)
queen = Img "images/queen.png" (50,50) (Filter False False False)
bishop = Img "images/bishop.png" (50,50) (Filter False False False)
knight = Img "images/knight.png" (50,50) (Filter False False False)
rook = Img "images/rook.png" (50,50) (Filter False False False)
pawn = Img "images/pawn.png" (50,50) (Filter False False False)
相关文章
haskell
haskell
更新于 2026-02-03
Adding.hs
Adding.hs — haskell source code from the haskell learning materials (haskell/Adding.hs).
阅读文章 →
haskell
haskell
更新于 2026-02-03
Area.hs
Area.hs — haskell source code from the haskell learning materials (haskell/Area.hs).
阅读文章 →
haskell
haskell
更新于 2026-02-03
Chess.hs
Chess.hs — haskell source code from the haskell learning materials (haskell/Chess.hs).
阅读文章 →
haskell
haskell
更新于 2026-02-03
Examples.hs
Examples.hs — haskell source code from the haskell learning materials (haskell/Examples.hs).
阅读文章 →
haskell
haskell
更新于 2026-02-03
Fibonacci.hs
Fibonacci.hs — haskell source code from the haskell learning materials (haskell/Fibonacci.hs).
阅读文章 →
haskell
haskell
更新于 2026-02-03
GPACalculator.hs
GPACalculator.hs — haskell source code from the haskell learning materials (haskell/GPACalculator.hs).
阅读文章 →