Upgraded graphics to 1920x1080 (FHD).

Changed title of application to Rock Paper Scissors.

Included base images (to be replaced at a later date).

Compiled build 0.0.12.7.5.8 (alpha)
This commit is contained in:
Neil Hanlon 2015-10-16 13:40:40 -04:00
parent a3c9376c03
commit 3425e46d65
9 changed files with 115 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.o
*.hi

BIN
O.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
RockPaperScissors.exe Normal file

Binary file not shown.

113
RockPaperScissors.hs Normal file
View File

@ -0,0 +1,113 @@
-- Putting it all together: Tic Tac Toe
-- cabal update
-- cabal install gloss
-- ghc tictactoe.hs
-- tictactoe.exe
-- import is just like Java, but you can give modules (akin to Java packages) their own local name
import qualified Graphics.Gloss.Interface.Pure.Game as Gloss
import qualified Graphics.Gloss.Data.Bitmap as Bitmap
import qualified Data.Map as Map
import Data.List
-- A tic-tac-toe cell is either blank, X, or O
data Cell = Blank | X | O deriving (Eq, Ord)
-- To encode game state:
-- we have the board (a map from a pair of ints to a Cell)
-- and the current "player" (either X or O)
data Game = Game {
board :: Map.Map (Int, Int) Cell,
player :: Cell
}
-- Initially, the board is a 3x3 grid of blank cells
initialBoard = Map.fromList [((i,j), Blank) | i <- [0..2], j <- [0..2]]
-- Given a game board, and two coordinates, is the move legit?
validMove :: Map.Map (Int, Int) Cell -> Int -> Int -> Bool
validMove board i j
| i < 0 || i >= 3 || j < 0 || j >= 3 = False
| otherwise = Blank == board Map.! (i,j)
-- X starts the game
initialGame = Game initialBoard X
-- List the rows in the game board
rows :: Map.Map (Int, Int) Cell -> [[Cell]]
rows board = map (map snd) $ groupBy (\((i,j),_) ((k,l),_) -> i == k) $ Map.assocs board
-- List the diagonals in the game board
diagonals :: Map.Map (Int, Int) Cell -> [[Cell]]
diagonals board = [[board Map.! (0,0), board Map.! (1,1), board Map.! (2,2)],
[board Map.! (2,0), board Map.! (1,1), board Map.! (0,2)]]
-- Players switch when taking turns
switch :: Cell -> Cell
switch O = X
switch X = O
-- Given a game board, and a move, get the new game board state
takeTurn :: Game -> (Int, Int) -> Game
takeTurn game@Game { board=b, player=p } (i, j)
| validMove b i j = newGame
| otherwise = game
where
newGame = Game {
board = Map.adjust (\_ -> p) (i,j) b,
player = switch p
}
-- Did anybody win?
winner :: Map.Map (Int, Int) Cell -> Bool
winner board = any win slices
where
slices = ((rows board) ++ (diagonals board) ++ (transpose $ rows board))
-- Given a slice (row, column, diagonal), are they all the same?
win slice = foldl1 (\x y -> if x == y then x else Blank) slice /= Blank
-- is the game over? either somebody won, or there's no blanks left
gameOver :: Map.Map (Int, Int) Cell -> Bool
gameOver board = winner board || (not $ any (== Blank) $ Map.elems board)
-- So, who won, if anybody?
outcome (Game board player)
| winner board = switch player
| otherwise = Blank
-- Translate mouse clicks (Gloss.Event) into turns
handleMouse :: Gloss.Event -> Game -> Game
handleMouse (Gloss.EventKey (Gloss.MouseButton Gloss.LeftButton) Gloss.Down _ (x, y)) game@(Game board player)
| gameOver board = game
| otherwise = takeTurn game (i, j)
where i = round $ (y+160) / 160
j = round $ (x+240) / 160
-- don't care about the other events
handleMouse _ game = game
main = do
oPicture <- Bitmap.loadBMP "O.bmp"
xPicture <- Bitmap.loadBMP "X.bmp"
_Picture <- Bitmap.loadBMP "_.bmp"
xwin <- Bitmap.loadBMP "xwin.bmp"
owin <- Bitmap.loadBMP "owin.bmp"
tie <- Bitmap.loadBMP "tie.bmp"
let cellPicture = Map.fromList [(O,oPicture), (X, xPicture), (Blank, _Picture)]
let outcomePicture = Map.fromList [(O,owin), (X, xwin), (Blank, tie)]
let displayCell (i,j) cell = Gloss.translate ((fromIntegral j :: Float)*160-240) ((fromIntegral i :: Float)*160-160) $ cellPicture Map.! cell
let displayBoard (Game board _) = Gloss.Pictures $ Map.elems $ Map.mapWithKey displayCell board
let displayOutcome game = Gloss.translate (230) (0) (outcomePicture Map.! (outcome game))
let display game@(Game board player) = if gameOver board then Gloss.Pictures [displayOutcome game, displayBoard game] else displayBoard game
Gloss.play
(Gloss.InWindow "Rock Paper Scissors" (1920,1080) (0,0))
Gloss.black
10
initialGame
display
handleMouse
(\f g -> g)

BIN
X.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
_.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
owin.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

BIN
tie.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

BIN
xwin.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB