{"id":21029491,"url":"https://github.com/lostsh/morpion","last_synced_at":"2025-09-14T23:42:37.578Z","repository":{"id":138697688,"uuid":"314852914","full_name":"lostsh/morpion","owner":"lostsh","description":"Simple PHP TIC-TAC-TOE game","archived":false,"fork":false,"pushed_at":"2022-03-21T13:15:19.000Z","size":51,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-09-14T11:52:53.766Z","etag":null,"topics":["care","game","grid","heroku","heroku-app","heroku-deployment","morpion","online-game","php","php7","player"],"latest_commit_sha":null,"homepage":"https://more-pion.herokuapp.com/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lostsh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2020-11-21T16:20:33.000Z","updated_at":"2024-01-23T14:58:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"e9897dd9-43d2-40e4-837f-76e3301f1a1f","html_url":"https://github.com/lostsh/morpion","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/lostsh/morpion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lostsh%2Fmorpion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lostsh%2Fmorpion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lostsh%2Fmorpion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lostsh%2Fmorpion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lostsh","download_url":"https://codeload.github.com/lostsh/morpion/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lostsh%2Fmorpion/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275184517,"owners_count":25419911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"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":["care","game","grid","heroku","heroku-app","heroku-deployment","morpion","online-game","php","php7","player"],"created_at":"2024-11-19T12:12:53.080Z","updated_at":"2025-09-14T23:42:37.540Z","avatar_url":"https://github.com/lostsh.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Morpion\nceci est une version très minimaliste du jeu du morpion (TIC-TAC-TOE), basée sur l'utilisation des `sessons` en PHP.\n\nIf you want to play it, it is available on [this site](https://more-pion.herokuapp.com/). You just have to click \"play now\".\n\nThe project repository site is available at [this address](https://lostsh.github.io/morpion/), and the repository code is [here on github](https://github.com/lostsh/morpion).\n\n![Box just for fun](box.jpg)\n\n## operating mode\n\nThe principle could not be simpler:\n\nLet's build the page first, and we'll take care of making it work with the sessions in a second step.\n\n1. With php we display an html table, in each cell we put a `\u003ca\u003e \u003c/a\u003e` tag with as a link the number of the row on which the cell is located, and the number of the column (for pass them using a GET request)\n\n```html\n\u003ctable\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\u003ca href=\"?col=0\u0026lig=0\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=1\u0026lig=0\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=2\u0026lig=0\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\u003ca href=\"?col=0\u0026lig=1\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=1\u0026lig=1\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=2\u0026lig=1\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\u003ca href=\"?col=0\u0026lig=2\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=1\u0026lig=2\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=2\u0026lig=2\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n```\n\n2. Once we have a nice grid we will add an `if` without putting any conditions there we can set it to` true` we will take care of the condition when we add the sessions. The objective is to obtain a grid of this type:\n\n```html\n\u003ctable\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003eX\u003c/td\u003e\n            \u003ctd\u003eX\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=2\u0026lig=0\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003eO\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=1\u0026lig=1\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=2\u0026lig=1\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003eO\u003c/td\u003e\n            \u003ctd\u003e\u003ca href=\"?col=1\u0026lig=2\u0026player=1\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\n            \u003ctd\u003eO\u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n```\nTo build something like this:\n```php\necho(\"\u003ctable\u003e\u003ctbody\u003e\");\nfor($i=0;$i\u003c3;$i++){\n    echo(\"\u003ctr\u003e\");\n    for($j=0;$j\u003c3;$j++){\n        if(true){\n\n            echo(\"\u003ctd\u003e\u003ca href=\\\"?col=\" .$j. \"\u0026lig=\" .$i. \"\\\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\");\n\n        }else{ //we will never go to the else, but it's ready for later\n            if(true){\n                echo(\"\u003ctd\u003eX\u003c/td\u003e\");\n            }else{\n                echo(\"\u003ctd\u003eO\u003c/td\u003e\");\n            }\n        }\n    }\n    echo(\"\u003c/tr\u003e\");\n}\necho(\"\u003c/tbody\u003e\u003c/table\u003e\");\n```\n\nNow we can take care of the sessions to really make the noughts and crosses work, to simplify the task we are not going to worry about player 1 / player 2 we will do that later.\n\nTo store the state of the game we are going to use an array of 3 boxes by 3 boxes (nobody expected it eh?). And we're just going to ask our session to store our table, and give it back to us when we reload the page.\n\nTo do this, we can do a function which aims to initialize a 2D table filled with 0.\n```\n[0][0][0]\n[0][0][0]\n[0][0][0]\n```\nThe function `intiTab()` return a 2D array.\n```php\nfunction initTab(){\n    $tab = array();\n    for($i=0;$i\u003c3;$i++){\n        for($j=0;$j\u003c3;$j++){\n            $tab[$i][$j] = 0;\n        }\n    }\n    return $tab;\n}\n```\nSo let's go to the grid itself, we will be able to put a condition in the `if` earlier.\n```php\necho(\"\u003ctable\u003e\u003ctbody\u003e\");\nfor($i=0;$i\u003c3;$i++){\n    echo(\"\u003ctr\u003e\");\n    for($j=0;$j\u003c3;$j++){\n        if($gameStatus[$i][$j] == 0){\n            echo(\"\u003ctd\u003e\u003ca href=\\\"?col=\".$j.\"\u0026lig=\".$i.\"\\\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\");\n        }else{\n            if($gameStatus[$i][$j] == 1){\n                echo(\"\u003ctd\u003eX\u003c/td\u003e\");\n            }else{\n                echo(\"\u003ctd\u003eO\u003c/td\u003e\");\n            }\n        }\n    }\n    echo(\"\u003c/tr\u003e\");\n}\necho(\"\u003c/tbody\u003e\u003c/table\u003e\");\n```\n\nNow, we must put this magnificent game board in our session, if it exists we update it, otherwise we create it, we could see something like this:\n```php\n$gameStatus = initTab();\nif(isset($_SESSION['gameStatus'])){\n    $gameStatus = $_SESSION['gameStatus'];\n}else{\n    $_SESSION['gameStatus'] = $gameStatus;\n}\n```\n\nSo now, when we use the GET parameters that we put when we click on a box. To do so, we will simply say that if GET exists, then update the games teablau, and update the game board that we put in the session!\n\n```php\nif(\n    isset($_GET['col']) \u0026\u0026 \n    isset($_GET['lig']) \u0026\u0026 \n    isset($_GET['player']) \n    )\n{\n    $gameStatus[$_GET['lig']][$_GET['col']] = 'X';\n    $_SESSION['gameStatus'] = $gameStatus;\n}\n```\n\nNow it works! well done ! now we will be able to play each turn, we will simply add a player attribute in our session which will be worth either 1 or 2\n\nWe create it like this:\n\n```php\nif(isset($_SESSION['player'])){\n\n    //this allows to reverse the current player compared to the previous player\n    if($_SESSION['player'] == 1){\n        $_SESSION['player'] = 2;\n    }else{\n        $_SESSION['player'] = 1;\n    }\n\n\n}else{\n    $_SESSION['player'] = random(1,2);\n}\n```\n\nyou have to update the array so that it is given as a parameter in the get like this:\n\n```php\necho(\"\u003ctable\u003e\u003ctbody\u003e\");\nfor($i=0;$i\u003c3;$i++){\n    echo(\"\u003ctr\u003e\");\n    for($j=0;$j\u003c3;$j++){\n        if($gameStatus[$i][$j] == 0){\n            echo(\"\u003ctd\u003e\u003ca href=\\\"?col=\".$j.\"\u0026lig=\".$i.\"\u0026player=\".$_SESSION['player'].\"\\\"\u003ejouer\u003c/a\u003e\u003c/td\u003e\");\n        }else{\n            if($gameStatus[$i][$j] == 1){\n                echo(\"\u003ctd\u003eX\u003c/td\u003e\");\n            }else{\n                echo(\"\u003ctd\u003eO\u003c/td\u003e\");\n            }\n        }\n    }\n    echo(\"\u003c/tr\u003e\");\n}\necho(\"\u003c/tbody\u003e\u003c/table\u003e\");\n```\n\n**Well now the game seems to be working more or less well, let's move on to victory conditions!**\n\nGood the most method is also the ugliest, but tempis I will come back to it later! For the moment it works.\n\nA function which returns 0 if the whole row does not have the same value, and if in the whole row we have the same value then we return this value. And even functoin for a colone.\n```php\n/**\n * Return the numer \n * if there is the same numer on all the $line of the $tab\n * else retrurn 0\n */\nfunction isLineSameValue($line, $tab){\n    $value = $tab[$line][0];\n    for($i=0;$i\u003ccount($tab[$line])-1;$i++){\n        if($tab[$line][$i] != $tab[$line][$i+1]){\n            $value = 0;\n        }\n    }\n    return $value;\n}\n/**\n * Return the numer \n * if there is the same numer on all the $col of the $tab\n * else retrurn 0\n */\nfunction isColSameValue($col, $tab){\n    $value = $tab[0][$col];\n    $colSize = (count($tab, COUNT_RECURSIVE) - count($tab[0])*count($tab[0]));\n    for($i=0;$i\u003c$colSize-1;$i++){\n        if($tab[$i][$col] != $tab[$i+1][$col]){\n            $value = 0;\n        }\n    }\n    return $value;\n}\n```\n\nNow a function that looks at the diagonal from top left to bottom right. Then a function that looks from top right to bottom left.\n```php\n/**\n * Return the numer duplicated on all a diagonale\n * if there is no same values, then it return 0\n */\nfunction isDiagonalSameValue($tab){\n    $size = 3;\n    $diagOneVal = $tab[0][0];\n    $diagTwoVal = $tab[0][$size-1];\n    for($i=0;$i\u003c$size-1;$i++){\n        if($tab[$i][$i] != $tab[$i+1][$i+1]){\n            $diagOneVal = 0;\n        }\n        if($tab[$i][$size-1-$i] != $tab[$i+1][$size-2-$i]){\n            $diagTwoVal = 0;\n        }\n    }\n    return ($diagOneVal!=0 || $diagTwoVal!=0)?($diagOneVal!=0?$diagOneVal:$diagTwoVal):0;\n}\n```\n\nIt only remains to gather this in a function which tells us if we have won or not, and if so which player has won.\n```php\n/**\n * Return 0 if no winer\n * Else return the numer of the winer {1 or 2}\n */\nfunction whoWin($matrix){\n    $winer = 0;\n    $i=0;\n    while($i\u003c3 and $winer==0){\n\n        if(isLineSameValue($i, $matrix) != 0){\n            $winer = isLineSameValue($i, $matrix);\n        }\n        else if(isColSameValue($i, $matrix) != 0)\n        {\n            $winer = isColSameValue($i, $matrix);\n        }\n        else if(isDiagonalSameValue($matrix))\n        {\n            $winer = isDiagonalSameValue($matrix);\n        }\n        $i++;\n\n    }\n    return $winer;\n}\n```\nWe can see that a tie takes place when no one has won and the grid is full, so here is a function to check whether or not the grid is full.\n```php\n/**\n * Return true if the matrix is full\n */\nfunction isMatrixFull($matrix){\n    $isFull = true;\n    $size = count($matrix);\n    $i = 0;\n    while($i\u003c$size \u0026\u0026 $isFull){\n        $j = 0;\n        while($j\u003c$size \u0026\u0026 $isFull){\n            if($matrix[$i][$j] == 0){\n                $isFull = false;\n            }\n            $j++;\n        }\n        $i++;\n    }\n    return $isFull;\n}\n```\n\n**Voila, you have the main functional elements, you just have to assemble them, and add two or three things to make it work and you're done!**\n\n## iframe\nYou may have noticed, the site on which the tic-tac-toe is located is a site hosted on `github pages`, but we cannot run php code! The obvious solution: it's an `iframe`. However I ran into some inconvenience of the `httpsOnly` type, or even `samesite`, anyway I will tell you about this in more detail.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flostsh%2Fmorpion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flostsh%2Fmorpion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flostsh%2Fmorpion/lists"}