CC BY 4.0 (除特别声明或转载文章外)
如果这篇博客帮助到你,可以请我喝一杯咖啡~
{-
设计一个交互程序,实现计算机(我)和用户(您)玩猜拳「石头、剪刀和布」。
例如,运行程序实现下来交互游戏:
*Main> play
请您出手 (R)石头, (S)剪刀, (P)布:p, 您出了布, 我出了石头
您赢了这手
我的得分: 0
您的得分: 1
请您出手 (R)石头, (S)剪刀, (P)布:s, 您出了剪刀, 我出了布
您赢了这手
我的得分: 0
您的得分: 2
请您出手 (R)石头, (S)剪刀, (P)布:r, 您出了石头, 我出了剪刀
您赢了这手
我的得分: 0
您的得分: 3
算您赢了这轮。
*Main> play
请您出手 (R)石头, (S)剪刀, (P)布:s, 您出了剪刀, 我出了布
您赢了这手
我的得分: 0
您的得分: 1
请您出手 (R)石头, (S)剪刀, (P)布:r, 您出了石头, 我出了石头
这一手平手
我的得分: 0
您的得分: 1
请您出手 (R)石头, (S)剪刀, (P)布:p, 您出了布, 我出了剪刀
我的得分: 1
您的得分: 1
请您出手 (R)石头, (S)剪刀, (P)布:p, 您出了布, 我出了剪刀
我的得分: 2
您的得分: 1
请您出手 (R)石头, (S)剪刀, (P)布:r, 您出了石头, 我出了剪刀
您赢了这手
我的得分: 2
您的得分: 2
请您出手 (R)石头, (S)剪刀, (P)布:s, 您出了剪刀, 我出了石头
我的得分: 3
您的得分: 2
哈哈,我赢了!
作业要求:
1. 模块命名为Game, 程序命名为play:: IO ();
2. 程序要仿照以上例子,输出交互过程和相关详细信息;
3. 使用下面的手势类型及instance定义,需要 import System.Random:
data Hand = Rock | Scissor | Paper deriving (Enum)
instance Random Hand where
random g = case randomR (0,2) g of
(r, g') -> (toEnum r, g')
randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
(r, g') -> (toEnum r, g')
你也可以自己将Hand定义为Random的实例,以便能够使用随机手势,如 randomIO :: IO Hand
4. 用户(您)的输入用字母表示:r, s和p(不分大小写)分别表示用户选择的石头、剪刀和布
5. 建议适当定义一些辅助函数,不要把所有的命令都写在函数play中
6. 一点提示:猜数和猜单词中定义了函数:
guess :: Int (或者String) -> IO ()
其中输入参数是要猜的数或单词,在一系列猜测过程中需要这个信息,以便决定是停止还是继续猜(递归)。那么,猜拳时可能也需要类似的信息。
提交要求:
1. 提交模块Game;
2. 仿照以上例子,至少给出计算机(我)和用户(您)各赢一次的运行截图。
-}
module Game where
import System.Random
import Text.Printf
data Hand = Rock | Scissor | Paper deriving (Enum,Eq)
instance Random Hand where
random g = case randomR (0,2) g of
(r, g') -> (toEnum r, g')
randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
(r, g') -> (toEnum r, g')
getHand::IO Hand
getHand=
do
s<-getLine
if (s=="r")||(s=="R")
then return Rock
else if (s=="s")||(s=="S")
then return Scissor
else return Paper
isWin::Hand->Hand->Bool
isWin p c=(p==Rock&&c==Scissor)||(p==Scissor&&c==Paper)||(p==Paper&&c==Rock)
toStr::Hand->String
toStr Rock="石头"
toStr Scissor="剪刀"
toStr Paper="布"
play::IO()
play=game 0 0
game::Int->Int->IO()
game a b=
do
putStrLn "请您出手 (R)石头, (S)剪刀, (P)布:"
ta<-getHand
tb<-randomIO::IO Hand
putStrLn(printf "您出了%s, 我出了%s" (toStr ta) (toStr tb))
if isWin ta tb
then do
putStrLn(printf "您赢了这手\n我的得分: %d\n您的得分: %d" b (a+1))
if a>1
then putStrLn "算您赢了这轮。"
else game (a+1) b
else if isWin tb ta
then do
putStrLn(printf "我赢了这手\n我的得分: %d\n您的得分: %d" (b+1) a)
if b>1
then putStrLn "哈哈,我赢了!"
else game a (b+1)
else do
putStrLn(printf "这一手平手\n我的得分: %d\n您的得分: %d" b a)
game a b
--main::IO()
--main=play