Creating Musical Chairs Simulation in Haskell
Explore our comprehensive guide on how to write a program to simulate Musical Chairs in Haskell. Whether you're a Haskell enthusiast or need help with your Haskell assignment, this guide provides step-by-step instructions and explanations to enhance your understanding. Dive into the world of Haskell programming and find assistance for your assignments right here.
Prerequisites
Before we dive into the code, it's important to have a basic understanding of Haskell programming. If you're new to Haskell, consider going through some beginner-level Haskell guide to get familiar with its syntax and concepts.
The Code
Below is the Haskell code that simulates the Musical Chairs game. We've structured the code with explanations for each block to help you understand the different parts of the program.
```haskell
-- Import necessary modules and libraries
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import System.Random
-- Define the number of players and chairs
numPlayers :: Int
numPlayers = 5
numChairs :: Int
numChairs = 3
-- Define the game state type
type GameState = (TVar [ThreadId], TVar [ThreadId])
-- Define the player behavior function
player :: Int -> GameState -> IO ()
player id gameState = do
-- Simulate player's arrival time
threadDelay <$> randomRIO (1000000, 3000000)
putStrLn $ "Player " ++ show id ++ " has arrived."
-- Add player to waiting list and check for game start
atomically $ modifyTVar waitingList (\list -> list ++ [myThreadId])
atomically $ readTVar waitingList >>= checkGameStart
putStrLn $ "Player " ++ show id ++ " is sitting."
-- Remove player from waiting list and add to finished list
atomically $ modifyTVar waitingList (\list -> filter (/= myThreadId) list)
atomically $ modifyTVar finishedList (\list -> list ++ [myThreadId])
putStrLn $ "Player " ++ show id ++ " has finished."
atomically $ readTVar finishedList >>= checkGameEnd
where
checkGameStart waitingPlayers
| length waitingPlayers == numPlayers = do
players <- readTVar waitingList
forM_ players (\player -> forkIO (musicalChairs player gameState))
checkGameEnd finishedPlayers
| length finishedPlayers == numPlayers - 1 = do
putStrLn "Game Over!"
mapM_ killThread finishedPlayers
-- Define the musical chairs round function
musicalChairs :: ThreadId -> GameState -> IO ()
musicalChairs playerThread gameState = do
let (waitingList, finishedList) = gameState
atomically $ readTVar waitingList >>= checkRoundStart
putStrLn $ "Player " ++ show playerThread ++ " is out!"
atomically $ modifyTVar waitingList (\list -> filter (/= playerThread) list)
atomically $ modifyTVar finishedList (\list -> list ++ [playerThread])
where
checkRoundStart waitingPlayers
| length waitingPlayers == numPlayers - 1 = do
threadDelay 1000000
atomically $ writeTVar waitingList []
putStrLn "Musical chairs round started!"
-- Main function
main :: IO ()
main = do
-- Initialize game state
waitingList <- atomically $ newTVar []
finishedList <- atomically $ newTVar []
let gameState = (waitingList, finishedList)
putStrLn "Musical Chairs Game!"
-- Create player threads
forM_ [1..numPlayers] (\id -> forkIO (player id gameState))
-- Wait for players to finish
threadDelay 50000000
```
Running the Simulation
Follow these steps to run the simulation:
Copy the provided code into a Haskell source file (e.g., `MusicalChairs.hs`).
Compile the code using a Haskell compiler such as GHC:
```
ghc MusicalChairs.hs -o MusicalChairs
```
Run the compiled executable:
```
./MusicalChairs
```
Observe the output as the simulation of the Musical Chairs game unfolds.
Conclusion
You've successfully created a simulation of the Musical Chairs game using Haskell. The code covered the essential components of the game, explaining each block to help you understand the logic behind the simulation. Now, you can take this project to the next level by experimenting with the code, making enhancements, and exploring additional features to further improve the simulation and your Haskell programming skills.