Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: coxmediagroup/Tic-Tac-Toe
base: master
...
head fork: nrb/Tic-Tac-Toe
compare: master
Checking mergeability… Don’t worry, you can still create the pull request.
  • 17 commits
  • 14 files changed
  • 0 commit comments
  • 1 contributor
Commits on Mar 11, 2011
Nolan Brubaker Updated README to remove project instructions and provide project ove…
…rview.
09fa63f
@nrb nrb Added Django base project files. 3998977
Commits on Mar 13, 2011
@nrb nrb Moved README up for github. bb73633
@nrb nrb Ignored pycs, created skeleton tictactoe Django app. 4f4c197
@nrb nrb Made apps package and added the tic tact toe app to installed apps. c893859
@nrb nrb Added templates path. b1dd51f
@nrb nrb Added default view/template, with matching URLconf
Default template is really a dummy for right now,
and the view just creates an empty context to
pass in.
4c5a9d9
@nrb nrb Ignored swp files, moved gitignore to root dir. ea46243
@nrb nrb Added initial models file.
Currently, the models file is NOT connected
to a database, since there is no need for
storage quite yet.
f4c4b0d
@nrb nrb Added database settings so django's tests will work. 47a78f0
@nrb nrb Added initial tests for the game. 2047844
Commits on Mar 19, 2011
@nrb nrb Added a field to show who's turn it is, with tests 2c21232
@nrb nrb Added check to enforce alternating turns.
Players shouldn't be able to make more
than one move at a time, so I added
and IllegalMove exception to make sure
this doesn't happen.
448e341
@nrb nrb Added test for overwriting a cell. e0419eb
@nrb nrb Added test mode, updated tests to use it.
In order to help test win conditions more
easily, I added a test flag that will
block certain exceptions from being
raised.

Some tests rely on the exceptions, and
they disable test mode.
c1e0b1b
@nrb nrb Added horizontal win condition test. 6f5ba89
@nrb nrb Added test for vertical wins, fixed bug in pivot.
Creating the pivot table with the list multi-
plication method actually resulted in one
list with 3 references to it, rather than 3
distinct lists. When marking a cell in
one list (row), the same cell would be
marked in all lists.

