{"id":19096696,"url":"https://github.com/stavarengo/php-tic-tac-toe","last_synced_at":"2026-06-29T14:31:29.402Z","repository":{"id":147860052,"uuid":"181371323","full_name":"stavarengo/php-tic-tac-toe","owner":"stavarengo","description":"Single player Tic Tac Toe game with a bot as the opponent. The bot uses Minimax algorithm to decides its moves.","archived":false,"fork":false,"pushed_at":"2021-01-07T17:21:59.000Z","size":123,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-22T08:57:48.959Z","etag":null,"topics":["minimax","minimax-algorithm","tic-tac-toe","tictactoe","tictactoe-game"],"latest_commit_sha":null,"homepage":"https://php-tic-tac-toe.stavarengo.me","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stavarengo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2019-04-14T21:30:10.000Z","updated_at":"2024-01-08T09:52:07.000Z","dependencies_parsed_at":"2023-05-27T17:30:11.840Z","dependency_job_id":null,"html_url":"https://github.com/stavarengo/php-tic-tac-toe","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/stavarengo/php-tic-tac-toe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stavarengo%2Fphp-tic-tac-toe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stavarengo%2Fphp-tic-tac-toe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stavarengo%2Fphp-tic-tac-toe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stavarengo%2Fphp-tic-tac-toe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stavarengo","download_url":"https://codeload.github.com/stavarengo/php-tic-tac-toe/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stavarengo%2Fphp-tic-tac-toe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34931580,"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-06-29T02:00:05.398Z","response_time":58,"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":["minimax","minimax-algorithm","tic-tac-toe","tictactoe","tictactoe-game"],"created_at":"2024-11-09T03:37:32.161Z","updated_at":"2026-06-29T14:31:29.381Z","avatar_url":"https://github.com/stavarengo.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# php-tic-tac-toe\n\n## About the project\n\n- To see it in action, go to [http://php-tic-tac-toe.stavarengo.me](http://php-tic-tac-toe.stavarengo.me/), or you\n  can run it locally with Docker, by running `sudo docker run stavarengo/php-tic-tac-toe` and then .\n- The bot uses the [Minimax Algorithm] to decide its moves. You can see it on [\\TicTacToe\\App\\Bot\\MinimaxBot].\n- The application is 100% covered with tests using [PHPUnit].\n- This is a modular application, compound of three modules: \n  1. `App`: Where you can find behaviors not related to an API nor to a Web Interface, as\n            the game board and the bots.\n  1. `Api`: This is where reside the API. This module only has behaviors related to API requests. There you will\n            find the Requests Handlers (AKA controllers), entities used in the API responses, etc.\n  1. `WebUi`: The main responsibility of WebUi is to render views, but not only that. More generally, it is responsible\n              for respond all requests that the API does not know how to handle.\n- No dependency on third-party code other than [PHPUnit], [Bootstrap] (CSS library) and [FontAwesome] (icon library). \n  Everything has been written from scratch. Why? Just because.\n- This is a object-oriented PHP, thus it use principles like S.O.L.I.D., G.R.A.S.P., etc.\n\n\n## Getting Started\n\nStart the project with composer:\n```bash\n$ composer install\n```\n\n#### Running with PHP's Built-in web server\n\nAfter installing the packages, start PHP's built-in web server:\n```bash\n$ composer run --timeout=0 serve\n```\nYou can then browse to [http://127.0.0.1:4000](http://127.0.0.1:4000)\n\nIf you want to start the serve using port different of 4000, you can start the server manually:\n```bash\n$ php -S 0.0.0.0:_YOU_PORT_ -t public/\n```\n\n\u003e ##### Linux users\n\u003e\n\u003e On PHP versions prior to 7.1.14 and 7.2.2, this command might not work as expected due to a bug in PHP that only\n\u003e affects linux environments. In such scenarios, you will need to start the\n\u003e [built-in web server](http://php.net/manual/en/features.commandline.webserver.php) yourself using the following\n\u003e command:\n\u003e ```bash\n\u003e $ php -S 0.0.0.0:4000 -t public/ public/index.php\n\u003e ```\n\n### WebUi Module\n\nBellow is a list of all the JS API and JS objects this the front-end uses.\n- [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON)\n- [https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)\n- [https://developer.mozilla.org/en-US/docs/Web/API/Element/classList](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)\n- [https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)\n\n### Api Module\n\nThe `php-tic-tac-toe` provides an RESTful API that allows you to manipulate the game. The operations you can do, through\nthe API, are:\n- Start a new game using [`POST /api/board`];\n- Set the human move using [`PUT /api/board`];\n- Get the current game state using [`GET /api/board`];\n- Reset/delete the current game using [`DELETE /api/board`].\n\n\u003ca id=\"the-game-state\"\u003e\u003c/a\u003e\n#### Layout of the Responses: The Game State\nAll endpoints (except for [`DELETE /api/board`]), when completed successfully, respond with a JSON representing the \ncurrent game state. The following is the JSON used to represent the game state.\n\u003e If the request fails, then it responds with [The Error Response Layout].\n```js\n{\n    // The `game` attribute will be `null` when there is no game started yet.\n    \"game\": {\n    \n        // The `winner` attribute will be `null` if the game does not have a winner yet.\n        \"winner\": {\n        \n            // It will be the string `draw` or the unit of the player that won.\n            \"result\":\"X\",\n            \n            // The coordinates in the board where the victory was found.\n            // It will be null in case of `draw`.\n            \"coordinates\":[[0, 0], [1, 0], [2, 0]]\n        }\n    },\n    \n    // The current board status.\n    // Each position will be either an empty string or one of the units chosen by the players.\n    \"board\": [\n        [\"X\", \"\", \"O\"],\n        [\"X\", \"O\", \"\"],\n        [\"X\", \"\", \"O\"]\n    ],\n    \n    // The `units` attribute contains the units of each player.\n    // For example, the \"human\" could be \"X\" and the bot \"O\".\n    \"units\": { \n        \"human\": \"X\",\n        \"bot\": \"O\"\n    }\n}\n```\n\n\u003ca id=\"the-error-response-layout\"\u003e\u003c/a\u003e\n#### Layout of the Responses: The Error Response\nAll endpoints (including [`DELETE /api/board`]), when end in failure, respond with a JSON trying to describe why the \nerror happens (for example, it would fail if you forget to send a required parameter). The following is the JSON used \nto represent and error response. \n\u003e If the request ends successfully, then it responds with [The Game State].\n\n ```js\n{\n  // This attribute will always be `true`\n  \"error\": true,\n  \n  // An string containing more details about the error.\n  \"detail\": \"Missing the \\\"botUnit\\\" attribute.\"\n}\n ```\n\n#### API endpoints\n\n\u003ca id=\"get-board\"\u003e\u003c/a\u003e\n##### `GET /api/board`\nReturns de current game state.\nThis endpoint can be consumed even if there is no game has started yet.\n\n**Curl example**\n```bash\n$ curl -X GET 'http://127.0.0.1:4000/api/board'\n```\n\n**Expected responses code**\n- `200 - Success`: In this case the response body will be [The Game State].\n\n\u003ca id=\"post-board\"\u003e\u003c/a\u003e\n##### `POST /api/board`\nStarts a new game.\nIt expect that the request body contains a JSON with the following layout:\n```js\n{\n  // The unit the human choose for this game: \"X\" or \"O\".\n  \"humanUnit\": \"X\",\n  // The unit the bot should use: \"X\" or \"O\".\n  \"botUnit\": \"O\"\n}\n```\n\n**Curl example**\n```bash\n$ curl -X POST 'http://127.0.0.1:4000/api/board' --data-binary '{\"humanUnit\": \"X\", \"botUnit\": \"O\"}'\n```\n\n**Expected responses code**\n- `201 - Created`: It means that a new game started. In this case the response body will be [The Game State].\n- `422 - Unprocessable Entity`: When there were missing parameters or invalid parameters. In this case the response body will be [The Error Response Layout].\n- `409 - Conflict`: If there is already a game started. In this case the response body will be [The Error Response Layout].\n- `400 - Bad Request`: If there the request could not be processed for an unexpected reason. In this case the response body will be [The Error Response Layout].\n\n\u003ca id=\"put-board\"\u003e\u003c/a\u003e\n##### `PUT /api/board`\nSet the human move.\nThis endpoint will store the human move and also perform the bot move.\nIt expect that the request body contains a JSON with the following layout:\n```js\n{\n  // The attributes `row` and `column` indicates the position the human choose do move.\n  // It sould be an integer greate or equals to 0, and less or equals to 2.\n  \"row\": 0,\n  \"column\": 2\n}\n```\n\n**Curl example**  \nFirst we need to start a game with [`POST /api/board`] and get the PHP Session ID where the game were started. Only \nafter that we can set a human move using [`PUT /api/board`] endpoint and the same Session ID we get from the POST request.\n```bash\n$ curl -X POST 'http://127.0.0.1:4000/api/board' --data-binary '{\"humanUnit\": \"X\", \"botUnit\": \"O\"}' -H 'Cookie: PHPSESSID=1;'\n$ curl -X PUT 'http://127.0.0.1:4000/api/board' --data-binary '{\"row\": 0, \"column\": 2}' -H 'Cookie: PHPSESSID=1;'\n```\n\n**Expected responses code**\n- `200 - Success`: In this case the response body will be [The Game State] (already with the human and the bot move).\n- `422 - Unprocessable Entity`: When there are missing parameters or invalid parameters. In this case the response body will be [The Error Response Layout].\n- `400 - Bad Request`: If The bot chosen an invalid move to perform or if the move you choose can not be performed by any reason (For example, when you choose to move in a place already in use). [The Error Response Layout].\n- `409 - Conflict`: If there is no game started yet or if there is a game but it is already done. In this case the response body will be [The Error Response Layout].\n\n\u003ca id=\"delete-board\"\u003e\u003c/a\u003e\n##### DELETE /api/board\nDelete the current game. No error will be throw if there is no game to be deleted. You can consume this endpoint even\nif no game exists. After this, you will going to need to start a new game if you want to play again.\n\n**Curl example**\n```bash\n$ curl -X DELETE 'http://127.0.0.1:4000/api/board'\n```\n\n**Expected responses code**\n- `204 - No Content`: It means that the game was deleted, therefor you need to start a new game if you want to play again.\n\n[Bootstrap]: https://getbootstrap.com/\n[FontAwesome]: https://fontawesome.com\n[PHPUnit]: https://phpunit.de/\n[Minimax Algorithm]: https://en.wikipedia.org/wiki/Minimax\n[`POST /api/board`]: #post-board\n[`PUT /api/board`]: #put-board\n[`GET /api/board`]: #get-board\n[`DELETE /api/board`]: #delete-board\n[The Game State]: #the-game-state\n[The Error Response Layout]: #the-error-response-layout\n[\\TicTacToe\\App\\Bot\\MinimaxBot]: https://github.com/stavarengo/php-tic-tac-toe/blob/master/src/App/Bot/MinimaxBot.php\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstavarengo%2Fphp-tic-tac-toe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstavarengo%2Fphp-tic-tac-toe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstavarengo%2Fphp-tic-tac-toe/lists"}