전쟁할 시간입니다. 암호. 전쟁

16134 단어 elixir100daysofcode

1라운드. 4일차



이제 ElixirSchool 의 엘릭서 기초 지식을 갖추게 되었고, 이제 연습을 시작하고 첫 엘릭서 앱을 구축할 때라고 생각합니다. CodeWars 의 코드 챌린지로 오늘의 연습을 시작했습니다. 지침은 다음과 같았습니다.

Consider an array/list of sheep where some sheep may be missing from their place. We need a function that counts the number of sheep present in the array (true means present).
For example,



[true,  true,  true,  false,
  true,  true,  true,  true ,
  true,  false, true,  false,
  true,  false, false, true ,
  true,  true,  true,  true ,
  false, false, true,  true]


The correct answer would be 17.



이 챌린지의 상용구 코드는 다음과 같습니다.

defmodule Shepherd do
  def count_sheeps(sheeps) do
    # TODO: for Elixir only true/false values can be presented the in sheeps list
  end
end


이번 챌린지는 그다지 어렵지도 않고 조금은 친숙한 느낌도 들었습니다. 나는 재빨리 나의 엘릭서 학교 노트를 살펴보고 이 문제를 해결하기 위한 좋은 템플릿이 될 재귀 계산 기능을 찾았습니다. 엘릭서 스쿨functions에는 배열의 길이를 세는 함수가 있었습니다.

defmodule Length do
  def of([]), do: 0
  def of([_ | tail]), do: 1 + of(tail)
end


이 논리를 약간의 패턴 일치와 결합하면 트릭을 수행해야 합니다. 그리고 그것은 했다!

스포일러 경고



경고: 동일한 코드워 챌린지를 해결하려면 더 이상 스크롤하지 마십시오.

해결책




defmodule Shepherd do
  # This form of the function was taken directly from the example at elixir
  # school.
  def count_sheeps([]), do: 0
  # Next, we write a form of the function that pattern matches the first
  # element to see if it is "true". If it is, we add 1.
  def count_sheeps([true | tail]), do: 1 + count_sheeps(tail)
  # All other elements will count as 0.
  def count_sheeps([_ | tail]), do: 0 + count_sheeps(tail)
end


나의 첫 번째 엘릭서 앱



6년 전에 루비를 처음 배웠을 때, 제 첫 루비 앱은 cli 블랙잭 게임이었습니다. 루비 학습을 시작하기에 충분했다면 엘릭서에도 좋은 연습이 될 것입니다.

앱은 아직 진행 중인 작업이지만 여기까지가 내가 수행한 작업입니다. 나는 아마도 죽일 것 같은 새로운 mix 프로젝트를 만드는 것으로 시작했습니다./shrug 블랙잭에 가장 먼저 필요한 것은 카드입니다. 그래서 Card Struct를 만드는 것으로 시작했습니다.lib/card.ex
defmodule Card do
  defstruct suit: "", value: ""
end


그리고 각 카드는 Deck의 일부가 될 것이므로 Deck 구조체도 생성해 보겠습니다. 이 시점에서 내 객체 지향 프로그래밍 사고 방식이 내가 엘릭서를 작성하는 방식에 영향을 미치고 있다고 느꼈지만 계속 진행했습니다.
lib/deck.ex
defmodule Deck do
  # I used Module constants to specify the different suits and the card values.
  @suits [:heart, :diamond, :club, :spade]
  @values ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]

  # To generate the deck, we flat_map the @suits List using the shorthand
  # function syntax to pass the suit into the `Deck.build_suit/1` function.
  # Then, the List returned from the flat_map is shuffled using `Enum.shuffle`
  def generate do
    @suits
    |> Enum.flat_map(&(build_suit(&1)))
    |> Enum.shuffle()
  end

  # the `Deck.build_suit/1` function maps over the @values List and creates
  # %Card structs using the given suit and card value.
  defp build_suit(suit) do
    @values |> Enum.map(fn (value) -> %Card{ suit: suit, value: value } end)
  end
end


나쁘지 않은 시작입니다. 그러나 게임의state를 어떻게 저장하고 초기 거래를 처리할지 알아내려고 바퀴를 돌렸습니다. 마침내 효과가 있는 것을 함께 스크랩할 수 있었지만 확실히 변경될 수 있습니다.

defmodule Game do
  # I figured I could use a %Game struct to store the players and the current game's cards.
  # This will allow me to keep up with what a player's hand is as well as what
  # cards are still in play.
  defstruct players: [%Player{name: "player_one"}, %Player{name: "dealer"}], cards: Deck.generate()

  # With recursion on my mind from the earlier CodeWar Challenge, I created a
  # recursive deal function that would deal cards from the deck until each play
  # had their initial 2 cards.
  def deal(game) do
    cond do
      # The first conditional checks to see if all players have 2 cards
      Game.cards_dealt(game.players) -> game
      # The catch all conditional will deal a card to the first player in the
      # %Game struct then call deal again.
      true -> game |> deal_card(hd(game.players)) |> deal
    end
  end

  # deal_card/2 handles a couple of things.
  # 1. We pattern match the first `card` from the %Game.cards and the rest of
  # the cards. This essentially pulls a card from the deck.
  # 2. We update the %Game.players by giving the first `card` to the given player.
  # 3. Finally, we update the %Game struct cards to the `tail` from the original game argument.
  def deal_card(%{cards: [card | cards]} = game, player) do
    game
    |> update_players(Player.add_cards(player, card))
    |> case do
      game -> %{ game | cards: cards}
    end
  end

  def cards_dealt(players) do
    Enum.reduce(players, 0, fn player, acc -> acc + length(player.hand) end) == length(players) * 2
  end

  defp update_players(game, player) do
    players = game.players |> Enum.filter(fn (p) -> p.name != player.name end)

    # ++/2 is slower, but it makes it easier to deal the cards
    %{ game | players: players ++ [player]}
  end
end


이 문제를 더 잘 처리하는 방법에 대한 의견을 듣고 싶습니다. 아래에 의견을 남기거나 https://github.com/basicBrogrammer/blackjack_cli 에서 풀 리퀘스트를 열 수 있습니다. 시청해주셔서 감사합니다. 내일 뵙겠습니다.

나를 따르라 @



|

좋은 웹페이지 즐겨찾기