Skip to content

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.
...
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.