Feedback on my Tic-Tac-Toe side project

Hey everyone,

My name is Nick and I’m new here :wave: . I was originally a C# Developer but I inherited an old Elixir/Phoenix project at my company. That was a year ago and I’ve been enjoying Elixir the more that I learn about it.

Anyway I’ve created this side project for a little Tic-tac-toe app using Elixir/GenServer to help me improve my skills. The repo can be found here: https://github.com/NickGowdy/tic-tac-toe. I would be grateful to anyone who could be me some tips/advice on how to improve this code.

Nick

A naming thing that jumped out - GameRegistry makes me think of the Elixir Registry, but it’s definitely not the same. The “usual” name for that module would be something like GameServer.

Definitely check out Registry and DynamicSupervisor; they are the foundation of handling many games on one server.

Regarding code quality: look for opportunities to eliminate code that doesn’t do anything and collapse Enum operations together. For instance, this code from GameEngine.check_grid:

    maybe_vertical_winner =
      dimensions
      |> Enum.map(fn d ->
        matches = Enum.count(grid, fn square -> square.x == d end) == 3

        case matches do
          true -> true
          false -> false
        end
      end)
      |> Enum.any?(fn match -> match == true end)

Enum.map(...) |> Enum.any?(fn match -> match == true end) can always be replaced with Enum.any?(... == true), giving:

    maybe_vertical_winner =
      dimensions
      |> Enum.any?(fn d ->
        matches = Enum.count(grid, fn square -> square.x == d end) == 3

        case matches do
          true -> true
          false -> false
        end == true
      end)

Since matches is the result of an == operation, the case statement is the identity function:

    maybe_vertical_winner =
      dimensions
      |> Enum.any?(fn d ->
        matches = Enum.count(grid, fn square -> square.x == d end) == 3

        matches == true
      end)

Similarly, x == true is also the identity function for the results of ==:

    maybe_vertical_winner =
      dimensions
      |> Enum.any?(fn d ->
        matches = Enum.count(grid, fn square -> square.x == d end) == 3

        matches
      end)

Now the binding to matches isn’t needed at all:

    maybe_vertical_winner =
      dimensions
      |> Enum.any?(fn d ->
        Enum.count(grid, fn square -> square.x == d end) == 3
      end)
3 Likes