Corrected this by making 3 separate lists
before doing the pivot.
679df22
View
2  .gitignore
@@ -0,0 +1,2 @@
+*.pyc
+*.swp
View
5 README
@@ -1,5 +0,0 @@
-Intructions:
-1. Fork this repo on github.
-2. Create an app that can interactively play the game of Tic Tac Toe against another player and never lose.
-3. Commit early and often, with good messages.
-4. Push your code back to github and send me a pull request.
View
5 README.rst
@@ -0,0 +1,5 @@
+===========
+Tic-Tac-Toe
+===========
+
+This application is an interactive Tic-Tac-Toe game that cane play against a human player, and never lose.
View
0  TicTacToe/__init__.py
No changes.
View
0  TicTacToe/apps/__init__.py
No changes.
View
0  TicTacToe/apps/tictactoe/__init__.py
No changes.
View
90 TicTacToe/apps/tictactoe/models.py
@@ -0,0 +1,90 @@
+from django.db import models
+
+class Game(object):
+ '''
+ Captures the state of the game board, so that it may be maintained
+ between requests.
+ '''
+
+ def __init__(self, test=False):
+ # Create a 3 x 3 matrix that we use as the markers.
+ self.matrix = [['-', '-', '-']] * 3
+
+ # The computer will always be x, and always start first.
+ self.players_turn = 'x'
+
+ self.test = test
+
+ def mark(self, row, column, character):
+ '''
+ Tag the cell that the player marked with their character.
+
+ Only 'x' and 'o' are allowed. Also, only currently-blank
+ cells can be marked.
+ '''
+ if character not in ['x', 'o']:
+ raise ValueError, "Character's value should be either x or o."
+
+ if character != self.players_turn and not self.test:
+ raise self.IllegalMove
+
+ # Make sure we're marking only blank cells.
+ if self.matrix[row][column] == '-':
+ self.matrix[row][column] = character
+
+ # Switch player's turn.
+ if self.players_turn == 'x':
+ self.players_turn = 'o'
+ else:
+ self.players_turn = 'x'
+ else:
+
+ return
+
+ def check_win_conditions(self):
+ '''
+ Checks to see which player won.
+
+ We have to check for horizontal, vertical, and diagonal cases.
+
+ Also, it should check for stalemates (that is, the board is full
+ without anyone getting 3 touching). In that case, the player
+ with the most marks wins.
+ '''
+ # Horizontal
+ for row in self.matrix:
+ if ['x'] * 3 == row:
+ return 'x'
+ elif ['o'] * 3 == row:
+ return 'o'
+
+ # Pivot matrix to check columns in a more readable way
+ # To do so, initiate another blank game board.
+ # This one is layed out explicitly; using the multi-
+ # plication method results in 3 references to 1 list.
+ pivoted_matrix = [['-', '-', '-'],
+ ['-', '-', '-'],
+ ['-', '-', '-']]
+ for row in xrange(0, 3):
+ for column in xrange(0, 3):
+ # Invert the column and rows to do the pivot
+ pivoted_matrix[column][row] = self.matrix[row][column]
+
+ # Check the newly pivoted board.
+ for row in pivoted_matrix:
+ if ['x'] * 3 == row:
+ return 'x'
+ elif ['o'] * 3 == row:
+ return 'o'
+
+ # TODO: Diagonals, should be 2.
+ # TODO: Stalemates
+
+ # If no win conditions met, we return nothing and keep going.
+ return None
+
+ def retart(self):
+ pass
+
+ class IllegalMove(Exception):
+ pass
View
66 TicTacToe/apps/tictactoe/tests.py
@@ -0,0 +1,66 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+from TicTacToe.apps.tictactoe.models import Game
+
+
+class GameTest(TestCase):
+ def setUp(self):
+ self.g = Game(test=True)
+
+ def test_matrix_list(self):
+ '''
+ Make sure that the matrix is initialized correctly.
+ '''
+ self.assertEqual([['-', '-', '-']] * 3, self.g.matrix)
+
+ def test_marking(self):
+ '''
+ '''
+ self.g.mark(0,0, 'x')
+ self.g.mark(2,2, 'o')
+
+ self.assertEqual('x', self.g.matrix[0][0])
+ self.assertEqual('o', self.g.matrix[2][2])
+
+ def test_failing_marks(self):
+ self.assertRaises(ValueError, self.g.mark, 0, 0, 'a')
+ self.assertRaises(ValueError, self.g.mark, 2, 2, 'b')
+
+ def test_turn_toggle(self):
+ self.g.mark(0,0,'x')
+
+ self.assertEqual(self.g.players_turn, 'o')
+
+ def test_no_double_turn(self):
+ # Disable testing mode, since it blocks the exception.
+ self.g.test = False
+ self.g.mark(0,0,'x')
+ self.assertRaises(Game.IllegalMove, self.g.mark, 0, 1, 'x')
+
+ def test_no_overwrite_marks(self):
+ '''No cell should be overwritten if it already contains
+ a player mark.'''
+
+ self.g.mark(0, 0, 'x')
+ self.g.mark(0, 0, 'o')
+ self.assertEqual(self.g.matrix[0][0], 'x')
+
+ def test_horizontal_win_conditions(self):
+ for cell in xrange(0,3):
+ self.g.mark(0, cell, 'x')
+
+ self.assertEqual(self.g.check_win_conditions(), 'x')
+
+ def test_vertical_win_conditions(self):
+ for row in xrange(0,3):
+ self.g.mark(row, 1, 'x')
+
+ self.assertEqual(self.g.check_win_conditions(), 'x', self.g.matrix)
+
View
5 TicTacToe/apps/tictactoe/urls.py
@@ -0,0 +1,5 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('TicTacToe.apps.tictactoe.views',
+ url(r'^$', 'game_board', name='game_board')
+)
View
7 TicTacToe/apps/tictactoe/views.py
@@ -0,0 +1,7 @@
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+
+def game_board(request):
+ context = RequestContext(request,{})
+ return render_to_response('tictactoe/game_board.html', context)
+
View
11 TicTacToe/manage.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
View
103 TicTacToe/settings.py
@@ -0,0 +1,103 @@
+# Django settings for TicTacToe project.
+
+import os.path
+
+PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': os.path.join(PROJECT_ROOT, 'dev.db'), # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+USE_L10N = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'qa5v_uz4rdj!4uc^p@8g)_#!yl=s7f%jz!l8(g8gm$twg^o6y!'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+ROOT_URLCONF = 'TicTacToe.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ os.path.join(PROJECT_ROOT, 'templates')
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.messages',
+ # Uncomment the next line to enable the admin:
+ # 'django.contrib.admin',
+ # Uncomment the next line to enable admin documentation:
+ # 'django.contrib.admindocs',
+
+ 'apps.tictactoe',
+)
View
11 TicTacToe/templates/tictactoe/game_board.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html>
+<head>
+</head>
+
+<body>
+Hello!
+</body>
+
+
+</html>
View
10 TicTacToe/urls.py
@@ -0,0 +1,10 @@
+from django.conf.urls.defaults import *
+
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('',
+ (r'^$', include('TicTacToe.apps.tictactoe.urls')),
+)

No commit comments for this range

Something went wrong with that request. Please try again.