{"id":20163755,"url":"https://github.com/emik03/minimax-tictactoe","last_synced_at":"2025-06-20T11:10:29.525Z","repository":{"id":100294975,"uuid":"418883274","full_name":"Emik03/minimax-tictactoe","owner":"Emik03","description":"Playable tic-tac-toe engine using α-β pruning.","archived":false,"fork":false,"pushed_at":"2021-12-08T10:34:46.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-14T17:51:02.244Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Emik03.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2021-10-19T10:53:26.000Z","updated_at":"2021-12-08T10:34:49.000Z","dependencies_parsed_at":"2023-04-24T21:09:02.811Z","dependency_job_id":null,"html_url":"https://github.com/Emik03/minimax-tictactoe","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Emik03/minimax-tictactoe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Emik03%2Fminimax-tictactoe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Emik03%2Fminimax-tictactoe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Emik03%2Fminimax-tictactoe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Emik03%2Fminimax-tictactoe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Emik03","download_url":"https://codeload.github.com/Emik03/minimax-tictactoe/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Emik03%2Fminimax-tictactoe/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260933580,"owners_count":23084959,"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","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":[],"created_at":"2024-11-14T00:31:37.880Z","updated_at":"2025-06-20T11:10:24.514Z","avatar_url":"https://github.com/Emik03.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# minimax-tictactoe\n\nPlayable tic-tac-toe engine using α-β pruning.\n\n---\n\n### Installation\n\nIf you are on windows, download the files [here](https://github.com/Emik03/minimax-tictactoe/releases/latest).\n\nFor mac/linux users, you need to compile this yourself.\n\n---\n\n### Contribution\n\nAs with most [GitHub](https://github.com/) repositories, you can contribute by:\n* [Creating an issue](https://github.com/Emik03/minimax-tictactoe/issues) to either address bugs, feature suggestions, or other changes.\n* [Creating or reviewing pull requests](https://github.com/Emik03/minimax-tictactoe/pulls) are also welcome.\n\n---\n\n### Building\n\n1. [Install Rust](https://www.rust-lang.org/tools/install) if you don't already have it.\n\n2. Download and extract the source code, or clone the repository:\n\n```bash\ngit clone https://github.com/Emik03/minimax-tictactoe.git\n```\n\n3. In the root directory, run the following from a command-line:\n\n```bash\ncargo build --release\n```\n\n4. Find the binary file in `\\target\\release`.\n\n---\n\n### License\n\nThis project falls under the [GPLv3 License](https://github.com/Emik03/minimax-tictactoe/blob/main/LICENSE.md), which in-short means that you copy, modify, and redistribute under private and commerical use, but the author cannot be held liable, the license must stay intact as is, a disclosure of the original source has to be made, and you must state changes to this repository.\n\n---\n\n### Explanation\n\nI was mainly driven by [DDD (Domain-Driven Design)](https://en.wikipedia.org/wiki/Domain-driven_design) to make a ton of abstractions and encapsulations. Therefore, a lot of the code is hidden away at other files so you don't have to worry about how they work.\n\n[The entry point of the application](https://github.com/Emik03/minimax-tictactoe/blob/master/src/main.rs#L16) will print to the console and ask the user for a query. The [`of_input`](https://github.com/Emik03/minimax-tictactoe/blob/master/src/main.rs#L113) method in particular is useful, as it allows me to create a closure that does a series of tests on the provided `String`.\n\nIf this method returns `None` then we know something went wrong and we need to try again, if `Some(x)` is returned then we can use that as the actual return and the program continues.\n\nAfter the user inputs everything, [all of the parameters get put into a wrapper method](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L21)), and it is [the inner method call](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L25) that starts the real core of the application.\n\nMinimax is a brute-force algorithm that determines the best move by recursively playing each move to see how they play out. The idea is that we have a maximizing player, which tries to get the maximum number because it implies that they win, and a minimizing player, which tries to get the minimum number because it implies that they win. Think of it like tug-of-war where both sides are trying to pull the rope through.\n\nWe write an [evaluator method](https://github.com/Emik03/minimax-tictactoe/blob/master/src/board.rs#L102) that looks at the position and returns the number indicating who is winning. 0 means a dead draw, positive means the maximizing player is winning, and negative means the minimizing player is winning. To make it more effective, we also subtract the number of moves played, and this is to encourage moves that win quickly.\n\nThe first thing we do is check [whether the game has ended](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L59), if the game is over then we should prematurely return the result of the game.\n\nIf the game goes on, we then [check the depth](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L65) to see if it is now 0. The depth calculates how deep the algorithm goes and therefore how fast it will perform. A higher depth *usually* means better moves are played.\n\nIf we reach here, we will [start creating a vector for each evaluation](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L72) which is needed later.\n\nWe then create a [loop of every theoretical possible move](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L75). Some of the moves are illegal though, so we have a [move legality checker](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L76) to return a new board state. We need to clone the board so that the original doesn't get mutated.\n\nWe then [call the inner minimax method](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L78) again which makes it play a move deeper. We need to invert the `is_o` parameter so that the other player plays, and we decrement the `depth` value by 1 since it goes 1 method call deeper.\n\nAfter that inner method call ends, we [add the result to the vector](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L85) mentioned prior.\n\nFinally, we [return the best move](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L91) by getting the maximum evaluation if the maximizing player is playing, or the minimum evaluation if the minimizing player is playing.\n\nWhile it takes more memory, we can make it more efficient by implementing α-β (alpha-beta) pruning to make the algorithm faster. The idea is that [each game stores an α value and a β value](https://github.com/Emik03/minimax-tictactoe/blob/master/src/board.rs#L13). α starts out as the most negative number, since it accounts for the worst case scenario for the maximizing player, and β starts out as the most positive number, since it accounts for the worst case scenario for the minimizing player.\n\nWe then [check if the result of the current game exceeds α or β](https://github.com/Emik03/minimax-tictactoe/blob/master/src/evaluation.rs#L79). In the event that it does, it means that we don't need to search this branch and can therefore prune it.\n\n---\n\n### Credit\n\nThanks to the [`ptree`](https://docs.rs/ptree/0.3.2/ptree/) crate for the pretty tree generator.\n\nBorrowed code from myself in [1D Chess](https://github.com/Emik03/EmikModules/tree/main/Assets/Modules/1D%20Chess).\n\nOther code borrowed from the following sources:\n- [How do I subtract one character from another in rust?](https://stackoverflow.com/questions/54583399/how-do-i-subtract-one-character-from-another-in-rust)\n- [Convert a string to int](https://stackoverflow.com/questions/27043268/convert-a-string-to-int)\n- [How to get elements from a vector with a computed index?](https://www.reddit.com/r/rust/comments/385em5/how_to_get_elements_from_a_vector_with_a_computed/)\n- [std::option](https://doc.rust-lang.org/std/option/)\n- [Proper way to return a new string in rust](https://stackoverflow.com/questions/43079077/proper-way-to-return-a-new-string-in-rust)\n- [How do I store a closure in a struct in rust?](https://stackoverflow.com/questions/27831944/how-do-i-store-a-closure-in-a-struct-in-rust)\n- [How to match against multiple characters in a rust match expression?](https://stackoverflow.com/questions/60102442/how-to-match-against-multiple-characters-in-a-rust-match-expression)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femik03%2Fminimax-tictactoe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femik03%2Fminimax-tictactoe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femik03%2Fminimax-tictactoe/lists"}