{"id":25613589,"url":"https://github.com/sajjon/tictactoe","last_synced_at":"2026-07-15T22:31:37.235Z","repository":{"id":87412700,"uuid":"254192924","full_name":"Sajjon/TicTacToe","owner":"Sajjon","description":"TicTacToe written in pure Swift, playable in your favourite shell! (ascii graphics)","archived":false,"fork":false,"pushed_at":"2021-01-16T10:46:00.000Z","size":48,"stargazers_count":4,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-28T03:51:32.963Z","etag":null,"topics":["ascii-game","game","tictactoe","tictactoe-game"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sajjon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-04-08T20:25:30.000Z","updated_at":"2024-11-07T04:08:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"92852376-21c4-40c4-8be5-d1664e657669","html_url":"https://github.com/Sajjon/TicTacToe","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Sajjon/TicTacToe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sajjon%2FTicTacToe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sajjon%2FTicTacToe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sajjon%2FTicTacToe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sajjon%2FTicTacToe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sajjon","download_url":"https://codeload.github.com/Sajjon/TicTacToe/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sajjon%2FTicTacToe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35523582,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-15T02:00:06.706Z","response_time":131,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ascii-game","game","tictactoe","tictactoe-game"],"created_at":"2025-02-22T01:36:12.765Z","updated_at":"2026-07-15T22:31:37.229Z","avatar_url":"https://github.com/Sajjon.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TicTacToe\n\n## Play\n\n```sh\nswift run TicTacToe\n```\n\nWhich starts the game, presenting this beautiful ascii graphics:\n\n```bash\n 1 │ 2 │ 3\n───┼───┼───\n 4 │ 5 │ 6\n───┼───┼───\n 7 │ 8 │ 9\n\nplayerX, which square:\n```\n\nAnd since this is the most pointless game in the history of games, get used to seeing the draw result.\n\n```bash\n⚖️ Game ended with a draw\n\n\n o │ x │ x\n───┼───┼───\n x │ x │ o\n───┼───┼───\n o │ o │ x\n```\n\nAnd in some rare cases where your partner had one to many 🍺 you might see this:\n\n```bash\nplayerX, which square:\n9\n\n🎉  playerX won!\n\n\n x │ o │ o\n───┼───┼───\n 4 │ x │ 6\n───┼───┼───\n 7 │ 8 │ x\n```\n\n\n## Implementation\n\n### `main.swift`\n\n```swift\nfunc run() throws {\n    var game = TicTacToe(matchUp: .humanVersusHuman)\n    \n    var result: TicTacToe.Result!\n    repeat {\n        result = try game.play()\n    } while result == nil\n    \n    print(\"\\n\\(result!)\")\n    game.printBoard()\n}\n```\n\n### `TicTacToe.swift`\n\n```swift\nmutating func play() throws -\u003e Result? {\n    defer { activePlayer.toggle() }\n    \n    let index = repeatedReadSquare(\n        prompt: \"\\(activePlayer), which square:\",\n        ifBadNumber: \"☣️  Bad input\",\n        ifSquareTaken: \"⚠️  Square not free\",\n        tipOnHowToExitProgram: \"💡 You can quit this program by pressing: `CTRL + c`\"\n    ) { board.is(square: $0, .free) }\n        \n    try board.play(index: index, by: activePlayer)\n    \n    if board.isFull() {\n        return .draw\n    } else {\n        return board.winner().map { .win(by: $0) }\n    }\n}\n```\n\n### `Board` \n\n```swift\npublic extension TicTacToe {\n    struct Board: Equatable, CustomStringConvertible {\n        internal var fillAtSquare: [Square: Fill] = [:]\n    }\n}\n\nextension TicTacToe.Board {\n    /// Squares 0 through 8\n    enum Square: UInt8, ExpressibleByIntegerLiteral, CaseIterable, Hashable {\n        case zero, one, two, three, four, five, six, seven, eight\n    }\n}\n```\n\n#### Got smarter ASCII print? PR!\n\n```swift\npublic extension TicTacToe.Board {\n    func ascii() -\u003e String {\n        Self.rows\n            .map(ascii(row:))\n            .joined(separator: \"\\n───┼───┼───\\n\")\n    }\n}\n\nprivate extension TicTacToe.Board {\n    \n    func ascii(row: Row) -\u003e String {\n        \" \" + row.map(ascii(square:)).joined(separator: \" │ \")\n    }\n\n    func ascii(square: Square) -\u003e String {\n        self[square].map({ $0.ascii }) ?? square.ascii\n    }\n}\n\nprivate extension TicTacToe.Board.Fill {\n    var ascii: String { rawValue }\n}\n\nprivate extension TicTacToe.Board.Square {\n    var ascii: String { \"\\(rawValue + 1)\" }\n}\n\n\n```\n\n#### Got smarter win condition check? PR!\n\n```swift\npublic extension TicTacToe.Board {\n    func winner() -\u003e Player? {\n        func hasPlayerWon(_ player: Player) -\u003e Bool {\n            func check(_ squareMatrix: [[Square]]) -\u003e Bool {\n                squareMatrix.reduce(false, { hasWon, squareList in\n                    hasWon || squareList.allSatisfy({ hasPlayer(player, filledSquare: $0) })\n                })\n            }\n            \n            return Self.winConditions.reduce(false, { hasWon, squareMatrix in\n                hasWon || check(squareMatrix)\n            })\n        }\n        \n        return Player.allCases.first(where: { hasPlayerWon($0) })\n    }\n}\n\n\nextension TicTacToe.Board {\n    \n    typealias Row       = [Square]\n    typealias Column    = [Square]\n    typealias Diagonal  = [Square]\n    \n    // MARK: Rows\n    static let firstRow:        Row = [0, 1, 2]\n    static let secondRow:       Row = [3, 4, 5]\n    static let thirdRow:        Row = [6, 7, 8]\n    static let rows:            [Row] = [firstRow, secondRow, thirdRow]\n    \n    // MARK: Columns\n    static let firstColumn:     Column = [0, 3, 6]\n    static let secondColumn:    Column = [1, 4, 7]\n    static let thirdColumn:     Column = [2, 5, 8]\n    static let columns:         [Column] = [firstColumn, secondColumn, thirdColumn]\n    \n    // MARK: Diagonals\n    \n    /// Main, Major, Principal, Primary; diagonal: ╲\n    /// from top left, to bottom right\n    static let mainDiagonal:    Diagonal = [2, 4, 6]\n    \n    /// Anti-, Minor, Counter, Secondary; diagonal: ╱\n    /// from bottom left, to top right\n    static let antiDiagonal:    Diagonal = [0, 4, 8]\n    static let diagonals:       [Diagonal] = [mainDiagonal, antiDiagonal]\n    \n    static let winConditions: [[[Square]]] = [rows, columns, diagonals]\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsajjon%2Ftictactoe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsajjon%2Ftictactoe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsajjon%2Ftictactoe/lists"}