昨天我們按照要改動的事項一個一個的做了出牌的方法
今天來調整一下
def play_card(pid, :host, card) do
GenServer.cast(pid, {:play_card, :host, card})
end
def handle_cast({:play_card, :host, card}, game) do
%{host: host} = game
# 從 hand 裡面拿掉一張 1
new_hand = host.hand -- [card]
# 把 1 加在 host 的 desk 裡面
new_desk = host.desk ++ [card]
# 組成新的 host 來替換舊的
new_host = Map.merge(host, %{hand: new_hand, desk: new_desk})
# 組成新的 game 來替換舊的
new_game = Map.replace(game, :host, new_host)
# 讓 process 使用新的 game
{:noreply, new_game}
end
首先我們先解決 guest 還不能出牌的問題,
其實就複製一份 handle_cast({:play_card, :host, card}, game)
方法
再把裡面的 host
都改成 guest
就可以了,但是這樣變超長,
再更改之前先講一下同名方法。
elixir 可以有同名方法,呼叫的時候會從上面開始 pattern matching 變數,
舉例來說
defmodule Lunch do
def eat("apple") do
end
def eat("cake") do
end
def eat(other) do
end
end
如果我呼叫 Lunch.eat("apple")
就會對應到第一個
如果我呼叫 Lunch.eat("pie")
因為前兩項都不符合,所以會到第三個,並把 other 變數賦予 "pie"
def handle_cast({:play_card, :host, card}, game) do
%{host: host} = game
new_hand = host.hand -- [card]
new_desk = host.desk ++ [card]
new_host = Map.merge(host, %{hand: new_hand, desk: new_desk})
new_game = Map.replace(game, :host, new_host)
{:noreply, new_game}
end
def handle_cast({:play_card, :guest, card}, game) do
%{guest: guest} = game
new_hand = guest.hand -- [card]
new_desk = guest.desk ++ [card]
new_host = Map.merge(guest, %{hand: new_hand, desk: new_desk})
new_game = Map.replace(game, :guest, new_host)
{:noreply, new_game}
end
我們來做一個方法把重複的地方拉出來
def handle_cast({:play_card, :host, card}, game) do
%{host: host} = game
new_host = play_card_helper(host)
new_game = Map.replace(game, :host, new_host)
{:noreply, new_game}
end
def handle_cast({:play_card, :guest, card}, game) do
%{guest: guest} = game
new_guest = play_card_helper(guest)
new_game = Map.replace(game, :guest, new_host)
{:noreply, new_game}
end
defp play_card_helper(data) do
new_hand = data.hand -- [card]
new_desk = data.desk ++ [card]
Map.merge(data, %{hand: new_hand, desk: new_desk})
end
再把那些等號拆掉
def handle_cast({:play_card, :host, card}, game) do
%{host: host} = game
{:noreply, Map.replace(game, :host, play_card_helper(host, card))}
end
def handle_cast({:play_card, :guest, card}, game) do
%{guest: guest} = game
{:noreply, Map.replace(game, :guest, play_card_helper(guest, card))}
end
defp play_card_helper(data, card) do
Map.merge(data, %{hand: data.hand -- [card], desk: data.desk ++ [card]})
end
我們可以再 pattern matching 方法的過程,直接從 game 裡面取用 %{host: host}
def handle_cast({:play_card, :host, card}, %{host: host} = game) do
{:noreply, Map.replace(game, :host, play_card_helper(host, card))}
end
def handle_cast({:play_card, :guest, card}, %{host: host} = game) do
{:noreply, Map.replace(game, :guest, play_card_helper(guest, card))}
end
defp play_card_helper(data, card) do
Map.merge(data, %{hand: data.hand -- [card], desk: data.desk ++ [card]})
end
好像可以改的更好,至少更好讀一點,比起這樣塞成一行
但是先這樣吧,還有很多功能要做
如果是以別人好讀懂的方向來調整,你會怎麼做呢?
(別人就是未來的自己哈哈)