Current Sprint: 2. 實作遊戲開始
repo: https://github.com/side-project-at-SPT/ithome-ironman-2024-san-juan
swagger docs: https://side-project-at-spt.github.io/ithome-ironman-2024-san-juan/
# app/models/trading_house.rb
class TradingHouse
# ...
BASE_PRICES = [
[ 1, 1, 1, 2, 2 ],
[ 1, 1, 2, 2, 2 ],
[ 1, 1, 2, 2, 3 ],
[ 1, 2, 2, 2, 3 ],
[ 1, 2, 2, 3, 3 ]
].each_with_object({}).with_index { |(prices, hash), index|
hash[index] = prices
}.freeze
# ...
end
# app/models/trading_house.rb
class TradingHouse
# ...
def initialize(seed: nil)
raise ArgumentError, "seed must provided" unless seed
# assume seed is hex
srand(seed.to_i(16))
@order = [ 0, 1, 2, 3, 4 ].shuffle
end
# ...
end
srand()
不提供引數時,會回傳一個 seed number
而當 srand(n)
時,會以 n
為種子取用隨機數
如此給予相同的 n
,即能確保隨機方法(例如 shuffle
, rand
)的結果可控
因此在產生價格卡順序時,使用固定的 game.seed
來 shuffle,讓遊戲狀態可以重現
# app/models/trading_house.rb
class TradingHouse
# ...
def draw_next_trading_house_tile
el = @order.shift
@order.push(el)
self
end
# ...
end
# app/models/trading_house.rb
class TradingHouse
# ...
def current_price = BASE_PRICES[@order.first]
def indigo_price = current_price[0]
def sugar_price = current_price[1]
def tobacco_price = current_price[2]
def coffee_price = current_price[3]
def silver_price = current_price[4]
# ...
end
TradingHouse
物件,方便操作# app/models/trading_house.rb
class TradingHouse
# ...
def initialize(params = nil)
case params
in Array
@order = params
else
raise ArgumentError, "order or seed must be provided"
end
end
# ...
end
宣告一個類別方法負責處理 start new game
- generate a random seed 產生種子
- shuffle the 5 trading house tiles 洗勻價格卡
- deal indigo plant to players as initial building 抽出玩家人數的染坊卡片,發給每位玩家,作為起始建築
- shuffle remaining cards to form a deck 洗勻剩餘卡牌成為牌庫(抽牌堆)
- deal 4 cards to each player as their initial hand, hidden from other players 發給每位玩家四張卡片,作為手牌
- choose first player 決定起始玩家
# app/models/game.rb
class Game < ApplicationRecord
# ...
class << self
def start_new_game
game = new(status: :playing)
# 1. generate a random seed
game.seed = SecureRandom.hex(16)
# 2. shuffle the 5 trading house tiles
game.game_data[:trading_house_order] = TradingHouse.new(seed: game.seed).order
# 3. deal indigo plant to players as initial building
# 4. shuffle remaining cards to form a deck
# 5. deal 4 cards to each player as their initial hand, hidden from other players
# 6. choose first player
game.save
game
end
end
# ...
end
# app/controllers/api/v1/games_controller.rb
class Api::V1::GamesController < ApplicationController
# ...
def create
@game = Game.start_new_game
render json: { error: @game.errors.full_messages } unless @game.present?
end
# ...
end
# app/views/api/v1/games/_game.json.jbuilder
json.id game.id
json.status game.status
if game.status_unknown?
json.message "game not set up yet"
else
json.game_config do
json.seed game.seed
end
json.game_data do
json.current_price game.current_price
end
end
收工
也可以直接看 diff 38959be
Sprint 2: 實作遊戲開始
以上不代表明天會做,如有雷同純屬巧合
SPT (Side Project Taiwan) 的宗旨是藉由Side Project開發來成就自我,透過持續學習和合作,共同推動技術和專業的發展。我們相信每一個參與者,無論是什麼專業,都能在這個社群中找到屬於自己的成長空間。
歡迎所有對Side Project開發有興趣的人加入我們,可以是有點子來找夥伴,也可以是來尋找有興趣的Side Project加入,邀請大家一同打造一個充滿活力且有意義的技術社群!
Discord頻道連結: https://sideproj.tw/dc