- To see it in action, go to http://php-tic-tac-toe.stavarengo.me, or you
can run it locally with Docker, by running
sudo docker run stavarengo/php-tic-tac-toe
and then . - The bot uses the Minimax Algorithm to decide its moves. You can see it on \TicTacToe\App\Bot\MinimaxBot.
- The application is 100% covered with tests using PHPUnit.
- This is a modular application, compound of three modules:
App
: Where you can find behaviors not related to an API nor to a Web Interface, as the game board and the bots.Api
: This is where reside the API. This module only has behaviors related to API requests. There you will find the Requests Handlers (AKA controllers), entities used in the API responses, etc.WebUi
: The main responsibility of WebUi is to render views, but not only that. More generally, it is responsible for respond all requests that the API does not know how to handle.
- No dependency on third-party code other than PHPUnit, Bootstrap (CSS library) and FontAwesome (icon library). Everything has been written from scratch. Why? Just because.
- This is a object-oriented PHP, thus it use principles like S.O.L.I.D., G.R.A.S.P., etc.
Start the project with composer:
$ composer install
After installing the packages, start PHP's built-in web server:
$ composer run --timeout=0 serve
You can then browse to http://127.0.0.1:4000
If you want to start the serve using port different of 4000, you can start the server manually:
$ php -S 0.0.0.0:_YOU_PORT_ -t public/
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 affects linux environments. In such scenarios, you will need to start the built-in web server yourself using the following command:
$ php -S 0.0.0.0:4000 -t public/ public/index.php
Bellow is a list of all the JS API and JS objects this the front-end uses.
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
- https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
- https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
- https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
The php-tic-tac-toe
provides an RESTful API that allows you to manipulate the game. The operations you can do, through
the API, are:
- Start a new game using
POST /api/board
; - Set the human move using
PUT /api/board
; - Get the current game state using
GET /api/board
; - Reset/delete the current game using
DELETE /api/board
.
All endpoints (except for DELETE /api/board
), when completed successfully, respond with a JSON representing the
current game state. The following is the JSON used to represent the game state.
If the request fails, then it responds with The Error Response Layout.
{
// The `game` attribute will be `null` when there is no game started yet.
"game": {
// The `winner` attribute will be `null` if the game does not have a winner yet.
"winner": {
// It will be the string `draw` or the unit of the player that won.
"result":"X",
// The coordinates in the board where the victory was found.
// It will be null in case of `draw`.
"coordinates":[[0, 0], [1, 0], [2, 0]]
}
},
// The current board status.
// Each position will be either an empty string or one of the units chosen by the players.
"board": [
["X", "", "O"],
["X", "O", ""],
["X", "", "O"]
],
// The `units` attribute contains the units of each player.
// For example, the "human" could be "X" and the bot "O".
"units": {
"human": "X",
"bot": "O"
}
}
All endpoints (including DELETE /api/board
), when end in failure, respond with a JSON trying to describe why the
error happens (for example, it would fail if you forget to send a required parameter). The following is the JSON used
to represent and error response.
If the request ends successfully, then it responds with The Game State.
{
// This attribute will always be `true`
"error": true,
// An string containing more details about the error.
"detail": "Missing the \"botUnit\" attribute."
}
Returns de current game state. This endpoint can be consumed even if there is no game has started yet.
Curl example
$ curl -X GET 'http://127.0.0.1:4000/api/board'
Expected responses code
200 - Success
: In this case the response body will be The Game State.
Starts a new game. It expect that the request body contains a JSON with the following layout:
{
// The unit the human choose for this game: "X" or "O".
"humanUnit": "X",
// The unit the bot should use: "X" or "O".
"botUnit": "O"
}
Curl example
$ curl -X POST 'http://127.0.0.1:4000/api/board' --data-binary '{"humanUnit": "X", "botUnit": "O"}'
Expected responses code
201 - Created
: It means that a new game started. In this case the response body will be The Game State.422 - Unprocessable Entity
: When there were missing parameters or invalid parameters. In this case the response body will be The Error Response Layout.409 - Conflict
: If there is already a game started. In this case the response body will be The Error Response Layout.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.
Set the human move. This endpoint will store the human move and also perform the bot move. It expect that the request body contains a JSON with the following layout:
{
// The attributes `row` and `column` indicates the position the human choose do move.
// It sould be an integer greate or equals to 0, and less or equals to 2.
"row": 0,
"column": 2
}
Curl example
First we need to start a game with POST /api/board
and get the PHP Session ID where the game were started. Only
after that we can set a human move using PUT /api/board
endpoint and the same Session ID we get from the POST request.
$ curl -X POST 'http://127.0.0.1:4000/api/board' --data-binary '{"humanUnit": "X", "botUnit": "O"}' -H 'Cookie: PHPSESSID=1;'
$ curl -X PUT 'http://127.0.0.1:4000/api/board' --data-binary '{"row": 0, "column": 2}' -H 'Cookie: PHPSESSID=1;'
Expected responses code
200 - Success
: In this case the response body will be The Game State (already with the human and the bot move).422 - Unprocessable Entity
: When there are missing parameters or invalid parameters. In this case the response body will be The Error Response Layout.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.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.
Delete the current game. No error will be throw if there is no game to be deleted. You can consume this endpoint even if no game exists. After this, you will going to need to start a new game if you want to play again.
Curl example
$ curl -X DELETE 'http://127.0.0.1:4000/api/board'
Expected responses code
204 - No Content
: It means that the game was deleted, therefor you need to start a new game if you want to play again.