Pigeonhole
Pigeonhole provides a 2-dimensional grid using refined types for it's coordinates.
Installing
Add the following to build.sbt:
libraryDependencies += Seq("com.fmsbeekmans" %% "pigeonhole" % version)
Usage
scala> import com.fmsbeekmans.pigeonhole._
import com.fmsbeekmans.pigeonhole._
scala> import eu.timepit.refined.auto._
import eu.timepit.refined.auto._
scala> import eu.timepit.refined.W
import eu.timepit.refined.W
scala> val ticTacToeBoard: Grid[W.`3`.T, W.`3`.T] = Grid[W.`3`.T, W.`3`.T](3, 3)
ticTacToeBoard: com.fmsbeekmans.pigeonhole.Grid[Int(3),Int(3)] = Grid(3,3)
scala> val center: ticTacToeBoard.Pt = ticTacToeBoard.refinePoint(1, 1).right.get
center: ticTacToeBoard.Pt = Point(1,1)
scala> val rows = ticTacToeBoard.rows.map(ticTacToeBoard.row).toList
rows: List[cats.data.NonEmptyList[com.fmsbeekmans.pigeonhole.Point[Int(3),Int(3)]]] = List(NonEmptyList(Point(0,0), Point(1,0), Point(2,0)), NonEmptyList(Point(0,1), Point(1,1), Point(2,1)), NonEmptyList(Point(0,2), Point(1,2), Point(2,2)))
scala> val columns = ticTacToeBoard.columns.map(ticTacToeBoard.column).toList
columns: List[cats.data.NonEmptyList[com.fmsbeekmans.pigeonhole.Point[Int(3),Int(3)]]] = List(NonEmptyList(Point(0,0), Point(0,1), Point(0,2)), NonEmptyList(Point(1,0), Point(1,1), Point(1,2)), NonEmptyList(Point(2,0), Point(2,1), Point(2,2)))
scala> val diagonals = {
| val topLeft = ticTacToeBoard.refinePoint(0, 0).right.get
| topLeft.steps(Step(1, 1)).toList
| val topRight = ticTacToeBoard.refinePoint(0, 2).right.get
| topLeft.steps(Step(-1, 1)).toList
|
| Seq(
| topLeft.steps(Step(1, 1)).toList,
| topLeft.steps(Step(-1, 1)).toList
| )
| }
diagonals: Seq[List[com.fmsbeekmans.pigeonhole.Point[Int(3),Int(3)]]] = List(List(Point(0,0), Point(1,1), Point(2,2)), List(Point(0,0)))
scala> val winningCombinations = rows ++ columns ++ diagonals
winningCombinations: List[Product with Serializable] = List(NonEmptyList(Point(0,0), Point(1,0), Point(2,0)), NonEmptyList(Point(0,1), Point(1,1), Point(2,1)), NonEmptyList(Point(0,2), Point(1,2), Point(2,2)), NonEmptyList(Point(0,0), Point(0,1), Point(0,2)), NonEmptyList(Point(1,0), Point(1,1), Point(1,2)), NonEmptyList(Point(2,0), Point(2,1), Point(2,2)), List(Point(0,0), Point(1,1), Point(2,2)), List(Point(0,0)))
scala> val notOnTheBoard = ticTacToeBoard.refinePoint(3, 3)
notOnTheBoard: Either[String,ticTacToeBoard.Pt] = Left((3,3) is not a valid point in Grid(3,3))