精華區beta Ruby 關於我們 聯絡資訊
有在玩 D&D 的玩家一定知道所謂的 d20 系統… 也就是 20 面骰子的系統。不過說是 20 面骰子, 事實上還有各種其他面數的骰子: http://www.wizards.com/d20modern/d20mdice/dice.htm 更有甚者,其實整個 WarCraft III 的普通攻擊也是整個用骰子去做成的。 比方說,Human 的 Knight 的攻擊力就是 2d5 + 25, 也就是五面骰丟兩個, 然後再加上 25 成為最終傷害。如果我沒記錯的話,每升一次級,則是加上 一顆骰子。也就是 3 級的 Knight 是 5d5 + 25. 查查官方網站, http://www.battle.net/war3/human/units/knight.shtml 一個沒升級的 Knight 傷害平均是 31, (2+2*5)/2+25, 確實是 31, 滿級的是 40, (5+5*5)/2+25, 確實是 40... 然後一個單位的傷害極限是 100d100 +... 好吧,那個 +... 不要管了, 總之這樣傷害力就會是 100 ~ 10000, 一個很鬼扯的傷害範圍 為了查證我的推測沒錯,還不小心發現官網有看起來很有趣的地圖…… 有空可以抓來試試看。不過當然以上都不是重點,只是想表述一下骰子 對於遊戲的重要性。 重點在於,今天下午我開始試著用 Ruby 實作骰子系統。想要做到的就是 可以方便呼叫骰子,使用骰子。當然我知道這個東西很簡單,所以我也只是 大概寫寫,然後稍微介紹一下我是怎麼寫的… 目標使用介面是這樣: 2.roll # 等同於 2d20 => 2 ~ 40 3.roll(4) # 等同於 3d4 => 3 ~ 12 dice = 6.dice # 儲存 6d20 的骰子(s) dice = 8.dice(4) # 儲存 8d4 的骰子(s) dice.roll # 搖出那骰子(s) 只有這樣就太無趣了,來個結構比較複雜的骰子組,比方說 2d20 + 3d4 + 8d4 dice_set = DiceSet.new(2.dice, 3.dice(4), 8.dice(d)) dice_set.roll # 這就是… 2~40 + 3~12 + 8~32 共 13~84 更有甚者,使用 composite pattern... another_dice_set = DiceSet.new(2.dice, dice_set) 現在上面這個 another_dice_set 變成 2d20 + 原本設定好的 dice_set another_dice_set << 2.dice # 再追加 2d20 another_dice_set << DiceSet.new(dice_set, dice_set, 2.dice) 現在這個 another_dice_set 已經變成很瘋狂的骰子組了,我懶得算了… another_dice_set.roll # 擲出剛剛那瘋狂的骰子組 實作很簡單,相信看到這裡的各位都已經知道怎麼寫了,不過還是稍微 說明一下好了,也許還有在觀望的讀者也說不定? 由於 5.times 之類的東西讓我驚艷,所以我決定把骰子也加到數字裡面。 而這可以靠著 Ruby 動態擴充 class 來辦到,所以現在要決定的是要擴充 到哪個 class 中? 5 的型別是 Fixnum, 不過野心可以大一點,加到 Numeric 感覺會比較爽,於是可以丟出這種詭異的骰子:-123.456.roll, 還有這種: 12972398574892734896769868686934059230491204821491.roll(Bignum) 當然意義是不大,不過這是爽度問題…反正也不是什麼正經程式 XD class Numeric # 打開 Numeric 去擴充 def roll(faces = 20) # 沒輸入面數則預設 20 面(d20 中最常用) return nil unless self > 0 && self.integer? && faces > 0 && faces.integer? # 如果「面數」或「骰數」其中之一不是整數,或是負數, # 則…說真的我也不知道這種骰子要怎麼骰,所以暫時傳回 nil # 表示目前還不知道這個骰子的意義是什麼? result = 0 # 這是骰子丟出來的結果,先初始化為 0 1.step(self){ |i| result += rand(faces) + 1 } # ok, 這行的意思是 |i| 由 1 開始跑,|i| 遞增 1, # 直到 self 這個數字為止(包含 self) # self 的意思等同於 C++/Java 中的 this, # 而這個東西指向的是:Numeric, 也就是 2.roll 的 "2" # 所以 2.roll 的話,這裡的 self 是 2, 1 開始跑,到 2 為止, # 正好是跑兩次,也就是丟兩顆骰子,rand(N) 產生 0~N-1 的數字 # 所以骰子需要 +1 成為 1~N, 也就是這裡的 1~20 result # 最後一行可以省略 return... 所以這等同於 return result end end 預知詳情,下回分曉……今天雜事有點多 =.= 下回介紹 Dice, DiceSet, 還有我拿來測試的 TestDice -- Hear me exalted spirits. Hear me, be you gods or devils, ye who hold dominion here: I am a wizard without a home. I am a wonderer seeking refuge. Sacrifice -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.135.28.18
jaiyalas:XD 08/09 23:55
poga:推 XDD 08/10 00:03
PsMonkey:看不懂也可以推吧? [逃] 08/10 00:09
Schelfaniel:Ruby 外國文章說, 算是最容易學習的語言.. 08/10 01:31
ogamenewbie:推一個, 其他還有高過低於的骰數等等 (笑) 08/10 07:15
godfat:高低骰是什麼?@@ 其實我骰子不太熟 XD 不過似乎離題太多… 08/10 14:48
PttHuge:相當不錯的例子 :) 08/10 23:35