Skip to content

Instantly share code, notes, and snippets.

@d-ronnqvist
Created October 19, 2014 15:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d-ronnqvist/89768210611e18417b6d to your computer and use it in GitHub Desktop.
Save d-ronnqvist/89768210611e18417b6d to your computer and use it in GitHub Desktop.
Swift alternative to class clusters?

I wanted to use enums, structs, and classes to create small, elegant objects for a basic chess game.

It started with the small squares in the chess board, and created the logic part in the main definition and an extension that is use for rendering

enum Row: Character {
    case A = "A"
    case B = "B"
    case C = "C"
    case D = "D"
    case E = "E"
    case F = "F"
    case G = "G"
    case H = "H"
}

enum Column: Int {
    case One   = 1
    case Two   = 2
    case Three = 3
    case Four  = 4
    case Five  = 5
    case Six   = 6
    case Seven = 7
    case Eight = 8
}

struct Square {
    let row: Row
    let col: Column
}

extension Square {
    var position: SCNVector3 {
        get {
            // calculated based on row and column
        }
    }
}

Then I wanted to to something similar for the pieces, so I defined these enums

enum PieceType: String {
    case Pawn   = "Pawn"
    case Rook   = "Rook"
    case Knight = "Knight"
    case Bishop = "Bishop"
    case Queen  = "Queen"
    case King   = "King"
}

enum PieceColor {
    case White
    case Black
}

If this would have been Objective-C then I would have created a base class and used subclasses to override and customize behavior for the specific pieces (pawn, rook, knight, etc.). This class would have been implemneted as a class cluster so that one of the subclasses would have been returned based on the type that was passed to the initliazer

class Piece {
    let type: PieceType
    let color: PieceColor
    
    var location: Square?

    init(_ type: PieceType, color: PieceColor) {
        // In ObjC I would have done a class cluster here
    }
    
    var possibleSquaresToMoveTo: [Square] {
        get {
            return [] // base class isn't meant to be used
        }
    }
}

class Knight: Piece {
    init(color: PieceColor) {
        super.init(.Knight, color: color)
    }
    
    override var possibleSquaresToMoveTo: [Square] {
        get {
            // calculate possible squares based on the Knights movement pattern and the current location
        }
    }
}

The main problem I have with this design is that it's still possible to create a base instance, so the Piece initlizer shouldn't really be used.

My next idea was to rethink the possibleSquaresToMoveTo calculated property. Perhaps the Swift way would be to define a function that maps from the current square to all the possible squares that can be moved to (Square -> [Square])

In either case, the Chessboard would have to be involved to filter the results since the Piece doesn't know of all the other Pieces on the board and their locations. So maybe all of this logic really belongs in the board (alhtough I kind of like the idea that the piece gives the basic pattern and the board filters it down).

In either case, I'm trying to involve having switch aPiece.type in the code (with a class cluster I would only have it in the Piece initiliazer)


What would be a nice Swift (possibly even functional) way of solving this problem?

Copy link

ghost commented Nov 7, 2018

Would be great to see how you guys @d-ronnqvist @chriseidhof solve this problem after 4 years of study and experimentation with Swift.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment