Game Development Journal 10: Changing the Player Enum to an Array

Back when I created my Player class, I was trying to figure out how to organize players. I needed to have three players that I would keep in a specific order. My initial idea was to put them in an enum:

enum Players {
    case PlayerA
    case PlayerB
    case PlayerC
}

This was really bothering me. I knew I wanted some way to switch between players and we would always have a current player.

I was trying to figure out how to make this work and I realized I made a grievous error. I was misusing Enumerations.

Enumerations are good for things where you have options that result in you doing something. The example used in the Swift programming book from Apple does a really good job of showing what they mean by that:

enum Direction {
    case North
    case South
    case East
    case West
}

Having these directions in an enum allows you to create conditional logic where you have different actions based on what direction is currently selected.

It is not good at directly affecting and changing any of the case statements in the enum.

I need a data structure that holds three players. I need to know the order the players are in. I have to be able to affect the properties based on things that happen in the code.

I thought about putting these in a dictionary, but I realized that wasn’t really optimal. Dictionaries have orders, but they’re meant to correlate to keys and values. I just need to know what the current player is so I can set its properties and move on to the next one reliably.

I decided I needed an array of players. This array of players has to be initialized in the Game class and passed into the Hand class. The Player needs to be initialized with the initial amount of money that each player starts with.

I created a function that generates an array of players:

func createPlayers(startingMoney:Int) -> [Player] {
    let player = Player(money: startingMoney)
    return Array(repeatElement(player, count: 3))
}

I can then call this function in the Game class and set it to a variable that I can pass to the Hand class. The Hand plays through a round, determines the winner, and returns it to the Game so the Game can determine if another round should be played.

This means that I needed to add a few methods to the Player class to accommodate for these implementation details:

    init(money:Int) {
        currentMoney = money
        numberOfDeferrals = 0
        numberOfPoints = 0
    }
    
    // Reset Players
    mutating func resetPlayer() {
        hand.removeAll()
        capturedCards.removeAll()
        numberOfDeferrals = 0
        numberOfPoints = 0
    }

When the Player is initialized, it is created with the starting amount of money. When a Hand is completed, a Player’s properties need to be reset.

This clarifies a lot of what I need to do in the Hand Class. Now that I know I am using an array of players rather than an enum, I can create all of my properties that I need for a Hand:

    /*
      1. Players
      2. Current Player
      3. Shuffled Deck
      4. Cards on Board
      5. Draw Pile
    */

    var players:[Player]
    var currentPlayer:Player
    let shuffledDeck = shuffleDeck(deck: deck)
    var cardsInPlay = [Card]()
    var drawPile = [Card]()

As per my work in my previous post on figuring out what components I need, I have been able to figure out what type each of my properties are.

I made a mistake when creating my initializer. At first I made the current player a Player object. My initializer looked like this:

    init(playerArray:[Player], firstPlayer:Player) {
        players = playerArray
        currentPlayer = players[firstPlayer]
        dealCards(shuffledDeck: shuffledDeck)
    }

I thought that made a lot of sense, to make the currentPlayer an instance of the Player struct, but I realized that doing this divorced it from the player array.

The game logic basically requires a player to complete their turn and for the process to continue with the next player. By pulling out the current player from the array and making a copy of it in the current player, I have no way of knowing if that player is the first player or the hundredth. I need to persist where I am in my cycle of players because the current player keeps changing.

So I changed my currentPlayer property to:

var currentPlayer:Int = 0

and my initializer to:

    init(playerArray:[Player], firstPlayer:Int) {
        players = playerArray
        currentPlayer = firstPlayer
        dealCards(shuffledDeck: shuffledDeck)
    }

Now being able to go to the next player is fairly simple. I created a method to move to the next player in the array:

   func nextPlayer() {
        if currentPlayer == 2 {
            currentPlayer = 0
        } else {
            currentPlayer += 1
        }
    }

I made this a method on the Hand class. I had hoped to make this into a standalone function so it would be easier to test and be reusable within the application, but I decided against that for two reasons:

  • It makes the function a lot messier. I have to pass in the current index and pass back the return function. I would much rather just call nextPlayer() and not worry about it.
  • I don’t think I actually need this anywhere else in the code. There is no point in over engineering the app adding a bunch of stuff you won’t need.

Conclusions

I am in the process of building out the dealCards() method. I have to deal four cards to each player, then deal three to the table, then three more to each player, and then three to the table. I have to switch players several times and organize all the arrays properly.

I would like to be able to pinch off the first few elements of one array and give them to another array. I know I need to copy those elements and probably remove them from the shuffled deck array.

I can think of some really inefficient ways of doing this. I might write that method out inefficiently first so I can see where all the repeated code is. Writing bad code is an underestimated way to find your way to good code. Embrace bad code!!