An unbeatable game of tic tac toe.
Branch: develop
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib Bump version and add release notes. Jan 24, 2014
spec Bump version and add release notes. Jan 24, 2014
.blam Rearrange spec directory. Dec 20, 2013
.gitignore Remove gem lock file from repository. Jan 10, 2014
.rspec To begin I'll set up a basic sinatra app to serve as the base for the… Nov 21, 2013
.rubocop.yml Ignore local vendor from rubocop check. Jan 10, 2014
.ruby-gemset To begin I'll set up a basic sinatra app to serve as the base for the… Nov 21, 2013
.ruby-version I cleaned up the board styles and creation and improved the responsiv… Dec 5, 2013
.travis.yml
Gemfile Clean lines in Gemfile. Jan 10, 2014
Gemfile.lock Update gems. Jan 10, 2014
Guardfile
LICENSE.md Add GPLv3 License. Mar 28, 2015
README.md Add GPLv3 License. Mar 28, 2015
Rakefile Add js tests to main rake command. Jan 8, 2014
config.ru

README.md

#Tic Tac Toe Documentation

Build Status Coverage Status Code Climate

A simple game. Or is it!? Try your skill at http://perfecttictactoe.herokuapp.com/

Along with the game there is a "Tic Tac Toe" API, simply post a JSON request indicating the current board state and the "turn" piece. The response will be an updated board state.

API End Point

POST /api/v2/play

Example Request

{
   "player_piece":"o",
   "opponent_piece":"x",
   "board":[
      {
         "id":"top-left",
         "value":""
      },
      {
         "id":"top-center",
         "value":""
      },
      {
         "id":"top-right",
         "value":"x"
      },
      {
         "id":"middle-left",
         "value":""
      },
      {
         "id":"middle-center",
         "value":"o"
      },
      {
         "id":"middle-right",
         "value":""
      },
      {
         "id":"bottom-left",
         "value":"x"
      },
      {
         "id":"bottom-center",
         "value":"o"
      },
      {
         "id":"bottom-right",
         "value":"x"
      }
   ]
}

Example Response

Note the addition of "o" in the top-center and that the player and opponent has switched. Also any spaces in a "winning" line are indicated as such with the attribute "winning_space": true.

{
   "status":"success",
   "data":{
      "player_piece":"x",
      "opponent_piece":"o",
      "board":[
         {
            "id":"top-left",
            "value":""
         },
         {
            "id":"top-center",
            "value":"o"
         },
         {
            "id":"top-right",
            "value":"x",
            "winning_space": true
         },
         {
            "id":"middle-left",
            "value":""
         },
         {
            "id":"middle-center",
            "value":"o",
            "winning_space": true
         },
         {
            "id":"middle-right",
            "value":""
         },
         {
            "id":"bottom-left",
            "value":"x"
         },
         {
            "id":"bottom-center",
            "value":"o",
            "winning_space": true
         },
         {
            "id":"bottom-right",
            "value":"x"
         }
      ]
   }
}

###Development This game was built on top of my sinatra-boilerplate app. Specifics to that boilerplate can be found at its repository.

###Notes on Testing Tests are best executed using the rake tasks:

  • rake test
  • rake system
  • rake js (Run javascript unit tests via jasmine on phantomjs.)
  • rake build_full (For all the tests.)

This is due to conditional configuration based on test type to improve the execution speed. You may run tests directly with the rspec command but this will include all dependencies.

To start a development server and guard simply run:

bundle exec guard

To start a jasmine server to view the results of javascript tests in the browser run:

bundle exec rake jasmine

###Room for Improvement

  • The board class is a little heavy, there may be a way to pull this apart.
  • There may be a way to further speed up the algorithm

##License

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

License located in LICENSE.md

##Change Log

###2.1.1 - March 28, 2015

  • Add GPL v3 License

###2.1.0 - January 23, 2014

  • Split Board into a Board and GameState object for better separation of responsibilities.
  • Improve turn hand off, isolating knowledge of pieces to the GameState.
  • Cleaned up with win check algorithm to leverage a more universal function.
  • Added mechanism to identify which "lines" on a board can never be winning because they contain at least 1 of both players' pieces. These are cached to prevent future checks of that line and improve speed.

###2.0.0 - January 10, 2014

  • Ignore expensive win check if there are not enough pieces for a win to be possible (while following the rules). For example, the soonest a player could win on a 3x3 board is when marking the 5th square.
  • Refactor board state object to improve copying performance and holding the state of the game as moves are made, this prevents expensive win checking of the whole board any time that method is called.
  • Refactor minimax algorithm to employ alpha-beta pruning, which improved performance significantly on the first computer move.
  • Update to version 2 of the api which reports winning spaces, allowing all the win check logic to be stripped out of the client.
  • Refactor client javascript code to simply read/write board and manage turn/messages.
  • Spruced up the styles a little.
  • Various test/code cleaning and performance optimizations.