6.10.2011
README
vastaamaan ryhmän aitoa kokoonpanoa.import Data.Char
main = do
putStrLn "Anna merkkijono: "
x <- getLine
if null x then return ()
else do
if (onkoPalindromi (poistaErikoisetjaPienenna x)) == Just True
then putStrLn "Antamasi merkkijono on palindromi."
else putStrLn "Antamasi merkkijono ei ole palindromi."
onkoPalindromi :: String -> Maybe Bool
onkoPalindromi [] = Nothing
onkoPalindromi [x] = Just True
onkoPalindromi [x,y] | x==y = Just True
| x/=y = Just False
onkoPalindromi xs | head xs /= last xs = Just False
| otherwise = onkoPalindromi $ init.tail $ xs
poistaErikoisetjaPienenna [] = []
poistaErikoisetjaPienenna (x:xs)
| isAlpha x = (toLower x):poistaErikoisetjaPienenna xs
| otherwise = poistaErikoisetjaPienenna xs
poistaErikoisetjaPienenna [] = []
poistaErikoisetjaPienenna (x:xs)
| isAlpha x = (toLower x):poistaErikoisetjaPienenna xs
| otherwise = poistaErikoisetjaPienenna xs
map
+ filter
poistaErikoisetjaPienenna = map toLower . filter isAlpha
onkoPalindromi :: String -> Maybe Bool
onkoPalindromi [] = Nothing
onkoPalindromi [x] = Just True
onkoPalindromi [x,y] | x==y = Just True
| x/=y = Just False
onkoPalindromi xs | head xs /= last xs = Just False
| otherwise = onkoPalindromi $ init.tail $ xs
main
issa)onkoPalindromi :: String -> Bool
onkoPalindromi xs = reverse xs == xs
main
import Data.Char
import Data.List
main = do
putStrLn "Anna merkkijono: "
x <- getLine
case x of
_ | null x -> return ()
_ | onkoPalindromi x -> putStrLn "Antamasi merkkijono on palindromi."
_ -> putStrLn "Antamasi merkkijono ei ole palindromi."
onkoPalindromi :: String -> Bool
onkoPalindromi x = let l = map toLower . filter isAlpha $ x
in reverse l == l
void calculateEstimate(int numPoints, double phi)
{
double estimate=0;
float minX,minY,maxX,maxY;
minX=minY=Float.MAX_VALUE;
maxX=maxY=Float.MIN_VALUE;
//we find the maximum & minimum coordinates
for(int i=1;i<numPoints;i++)
{
if(xc[i]<minX)
minX=xc[i];
if(xc[i]>maxX)
maxX=xc[i];
if(yc[i]<minY)
minY=yc[i];
if(yc[i]>maxY)
maxY=yc[i];
}
//we calculate the area of rectangle including all points
float area=(maxX-minX)*(maxY-minY);
estimate=phi*Math.sqrt(area*(numPoints-1));
}
estimator :: [(Float, Float)] -> Int -> Float -> Float
estimator [] _ _ = -1.0 --virhearv
estimator _ 0 _ = -1.0
estimator x n phi = phi * sqrt ( fromIntegral (n-1) * areaOf x)
areaOf :: [(Float, Float)] -> Float
areaOf x = leveys * korkeus
where
leveys = maxx - minx
korkeus = maxy - miny
(maxx,maxy) = findMaxs x
(minx, miny) = findMins x
findMins :: [(Float, Float)] -> (Float, Float)
findMins xs = findCoords minimum xs
findMaxs :: [(Float, Float)] -> (Float, Float)
findMaxs xs = findCoords maximum xs
findCoords :: ([Float] -> Float) -> [(Float, Float)] -> (Float, Float)
findCoords f xs = (minfst, minsnd)
where
minfst = f [fst x | x <- xs ]
minsnd = f [snd x | x <- xs ]
data Rectangle a = R {left :: a, right :: a, top :: a, bottom :: a}
area :: Num a => Rectangle a -> a
area (R minx maxx miny maxy) = (maxx-minx) * (maxy-miny)
boundingBox :: (Ord a, Bounded a) => [(a,a)] -> Rectangle a
boundingBox = foldl' f void
where
f (R a b c d) (x,y) = R (min a x) (max b x) (min c y) (max d y)
void = R maxBound minBound maxBound minBound
estimator :: (Ord a, Floating a, Bounded a) => t -> [(a, a)] -> a
estimator phi xs = sqrt $ (genericLength xs-1) * (area . boundingBox $ xs)
data Rectangle a = R {left :: a, right :: a, top :: a, bottom :: a}
area :: Num a => Rectangle a -> a
area (R minx maxx miny maxy) = (maxx-minx) * (maxy-miny)
boundingBox :: (Ord a, Bounded a) => [(a,a)] -> Rectangle a
boundingBox = foldl' f universe
where
f (R a b c d) (x,y) = R (min a x) (max b x) (min c y) (max d y)
universe = R maxBound minBound maxBound minBound
import java.io.*;
import java.util.*;
public class T1 {
public static void main(String[] args) {
BufferedReader fi;
try { // Avataan tiedosto lukemista varten
fi = new BufferedReader(new FileReader("tiedosto.txt"));
} catch (FileNotFoundException ex) {
System.out.println("Tiedosto ei aukea!");
return;
}
try {
String s = new String();
for( int i = 1; ( s = fi.readLine() ) != null; i++) {
// Tulostetaan riveille numerot ja katkaistaan pitkät rivit
if(s.length() > 40)
System.out.println("/" + "* 0" + i + " *" + "/ "
+ s.substring(0,40));
else
System.out.println("/" + "* 0" + i + " *" + "/ " + s);
}
} catch (IOException ex) {
System.out.println("Virhe tiedostoa luettaessa!");
} finally { // Aina ehdottomasti finally:ssa resurssien vapautus
try {
fi.close(); // tiedoston sulkeminen heti kun sitä ei enää tarvita
} catch (IOException ex) {
System.out.println("Tiedostoa ei saa suljettua!");
}
}
}
module Main where
import System.Environment
import System.IO.Error
import System.IO
import Data.List
-- Palauttaa rivinumeron mukavan pituisena nolla-alkuisena numerona
indexing :: Int -> Int -> String
indexing total current = "/* " ++ take pad (repeat '0') ++ show current ++ " */ "
where pad = length (show total) - length (show current)
-- Listan alkioit typistettynä 40-merkkisiksi, etuliitteenä vielä rivinumero
formatList :: [String] -> [String]
formatList xs = zipWith op [1..] xs
where
op i r = (index i) ++ (take 40 r)
index = indexing (length xs)
-- Lukee tiedoston ja kopioi sen toiseen tiedostoon.
main = do [luetaan,kirjoitetaan] <- getArgs
inh <- openFile luetaan ReadMode
outh <- openFile kirjoitetaan WriteMode
inputti <- readFile luetaan
let rivit = lines inputti
writeFile kirjoitetaan $ unlines (formatList rivit)
hClose inh
hClose outh
-- Lukee tiedoston ja kopioi sen toiseen tiedostoon.
main = do [luetaan,kirjoitetaan] <- getArgs
inh <- openFile luetaan ReadMode
outh <- openFile kirjoitetaan WriteMode
inputti <- readFile luetaan
let rivit = lines inputti
writeFile kirjoitetaan $ unlines (formatList rivit)
hClose inh
hClose outh
readFile
ja writeFile
avaavat tiedostonsa itse:-- Lukee tiedoston ja kopioi sen toiseen tiedostoon.
main = do [luetaan,kirjoitetaan] <- getArgs
inputti <- readFile luetaan
let rivit = lines inputti
writeFile kirjoitetaan $ unlines (formatList rivit)
-- Lukee tiedoston ja kopioi sen toiseen tiedostoon.
main = do [luetaan,kirjoitetaan] <- getArgs
inputti <- readFile luetaan
let rivit = lines inputti
writeFile kirjoitetaan $ unlines (formatList rivit)
formatString :: String -> String
formatString = unlines . formatList . lines
main = do [luetaan,kirjoitetaan] <- getArgs
readFile luetaan >>= writeFile kirjoitetaan . formatString
main = do [luetaan,kirjoitetaan] <- getArgs
readFile luetaan >>= writeFile kirjoitetaan . formatString
:main kissa
=> Pattern Match failure
main = do as <- getArgs
case as of
[luetaan,kirjoitetaan]
-> readFile luetaan >>= writeFile kirjoitetaan . formatString
[luetaan]
-> readFile luetaan >>= putStr . formatString
[] -> putStrLn "Anna tiedostonimi"
module Main where
import Graphics.Gloss
import Graphics.Gloss.Data.Vector
import Graphics.Gloss.Interface.Game
data PingPongWorld = GameOver
| Start
| World { player1 :: Player
,player2 :: Player
,ball :: Ball }
data Player = Player Score Paddle
data Paddle = Paddle Point Size State
data State = SUp | SStay | SDown deriving Eq
type Size = Float
type Score = Int
data Ball = GBLeft | GBRight | Ball Point Velocity Size
type Velocity = Point
screenW :: Float
screenW = 400
playerX :: Float
playerX = screenW/2 - 5
padVel = 200
initialWorld sc1 sc2 = World (Player sc1 (Paddle (-playerX,0) 100 SStay))
(Player sc2 (Paddle (playerX,0) 100 SStay))
(Ball (0,0) (150,0) 10)
drawWorld (World (Player sc1 p1) (Player sc2 p2) ball@(Ball (bx,_) (_,_) _))
= rotate rot . pictures $ [drawBall ball, drawPaddle p1
, drawPaddle p2 , drawScore,
, color red . Line $ [(-screenW/2,screenW/2)
,(screenW/2,screenW/2)]
, color red . Line $ [(-screenW/2,-screenW/2)
,(screenW/2,-screenW/2)]]
where
drawBall (Ball (bx,by) (bvx,bvy) bs)
= color red . translate bx by . circle $ bs
drawBall _
= Blank
drawScore
= color red . translate (-150) (screenW/2) . scale 0.25 0.25
. Text $ (show sc1) ++ " - " ++ (show sc2)
drawPaddle (Paddle (x,y) s _)
= color red . translate x y . Line $ [(0,-s/2),(0,s/2)]
rot = fromIntegral (sc1-sc2) + (fromIntegral (sc1+sc2) * (bx / screenW))
drawWorld w_ = Blank
simulateWorld _ GameOver = GameOver
simulateWorld _ Start = Start
simulateWorld _ (World p1@(Player sc1 paddle1)
p2@(Player sc2 paddle2) GBRight)
= initialWorld (sc1+1) sc2
simulateWorld _ (World p1@(Player sc1 paddle1)
p2@(Player sc2 paddle2) GBLeft)
= initialWorld sc1 (sc2+1)
simulateWorld step (World p1@(Player sc1 paddle1)
p2@(Player sc2 paddle2) ball)
= World (Player sc1 (updatePaddle paddle1)) (Player sc2 (updatePaddle paddle2)) (updateBall ball)
where
updatePaddle (Paddle (x,y) s state)
| state == SUp && y + s/2 < screenW/2 = Paddle (x,y+padVel*step) s state
| state == SDown && y - s/2 > -screenW/2 = Paddle (x,y-padVel*step) s state
| otherwise = Paddle (x,y) s state
updateBall (Ball (x,y) (vx,vy) s)
| collidesWithPaddle paddle1 ball = paddleHit paddle1 ball
| collidesWithPaddle paddle2 ball = paddleHit paddle2 ball
| x > screenW/2 = GBRight
| x < -screenW/2 = GBLeft
| y > screenW/2 = Ball (x+vx*step,screenW/2-(abs vy)*step) (vx,-(abs vy)) s
| y < -screenW/2 = Ball (x+vx*step,-screenW/2+(abs vy)*step) (vx, abs vy) s
| otherwise = Ball (x+vx*step,y+vy*step) (vx, vy) s
collidesWithPaddle (Paddle (px,py) size _) (Ball (bx,by) _ s)
= (abs (py-by) < size/2) && (abs (px-bx) < s/2)
paddleHit (Paddle (px,py) _ SStay) (Ball (bx, by) (vx,vy) s)
= Ball (bx-(sign px) * s* 2,by) (-vx, vy) s
paddleHit (Paddle (px,py) size SUp) (Ball (bx, by) (vx,vy) s)
= Ball (bx-(sign px) * s* 2,by) (-vx, vy+250*(abs (py - by))/size) s
paddleHit (Paddle (px,py) size SDown) (Ball (bx, by) (vx,vy) s)
= Ball (bx-(sign px) * s* 2,by) (-vx, vy-250*(abs (py - by))/size) s
sign x = x / abs x
handleEvents (EventKey (Char 'w') Down _ _)
(World (Player sco (Paddle pos1 size _)) pl2 ball )
= World (Player sco (Paddle pos1 size SUp)) pl2 ball
handleEvents (EventKey (Char 's') Down _ _)
(World (Player sco (Paddle pos1 size _)) pl2 ball )
= World (Player sco (Paddle pos1 size SDown)) pl2 ball
handleEvents (EventKey (Char 'o') Down _ _)
(World pl1 (Player sco (Paddle pos1 size _)) ball )
= World pl1 (Player sco (Paddle pos1 size SUp)) ball
handleEvents (EventKey (Char 'l') Down _ _)
(World pl1 (Player sco (Paddle pos1 size _)) ball )
= World pl1 (Player sco (Paddle pos1 size SDown)) ball
..
..
main = gameInWindow
"PingPong"
(floor screenW, floor screenW)
(20,20)
black
24
(initialWorld 0 0)
drawWorld
handleEvents
simulateWorld
import System.Random
main = do
let r1 = (randomList 100000 1.0 (mkStdGen 99))
r2 = (randomList 100000 1.0 (mkStdGen 232))
print $ 4.0 * likiarvo (laskePi (coord r1 r2))
randomList :: Int -> Double -> StdGen -> [Double]
randomList 0 _ _ = []
randomList a b c = take a (randomRs(0,b) c)
coord :: [a] -> [b] -> [(a,b)]
coord a b = zip a b
laskePi :: [(Double,Double)] -> [Bool]
laskePi [] = []
laskePi ((a,b):xs) = onkoSisalla a b : laskePi xs
onkoSisalla :: Double -> Double -> Bool
onkoSisalla a b = if (sqrt((a*a)+(b*b)) < 1) then True else False
likiarvo :: [Bool] -> Double
likiarvo [] = 0.0
likiarvo x = (intToDouble (length (filter (==True) x))) / intToDouble (length(x))
intToDouble :: Int -> Double
intToDouble x = fromIntegral x
import System.Random
main = do
let r1 = (randomList 100000 1.0 (mkStdGen 99))
r2 = (randomList 100000 1.0 (mkStdGen 232))
print $ (1/100000) * 4.0 * fromIntegral (count onkoSisalla (zip r1 r2)))
randomList :: Int -> Double -> StdGen -> [Double]
randomList a b c = take a (randomRs(0,b) c)
onkoSisalla :: (Double, Double) -> Bool
onkoSisalla (a, b) = (sqrt((a*a)+(b*b)) < 1)
count :: (a -> Bool) -> [a] -> Int
count x = length . filter p
module Main where
type Piste a = (a,a)
viivaIntegraali :: (Floating a) => (Piste a -> a) -> (a -> Piste a) -> [a] -> a
viivaIntegraali funktio polku väli = sum $ zipWith ala väli (tail väli)
where
ala x y = (keskiarvo x y)*(välinpituus x y)
välinpituus x y = pituus (polku x .- polku y)
keskiarvo x y = (funktio (polku x) + funktio (polku y))/2
(.-) :: (Floating a) => Piste a -> Piste a-> Piste a
(x,y) .- (u,v) = (x-u,y-v)
infixl 6 .-
pituus :: (Floating a) => Piste a -> a
pituus (x,y) = sqrt (x**2+y**2)
-- Tässä muuten hämää käsittämätön numeerinen virhe listan automaagisessa
-- generaatiossa. Keskimmäinen lista on ihan eri näköinen jos sen ensin
-- generoi kokonaislukuina ja sitten jakaa jokaisen luvun kymmenellä eli map (/10)
-- [51,52..100].
esimerkkiVäli = [1,2..5]++[5.1,5.2..10]++[11,12..15]
esimerkkiPolku :: (Floating a) => a -> Piste a
esimerkkiPolku t = (sinh t,sin t)
esimerkkiFunktio :: (Floating a) => Piste a -> a
esimerkkiFunktio (x,y) = x*y**2
main = print $ viivaIntegraali esimerkkiFunktio esimerkkiPolku esimerkkiVäli
-- Lisäbonus
integraali :: (Floating a) => (a -> a) -> [a] -> a
integraali funktio väli = viivaIntegraali (ulotteistaja funktio) pisteyttäjä väli
where
pisteyttäjä x = (x,0)
ulotteistaja funktio (x,y) = funktio x
module Main where
import Graphics.Gloss hiding (Path, Point)
import Graphics.Gloss.Data.Vector
import Graphics.Gloss.Interface.Game hiding (Path, Point)
import qualified Data.Map as Map
import Random
type Point a = (a, a)
type Path a = [Point a]
-- Vektorioperaattorit
(.-) , (.+) :: (Num a) => Point a -> Point a -> Point a
(x,y) .- (u,v) = (x-u,y-v)
(x,y) .+ (u,v) = (x+u,y+v)
infixl 6 .- , .+
infixl 7 .*
(.*) :: (Num a) => a -> Point a -> Point a
s .* (u,v) = (s*u,s*v)
snakeSize = 5
snakeSizeF = fromIntegral snakeSize
left = (-1, 0)
right = (1, 0)
up = (0, 1)
down = (0, -1)
type Controls = Map.Map Key (Point Int)
type Direction = Point Int
data Turn = Turn {
direction :: Direction,
timestamp :: Int
} deriving (Eq)
data Player = Player {
startPosition :: Point Int,
colour :: Color,
turns :: [Turn],
controls :: Controls,
randomNumbers :: [Int],
timeOfDeath :: Int
}
instance Eq Player where
p1 == p2 = (colour p1) == (colour p2)
data GameState = GameState {
players :: [Player],
time :: Float,
bounds :: Point Int
}
isAlive player = timeOfDeath player == 0
isAIPlayer player = Map.null (controls player)
isGameOver :: GameState -> Bool
isGameOver game = length (filter isAlive (players game)) < 2
playerDirection player = direction . last $ turns player
playerCanTurnToDirection player (x1, y1) = x1 + x2 /= 0 && y1 + y2 /= 0
where
(x2, y2) = playerDirection player
updateGameState :: Float -> GameState -> GameState
updateGameState delta game@(GameState players prevTime bounds) =
if isGameOver game then
game
else
GameState (map (updatePlayer (floor time))
(updateAIPlayers game)) time bounds
where
time = prevTime + 1 --TODO: Use delta
updatePlayer time player@(Player startPosition colour turns controls
nums tod)
= Player startPosition colour turns controls nums timeOfDeath
where timeOfDeath = if isAlive player then
(if (collidesWithBounds bounds position)
|| collidesWithOthers then time else 0)
else tod
where
position@(x, y) = playerPosition time player
collidesWithOthers = foldl (\acc other ->
acc || checkCollision player other )
False players
where checkCollision player other
= collidesWithPath (playerPath excludeHeadIfSelf other) (x, y)
where excludeHeadIfSelf = if other == player then time - 1 else time
updateAIPlayers :: GameState -> [Player]
updateAIPlayers game@(GameState players prevTime bounds)
= map (\player -> if isAIPlayer player && isAlive player
then updateAIPlayer game player
else player) players
updateAIPlayer :: GameState -> Player -> Player
updateAIPlayer game@(GameState players prevTime bounds)
player@(Player startPosition _ turns _ rands _)
| collidesWithSomething || time - (timestamp (last turns)) >= 20 + (rand1 `mod` 30)
= turnAIPlayer game (player {randomNumbers = newRands})
| otherwise = player
where
rand1 = head rands
rand2 = head (drop 1 rands)
newRands = drop 2 rands
time = floor prevTime
collidesWithSomething =
case playerCollisionDistanceAtDirection game player (playerDirection player) (2 + rand2 `mod` 10)
of Just x -> True
Nothing -> False
playerCollidesAtDirection :: GameState -> Player -> Direction -> Int -> Bool
playerCollidesAtDirection (GameState players prevTime bounds) player direction distance
= any collidesWithPlayer players || collidesWithBounds bounds nextPosition
where
time = floor prevTime
collidesWithPlayer otherPlayer = collidesWithPath (playerPath time otherPlayer) nextPosition
nextPosition = (playerPosition time player .+ distance .* direction)
playerCollisionDistanceAtDirection :: GameState -> Player -> Direction -> Int -> Maybe Int
playerCollisionDistanceAtDirection game player direction maxDistance
| noCollisionDistance < maxDistance = Just (noCollisionDistance + 1)
| otherwise = Nothing
where noCollisionDistance = case takeWhile (\distance -> not $ playerCollidesAtDirection game
player direction distance)
[1..maxDistance] of
[] -> 0
xs -> last xs
randomAITurnDirection :: GameState -> Player -> Int -> Maybe Direction
randomAITurnDirection game player randomNumber = if null candidates
then Nothing
else Just $ candidates !! (randomNumber `mod` length candidates)
where
candidates = map fst $ filter (\(direction, distance) -> distance == maxDistance)
collisionDistances
maxDistance = foldr max 0 $ map snd collisionDistances
collisionDistances = [(direction, collisionDistanceAtDirection direction)
| direction <- legalDirections]
legalDirections = [d | d <- [left, right, up, down]
,playerCanTurnToDirection player d
,not (playerCollidesAtDirection game player d 1)]
collisionDistanceAtDirection direction
= case playerCollisionDistanceAtDirection game player direction 10 of
Just x -> x
Nothing -> infiniteDistance
infiniteDistance = 100000
turnAIPlayer :: GameState -> Player -> Player
turnAIPlayer game@(GameState players prevTime bounds)
player@(Player startPosition _ turns _ rands _)
= case randomAITurnDirection game player (head rands) of
Nothing -> player
Just direction -> (turnPlayer (Turn direction time) player)
{ randomNumbers = drop 1 rands }
where
time = floor prevTime
-- Converts path to a list of lines
lineByLine :: [a] -> [(a,a)]
lineByLine [] = []
lineByLine (x:[]) = []
lineByLine (x:xs) = (x,head xs):(lineByLine xs)
collidesWithPath :: (Path Int) -> (Point Int) -> Bool
collidesWithPath path point
= any (\line -> collidesWithLine line point) (lineByLine path)
where collidesWithLine ((x1,y1),(x2,y2)) (x, y)
= (x >= (min x1 x2) && y >= (min y1 y2)
&& x <= (max x1 x2) && y <= (max y1 y2))
collidesWithBounds :: (Point Int) -> (Point Int) -> Bool
collidesWithBounds (bx, by) (x, y) = x < -bx || y < -by || x > bx || y > by
-- Returns players position at specific point in time
playerPosition :: Int -> Player -> Point Int
playerPosition time player = last (playerPath time player)
pathFromTurns :: Int -> Point Int -> [Turn] -> Path Int
pathFromTurns time turnPosition [] = [turnPosition]
pathFromTurns time turnPosition ((Turn direction turnTime):turns)
= turnPosition : (pathFromTurns time nextTurnPosition turns)
where
nextTurnPosition = turnPosition .+ ((nextTurnTime time turns) - turnTime) .* direction
nextTurnTime time [] = time
nextTurnTime _ ((Turn _ t):turns) = t
playerPath :: Int -> Player -> Path Int
playerPath time player = pathFromTurns playerTime (startPosition player) (turns player)
where
playerTime = if isAlive player then time else timeOfDeath player
-- For drawing thicker lines
lineAsRect :: Path Float -> Picture
lineAsRect path = pictures (map drawRect (lineByLine path))
drawRect :: (Point Float, Point Float) -> Picture
drawRect ((x1, y1), (x2, y2)) = translate (x + 0.5 * w) y pic
where
x = min x1 x2 - 0.5
y = min y1 y2 - 0.5
w = ((max x1 x2) + 0.5 - x)
h = ((max y1 y2) + 0.5 - y)
pic = rectangleUpperSolid w h
drawGame :: GameState -> Picture
drawGame game = pictures (map (drawPlayer game) (players game))
where drawPlayer game player
= scale snakeSizeF snakeSizeF . Color drawColor . lineAsRect
$ map convertTuple (playerPath (floor (time game)) player)
where
drawColor = if isAlive player then colour player else greyN 0.5
convertTuple (x, y) = (fromIntegral x, fromIntegral y)
-- Handles player input
handleInput :: Event -> GameState -> GameState
handleInput (EventKey key Down _ _) game =
if isGameOver game then
initGameState
else
GameState playerList (time game) (bounds game)
where playerList = [ if isAlive player then handleInputFor player else player
| player <- (players game) ]
where handleInputFor player = case Map.lookup key (controls player) of
Nothing -> player
Just direction -> turnPlayer (Turn direction (floor (time game))) player
handleInput _ g = g
turnPlayer :: Turn -> Player -> Player
turnPlayer turn player =
if isLegal then
Player (startPosition player) (colour player) ((turns player) ++ [turn])
(controls player) (randomNumbers player) 0
else
player
where
lastTurn = last (turns player)
(x1, y1) = direction lastTurn
(x2, y2) = direction turn
isLegal = (playerCanTurnToDirection player (direction turn))
&& timestamp lastTurn < timestamp turn
-- Helper for creating new players
initPlayers :: [(Color, Int, Controls)] -> [Player]
initPlayers [] = []
initPlayers ((colour,seed,ctrl):xs)
= (Player (0, 10 * length xs) colour [ Turn right 0 ] ctrl randomNumbers 0):(initPlayers xs)
where
randomNumbers = randomRs (1, 10000) (mkStdGen seed)
-- Initializes the game
initGameState = GameState {
players = initPlayers [
(blue, 1, Map.fromList [ (SpecialKey KeyUp, up), (SpecialKey KeyDown, down)
, (SpecialKey KeyLeft, left), (SpecialKey KeyRight, right) ]),
(green, 2, Map.empty),
(red, 3, Map.empty) ],
time = 0,
bounds = (320 `div` snakeSize, 240 `div` snakeSize)
}
main = gameInWindow
"Tron"
(640, 480)
(20, 20)
black
24
initGameState
drawGame
handleInput
updateGameState
foldr max 0 == maximum
candidates = map fst $ filter (\(direction, distance)
-> distance == maxDistance)
collisionDistances
candidates = filter (==maxDistance) . map fst $ collisionDistances
collidesWithOthers = foldl (\acc other ->
acc || checkCollision player other )
False players
collidesWithOthers = any (checkCollision player) players
if
's everywhere. Use cases or guards, or rethink. Haskell program of this size usually has one or two if statements overall.module Main where
import Char
import Maybe
data Valuutta = Valuutta { lyhenne :: String,
nimi :: String,
kurssi :: Double }
uusiValuutta :: String -> String -> Double -> Valuutta
uusiValuutta lyhenne nimi kerroin = Valuutta (uppercase lyhenne) nimi kerroin
vaihdaEuroksi = (*)
etsiKurssi :: String -> [Valuutta] -> Maybe Double
etsiKurssi _ [] = Nothing
etsiKurssi lyhenne ((Valuutta a b c):xs)
| a == lyhenne = Just c
| otherwise = etsiKurssi lyhenne xs
main = do putStrLn "Ohjelma muuntaa eri valuuttoja euroiksi. Ohjelma loppuu, kun painat q. Kurssi on otettu 3.10.2011."
kysy teeValuutat
putStrLn "Kiitos!"
kysy valuutat = do putStrLn "Anna summa ja rahan lyhenne: "
rahat <- getLine
if rahat == "q"
then return ()
else do (parseSyote rahat) `testaaSyote` valuutat
kysy valuutat
uppercase = map toUpper
parseSyote :: String -> Maybe (Double, String)
parseSyote teksti = if (2 >= (length sanat))
then Just ((read (head sanat) :: Double) , last sanat)
else Nothing
where sanat = words teksti
testaaSyote Nothing _ = putStrLn "Antamasi raha ei ollut kelvollinen"
testaaSyote (Just (a,b)) valuutat =
do let kurssi = etsiKurssi (uppercase b) valuutat
if kurssi == Nothing
then putStrLn "Antamaasi valuuttaa ei ole"
else putStrLn $ (show a) ++ " " ++ b ++ " on " ++ (show (vaihdaEuroksi a (fromJust kurssi))) ++ " euroa"
putStrLn ""
teeValuutat :: [Valuutta]
teeValuutat = [Valuutta "SKR" "kruunu" 0.6, Valuutta "$" "dollari" 1.2]