This is my final project for EECS 368 at the University of Kansas. The project was to recreate a game using one of the two languages we learned throughout the semester. I chose to recreate the classic game Tetris
using Haskell.
Assuming you have GHC and stack installed, all you need to do is clone the repository and install the packages using stack:
git clone
cd Haskell-Tetris/
stack install
To run it, use stack as well:
stack exec Haskell-Tetris-exe
This will run a web server on port 3000, to play the game, open any browser and navigate to the following address:
http://localhost:3000
Key | Action |
---|---|
Left Arrow Key | Move the tetromino left |
Right Arrow Key | Move the tetromino right |
Down Arrow Key | Hard drop the tetromino (instantly drops the piece) |
Q | Rotate tetromino counter clockwise |
E | Rotate tetromino clockwise |
This project taught me a lot, and throughout the creation of this project I really started to enjoy coding in Haskell. It's a completely differet type of coding than I was used to in regular OOP style coding in C/C++.
Thinking in terms of functions, function compositions, list comprehensions, and mondas instead of the usual objects was a fun challenge, and I hope to do more with the language in the future.
On a whole, I'm proud of this project in general. Making Tetris is not an easy task, and I think I did a genuinely good job. If I were to point out particular parts though, I am most proud of the following functionalities:
mapBoard :: Matrix -> ((Int, Int) -> GridSquare) -> Matrix
mapBoard
is a higher order function that takes a board matrix, and a function that takes a two tuple for a position on the board and returns a GridSquare, and will result in a manipulated matrix. This is used to change the game board based off of the position of the piece. For example, we use mapBoard when having a piece fall down. We get the position of all the falling pieces, and if the position below of any of those is the one we're evaluating, then we set that to a falling piece. If the position was one of the falling pieces, we set that to empty, since the piece will have fallen.
placePiece :: [(Int, Int)] -> GridSquare -> Matrix -> Matrix
placePiece
is a function that takes an array of positions, a square to add, and the board and it adds the piece to the board. where the array of positions is the pattern for a piece. This way you can easily place any piece on the board using an array of positions starting at (0,0) easily using this function.
If I finish this project (after the due date, just for fun), there's a list of features I wanted to add to the game. These are features that are in the main tetris game that I didn't have time or want to dedicate time to implement:
- Soft dropping (faster falling so a piece isn't immediately set)
- Proper rotation, right now the center of rotation is calculated each time a piece is rotated. This leads to the piece slowly drifting to the side, or falling faster after each rotation. What would be ideal is to store the center of rotation as a part of the GridSquare data class, that way the rotation is actually around a center not just jankily slapped around.
- Scoring system, there's no score, I didn't want to figure out how to score the game so I just kind of didn't
- Holding, allowing players to hold on to a piece to use later
- Piece queue, allowing players to see what pieces are coming next so they can make better judgement on where to place their current pieces