Skip to content

Instantly share code, notes, and snippets.

@jackywyz
Forked from brianhsu/gist:792885
Created October 26, 2011 06:22
Show Gist options
  • Save jackywyz/1315610 to your computer and use it in GitHub Desktop.
Save jackywyz/1315610 to your computer and use it in GitHub Desktop.
[Scala] 剪刀石頭布猜拳大亂鬥
class Answer(val id: Int)
case object Rock extends Answer(0) {override def toString = "石頭"}
case object Paper extends Answer(1) {override def toString = "布"}
case object Scissor extends Answer(2) {override def toString = "剪刀"}
case class User(x: Int, score: Int = 20)
case class Turn(user: User, answer: Answer)
object Game {
val answers = Array(Rock, Paper, Scissor)
/**
* 開始進行某一局
*
* @param turn 某一局所有人出的拳
* @return 該局結束之後,存活下來的人
*/
def playTurn(turn: List[Turn]) = {
// 將所有人出的拳印出
turn.foreach { x => println ("%s 出 %s" format(x.user, x.answer)) }
// 判定該局勝負
judge(turn)
}
/**
* 判斷某一局的勝負
*
* 判斷條件:
*
* - 如果該局出現的拳種數目為 1(大家都出一樣)、3(剪刀、石頭、布都有出現),則該局平手
* - 如果該局出現的拳種數目為 2,以窮舉法判定輸贏
* - 贏的人分數加 10
* - 輸的人分數扣 10
* - 該局結束後分數為 0 的人出局,不再列入參賽者清單
*
* @param turn 某一局所有人出的拳
* @return 該局結束之後,存活下來的人
*/
def judge (turn: List[Turn]) = turn.map(_.answer).toSet.size match { // 所有人的拳種數量如果
// 是一或三就平手
case 1 | 3 =>
println ("全部平手")
turn.map(_.user)
// 是二就進行輸贏判定
case 2 =>
val group = turn.groupBy(_.answer).toList // 將使用者依他們出的拳種分組
.sortWith(_._1.id < _._1.id) // 並依照拳種的 ID 排序
// 用窮舉法找出贏的組別和輸的組別
val (winner, loser) = group match {
// 石頭對布、石頭對剪刀
case List((Rock, lose @ _), (Paper, win @ _)) => (win.map(_.user), lose.map(_.user))
case List((Rock, win @ _), (Scissor, lose @ _)) => (win.map(_.user), lose.map(_.user))
// 布對剪刀、布對石頭
case List((Paper, lose @ _), (Scissor, win @ _)) => (win.map(_.user), lose.map(_.user))
case List((Rock, lose @ _), (Paper, win @ _)) => (win.map(_.user), lose.map(_.user))
// 剪刀對石頭、剪刀對布
case List((Scissor, lose @ _), (Rock, win @ _)) => (win.map(_.user), lose.map(_.user))
case List((Scissor, win @ _), (Paper, lose @ _)) => (win.map(_.user), lose.map(_.user))
}
def forWin(user: User) = user copy (score = user.score + 10) // 加玩家十分
def forLose(user: User) = user copy (score = user.score - 10) // 扣玩家十分
val updateWinner = winner.map(forWin _) // 贏家全加十分
val updateLoser = loser.map(forLose _) // 輸家全扣十分
// 印出該局狀態
updateWinner.foreach (user => println (user + " 贏了"))
updateLoser.foreach (user => println (user + " 輸了"))
updateLoser.filter(_.score <= 0).foreach (user => println (user + " 退場"))
// 存活的人:贏家再加上分數還沒被扣到 0 分的輸家
updateWinner ++ updateLoser.filter(_.score > 0)
}
/**
* 遊戲結束
*/
def endGame(players: List[User]) = {
println ("=============")
println ("遊戲結束,以下為存活者及其積分:")
// 依分數排序後印出
players.sortWith(_.score > _.score).foreach {println _}
}
/**
* 亂數取他某使用者出的拳
*
* @param user 哪個使用者
* @return 該使用者那一局的策略
*/
def getUserAnswer(user: User) = {
val answerIndex = ((scala.math.random * 10) % 3).toInt
Turn(user, answers(answerIndex))
}
/**
* 開始遊戲
*
* @param n 倒數第 n 次
* @param players 此局參與的玩家
*/
def startGame(n: Int, players: List[User]): Unit = n match {
case 0 => endGame(players) // 時間到
case x if players.length == 1 => endGame(players) // 只剩一個,冠軍產生
case x =>
println ("============ 倒數第 %d/%d 次 =========" format(x, turnNumber))
// 取得每一個人出的拳
val turn = players.map {user => getUserAnswer(user)}
// 進行此局,並取得下一局仍然存活的玩家
val nextTurnPlayers = playTurn(turn)
startGame (n-1, nextTurnPlayers)
}
}
val turnNumber = 50 // 玩幾輪
val playerNumber = 5 // 幾個玩家
val players = (1 to playerNumber).map(User(_)).toList // 初始化玩家
Game.startGame(turnNumber, players) // 開始猜拳大亂鬥
'''print 格式化 => String 格式化,适用于python 的print语法
println("welcome %s ." format("jack"))
'''Java 版
String s = String.format("%d", factor);
System.out.println(s);
'''1.格式
%s 为字符串
%h %x 为十六进制
%d 为十进制
%o 为八进制
%f 为浮点数
'''2.空格
%10s 为左边空10个空格
res52: String = " 14"
%-10s 为右边空10个空格
res53: String = "14 "
@jackywyz
Copy link
Author

//copy方法
case class Test(name:String)
val p = Test("jack") copy (name="tomas")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment