{"id":19961378,"url":"https://github.com/skylar-lorena/tic-tac-toe-ruby","last_synced_at":"2026-06-08T06:35:30.783Z","repository":{"id":70138365,"uuid":"527108886","full_name":"Skylar-Lorena/Tic-Tac-Toe-Ruby","owner":"Skylar-Lorena","description":"Build a CLI Tic Tac Toe game in Ruby!","archived":false,"fork":false,"pushed_at":"2022-08-21T04:55:53.000Z","size":10,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-01T16:47:38.497Z","etag":null,"topics":["oop","oop-in-ruby","ruby","tic-tac-toe","tic-tac-toe-game","tic-tac-toe-ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Skylar-Lorena.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":"2022-08-21T04:54:57.000Z","updated_at":"2022-08-21T08:11:07.000Z","dependencies_parsed_at":"2023-03-04T10:00:28.033Z","dependency_job_id":null,"html_url":"https://github.com/Skylar-Lorena/Tic-Tac-Toe-Ruby","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Skylar-Lorena/Tic-Tac-Toe-Ruby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skylar-Lorena%2FTic-Tac-Toe-Ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skylar-Lorena%2FTic-Tac-Toe-Ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skylar-Lorena%2FTic-Tac-Toe-Ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skylar-Lorena%2FTic-Tac-Toe-Ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Skylar-Lorena","download_url":"https://codeload.github.com/Skylar-Lorena/Tic-Tac-Toe-Ruby/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Skylar-Lorena%2FTic-Tac-Toe-Ruby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34051771,"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-08T02:00:07.615Z","response_time":111,"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":["oop","oop-in-ruby","ruby","tic-tac-toe","tic-tac-toe-game","tic-tac-toe-ruby"],"created_at":"2024-11-13T02:07:22.562Z","updated_at":"2026-06-08T06:35:30.778Z","avatar_url":"https://github.com/Skylar-Lorena.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OO Tic Tac Toe\n\n## Learning Goals\n\n- Use Object Oriented Programming to build a CLI Tic Tac Toe game\n\n## Overview\n\nYou're going to be building a 2 player CLI version of Tic Tac Toe by building a\n`TicTacToe` object. The game play will be very similar to other versions of\nTicTacToe.\n\n## Instructions\n\nIn order to get everything working you should refer to these instructions as you\ngo _and_ pay close attention to the test output.\n\n**Run `bundle` within this lab's directory before getting started.**\n\n### Project Structure\n\n```txt\n├── Gemfile\n├── Gemfile.lock\n├── README.md\n├── bin\n│   └── tictactoe\n├── lib\n│   └── tic_tac_toe.rb\n└── spec\n    ├── 01_tic_tac_toe_spec.rb\n    ├── 02_play_spec.rb\n    ├── 03_cli_spec.rb\n    └── spec_helper.rb\n```\n\n#### Gemfile\n\nThese files set up some tools and gems for our project and can mostly be\nignored. Make sure to run `bundle` before starting this project so that you have\nall the required gems.\n\n#### `bin/tictactoe`\n\nThis is our main executable and will be how we initialize and start our game.\n\n#### `lib/tic_tac_toe.rb`\n\nOur main `TicTacToe` class will be defined here with all the data and logic\nrequired to play a game of tic tac toe via instances of `TicTacToe`.\n\n#### `spec`\n\nThere are three test files that should be completed in order.\n`01_tic_tac_toe_spec.rb` tests our helper methods within `TicTacToe`.\n`02_play_spec.rb` tests the main `#play` method. `03_cli_spec.rb` tests the CLI.\n\n### Your Object-Oriented Tic Tac Toe\n\nWe're going to be building a very well encapsulated object for Tic Tac Toe where\neach instance method will represent a discrete, single responsibility or\nfunctionality of a Tic Tac Toe game.\n\nWe'll be following the Tic Tac Toe conventions of representing the board as an\narray with 9 elements where `\" \"` represents an empty cell in the board.\n\nWe'll be getting user input via `gets` and a player will choose a position by\nentering 1-9. Our program will then fill the appropriate position on the board\nwith the player's token.\n\nWe will keep track of which player's turn it is and how many turns have been\nplayed. We will check to see, at every turn, if there is a winner. If there is a\nwinner, we'll congratulate them. If there is a tie, we will inform our players.\n\n## The Logic: `lib/tictactoe.rb`\n\n### `TicTacToe` class\n\nOpen up `lib/tic_tac_toe.rb`. You'll be defining the main game class,\n`TicTacToe` in `lib/tic_tac_toe.rb`. Until the `TicTacToe` class is defined,\neverything will break.\n\nEvery method you build will be encapsulated by this class.\n\n### `#initialize` and `@board`\n\nThe first test in `01_tic_tac_toe_spec.rb` will ensure the requirement that when\na new game of Tic Tac Toe is started — that is, when a new instance of\n`TicTacToe` is initialized — the instance of the game must set the starting\nstate of the board, an array with 9 empty strings `\" \"`, within an instance\nvariable named `@board`.\n\nIn other words, your `#initialize` method should set a `@board` variable equal\nto a new, empty array that represents the game board.\n\n#### `WIN_COMBINATIONS`\n\nDefine a `WIN_COMBINATIONS` constant within the `TicTacToe` class, and set it\nequal to a nested array filled with the index values for the eight winning\ncombinations possible in Tic Tac Toe.\n\n**Top-Tip:** When you see this line, `TicTacToe::WIN_COMBINATIONS`, in the test\nsuite, that means the test suite is accessing the constant `WIN_COMBINATIONS`\nthat was declared inside the `TicTacToe` class.\n\n```ruby\n# within the body of TicTacToe\n\nWIN_COMBINATIONS = [\n  [0,1,2], # Top row\n  [3,4,5]  # Middle row\n  # et cetera, creating a nested array for each win combination\n]\n\n# the rest of the TicTacToe class definition\n```\n\n### Helper Methods\n\nThe next bunch of methods we will be describing are helper methods - methods\nthat will be called by other methods in your code. This keeps our code [DRY] and\nwell encapsulated \u0026mdash; each method has a single responsibility \u0026mdash; which\nmakes the code easier to maintain and expand.\n\n[dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\n\n#### `#display_board`\n\nDefine a method that prints the current board representation based on the\n`@board` instance variable.\n\n#### `#input_to_index`\n\nDefine a method into which we can pass user input (in the form of a string,\ne.g., `\"1\"`, `\"5\"`, etc.) and have it return to us the corresponding index of\nthe `@board` array. Remember that, from the player's point of view, the board\ncontains spaces 1-9. But the indices in an array start their count at 0. If the\nuser inputs `5`, your method must correctly translate that from the player's\nperspective to the array's perspective \u0026mdash; accounting for the fact that\n`@board[5]` is _not_ where the user intended to place their token.\n\n#### `#move`\n\nYour `#move` method must take in two arguments: the index in the `@board` array\nthat the player chooses and the player's token (either `\"X\"` or `\"O\"`). The\nsecond argument, the player's token, should default to `\"X\"`.\n\n#### `#position_taken?`\n\nThe `#position_taken?` method will be responsible for evaluating the user's\ndesired move against the Tic Tac Toe board and checking to see whether or not\nthat position is already occupied. Note that this method will be running _after_\n`#input_to_index`, so it will be checking index values. When it is passed the\nindex value for a prospective move, `#position_taken?` will check to see if that\nposition on the `@board` is vacant or if it contains an `\"X\"` or an `\"O\"`. If\nthe position is free, the method should return `false` (i.e., \"the position is\nnot taken\"); otherwise, it will return `true`.\n\n#### `#valid_move?`\n\nBuild a method `valid_move?` that accepts a position to check and returns `true`\nif the move is valid and `false` or `nil` if not. A valid move means that the\nsubmitted position is:\n\n1. Present on the game board.\n2. Not already filled with a token.\n\n#### `#turn_count`\n\nThis method returns the number of turns that have been played based on the\n`@board` variable.\n\n#### `#current_player`\n\nThe `#current_player` method should use the `#turn_count` method to determine if\nit is `\"X\"`'s or `\"O\"`'s turn.\n\n#### `#turn`\n\nBuild a method `#turn` to encapsulate the logic of a single complete turn\ncomposed of the following routine:\n\n1. Ask the user for their move by specifying a position between 1-9.\n2. Receive the user's input.\n3. Translate that input into an index value.\n4. If the move is valid, make the move and display the board.\n5. If the move is invalid, ask for a new move until a valid move is received.\n\n**Note**: If the user enters an invalid move, we need to repeat the entire\nsequence of events listed above: asking for input, translating it into an index,\nchecking whether the move is valid and, if it is, making the move.\nTheoretically, we could code all that into our `else` but that would definitely\nviolate DRY principles. And what if the user enters an invalid move a second or\nthird or tenth time? What we really need to do is _restart_ the `turn` method\neach time an invalid move is entered. Luckily, Ruby (and many other programming\nlanguages) allows us to call a method from inside itself. This process of\ncalling a method from inside itself is commonly used in [recursion].\n\n[recursion]: https://en.wikipedia.org/wiki/Recursion_(computer_science)\n\nAll these procedures will be wrapped into our `#turn` method, but the majority\nof the logic for these procedures will be defined and encapsulated in our helper\nmethods. You will need to call those methods from inside the `turn` method to\nget the tests passing. Pay close attention to the sequence of events and when\nand where the helper methods should be called. If there are redundancies in your\ncode the tests may not pass.\n\n**Hint**: don't forget to pay attention to which argument(s) each of your helper\nmethods requires.\n\nYou can imagine the pseudocode for the `#turn` method:\n\n```txt\nask for input\nget input\ntranslate input into index\nif index is valid\n  make the move for index\n  show the board\nelse\n  restart turn\nend\n```\n\n#### `#won?`\n\nYour `#won?` method should return `false` or `nil` if there is no win\ncombination present in the board and return an array containing the winning\ncombination indexes if there is a win. Use your `WIN_COMBINATIONS` constant in\nthis method.\n\n#### `#full?`\n\nThe `#full?` method should return `true` if every element in the board contains\neither an \"X\" or an \"O\".\n\n#### `#draw?`\n\nBuild a method `#draw?` that returns `true` if the board is full and has not\nbeen won and `false` otherwise.\n\n#### `#over?`\n\nBuild a method `#over?` that returns `true` if the board has been won or is full\n(i.e., is a draw).\n\n#### `#winner`\n\nGiven a winning `@board`, the `#winner` method should return the token, `\"X\"` or\n`\"O\"`, that has won the game.\n\n### Putting it all together: the `#play` method\n\n#### `#play`\n\nThe play method is the main method of the Tic Tac Toe application and is\nresponsible for the game loop. A Tic Tac Toe game must allow players to take\nturns, checking if the game is over after every turn. At the conclusion of the\ngame, whether because it was won or ended in a draw, the game should report to\nthe user the outcome of the game. You can imagine the pseudocode:\n\n```txt\nuntil the game is over\n  take turns\nend\n\nif the game was won\n  congratulate the winner\nelse if the game was a draw\n  tell the players it ended in a draw\nend\n```\n\nHere again, much of the functionality you need is built into our helper methods\n\u0026mdash; don't forget to use them!\n\nRun the tests for the `#play` method by typing `rspec spec/02_play_spec.rb` in\nyour terminal.\n\n## The CLI: `bin/tictactoe`\n\nYour `bin/tictactoe` CLI should:\n\n1. Instantiate an instance of `TicTacToe`\n2. Start the game by calling `#play` on that instance.\n\nRun the tests by typing `rspec spec/03_cli_spec.rb` in your terminal.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylar-lorena%2Ftic-tac-toe-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskylar-lorena%2Ftic-tac-toe-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylar-lorena%2Ftic-tac-toe-ruby/lists"}