Added the boardgame tic-tac-toe without winning conditions, written entirely in Python.

This commit is contained in:
Kallfaktorn 2011-01-28 01:21:12 +01:00
parent 0590fa6ca1
commit affcb739b4
28 changed files with 448 additions and 0 deletions

Binary file not shown.

91
games/tic-tac-toe/TODO Normal file
View file

@ -0,0 +1,91 @@
- background image
- subimages for game_area:s
- subimages for game markers (X or 0)
- rectangle collision on game_area:s
- redraw background then all game_area:s
- board_state: a hashtable where key is game_area_index
and value is either'x' 'o' or ' '
board contains nr_of_squares = 9
board contains array of squares with nr_of_squares elements
board contains x, y, width and height
board contains a frame
frame contains width and height
game_area contains.
game_area contains index.
game init:
t
//frame is initialized with given width and height
//frame is initialized with color
//board is initialized with frame
board is initialized with given nr_of_squares
square_dimensions is initialized with x, y width and height
board is initialized with square_dimensions
board method init() is invoked
board:init(canva, nr_of_squares, square_dimensions):
img_sqr_x = load x image from harddisk
img_sqr_y = load y image from harddisk
squares = new array of squares with nr_of squares elements
for i in nr_of_squares:
square[i].init(square_dimensions, i, nr_of_squares)
state of all game_areas is set to ' '.
board:paint():
frame_paint()
squares_paint()
board:
ptr canva
img_sqr_x
img_sqr_o
//img_sqr_blank
//frame
array of squares
squares_paint():
for square in squares:
// May paint blank also
if square.state is x:
canva.paint(square.x, square.y, img_sqr_x)
elif square.state is o:
canva.paint(square.x, square.y, img_sqr_o)
square:
int x,y,width,height
char state
init(square_dimensions, index, nr_of_squares):
//calculate x and y based on width, height and index
//should really been done in squares class instead
self.x = width * (index % (sqrt(nr_of_squares)))
self.y = height * (index % (sqrt(nr_of_squares)))
state is ' '
all values of board_state is ' '.
array of game_area:s initialized with game_positions
according to the board
-game loop:
1. print background
2. f
--marked gamepositions when hovering them

BIN
games/tic-tac-toe/board.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View file

@ -0,0 +1,18 @@
from rectangle import Rectangle
from gamerectangle import GameRectangle
from math import sqrt
#param: nr_of_squares, dimensions(could be a Rectangle)
#creates an array of gamerectangles within itself with correct
#positions from each other
class Board(object):
def __init__(self, nr_of_rectangles, dimensions):
self.game_rectangles = []
axis = sqrt(nr_of_rectangles)
width = dimensions.width
height = dimensions.height
for index in range(nr_of_rectangles):
x = width * (index % axis)
y = height * int(index / axis)
gr = GameRectangle(index, x, y, width, height)
self.game_rectangles.append(gr)

BIN
games/tic-tac-toe/board.pyc Normal file

Binary file not shown.

BIN
games/tic-tac-toe/e.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,7 @@
from rectangle import Rectangle
class GameRectangle(Rectangle):
def __init__(self, index, x, y, width, height):
self.index = index
self.state = ' '
Rectangle.__init__(self, x, y, width, height)

Binary file not shown.

View file

@ -0,0 +1,23 @@
#Input.py
#Variables: Key_Id[Int,String], KeyBehaviour[enum], Action[method]
#Methods: update() Param nothing,
#Behaviour
#in update. when called. takes the state of the key. compares with the behaviour.
#if fullfilled perform action.
#All Input instances have an id.
class Input(object):
id = -1
fun = None
def __init__(self, id, fun):
self.id = id
self.fun = fun
def notify(self):
pass
def update(self,state):
pass

BIN
games/tic-tac-toe/input.pyc Normal file

Binary file not shown.

View file

@ -0,0 +1,71 @@
#Input_Manager.py
#
from sys import exit
import pygame.event as event
import pygame.key as key
from pygame import QUIT,KEYDOWN,KEYUP,MOUSEBUTTONDOWN,MOUSEBUTTONUP
from keypress import KeyPress
from mousepress import MousePress
#inputlist: [Input]
#Input = {Key_Id, Key_Behaviour, Action}
#Key_Id: Id of a pygame key or a String matching the pygame key
#Key_Behaviour: OnPress OnRelease etc
#Action: A function to perform when the given input occurs.
#Key_Dictionary: A dictionary of Strings for the corresponding pygame key id:s
#To speed up input lookups a store a dictionary where each key corresponds to an input or a set of inputs
#for each update, lookup each key input in dict to get the affected inputs only
#Each Input subclass name must begin with Key
#Functions
#add: Add an input to the list of inputs
#remove: Remove an input from the list of inputs
#Process: For all inputs, check if any of them is occuring and trigger the corresponding action
#Defect: Press two keys at the same time and release them. Should some time give 2 KeyUp events but sometimes only gets one.
class InputManager(object):
#param: [Input]
#requires:Pygame is initialized
inputs = None
def __init__(self, inputs):
self.inputs = []
for i in inputs: #LAST UPDATED HERE!!!
if i[0] is "Key":
key_behaviour = "Key" + i[2]
#key_behaviour = key_behaviour + "." + key_behaviour
self.inputs.append(eval(key_behaviour)(i[1],i[3]))
elif i[0] is "Mouse":
mouse_behaviour = "Mouse" + i[2]
#mouse_behaviour = mouse_behaviour + "." + mouse_behaviour
self.inputs.append(eval(mouse_behaviour)(i[1],i[3]))
#desc: Look up the refreshed current input state and call the affected methods
def update(self):
for e in event.get():
if e.type == QUIT: exit()
if e.type is KEYDOWN:
for i in self.inputs:
if i.id == e.key:
i.update("Down")
if e.type is KEYUP:
for i in self.inputs:
if i.id == e.key:
i.update("Up")
if e.type is MOUSEBUTTONDOWN:
for i in self.inputs:
if i.id == e.button:
i.update("Down")
if e.type is MOUSEBUTTONUP:
for i in self.inputs:
if i.id == e.button:
i.update("Up")
for i in self.inputs:
i.notify()
#chec for keyUpdates

Binary file not shown.

View file

@ -0,0 +1,29 @@
#KeyPress.py
#Should call method if a key was pressed
#Variales: isPressed, actionPerformed
#To make sure that the key only get's pressed once when holding a button down, Two variables are needed.
#isPressed: If not pressed, call method on next keypress
#actionPerformed: If method was called and key is still down, do not call method no more
#Input instances will be allocated before gameplay, therefore: isPressed and actionPerformed will be initialized false.
#methods: init, update
#update: Will be called when there is a change in this actual keys state. With respect to the input class behaviour,
#update will evaluate if it's corresponding method should be called or not
#param: state tells if the key is down or up.
#Four possible preconditions: is not pressed and key is up. -> Set isPressed to false.
# is not pressed and key is down. ->
# is pressed and key is up.
# is pressed and key is down.
from input import Input
class KeyPress(Input):
def __init__(self, id, function):
Input.__init__(self, id, function)
def update(self,state):
if state == "Down":
self.fun()

Binary file not shown.

47
games/tic-tac-toe/main.py Normal file
View file

@ -0,0 +1,47 @@
from sys import exit
#from pygame.image import load
from pygame.display import set_mode, flip
from pygame import init
import pygame.event as event
from pygame.mouse import get_pos
from pygame import QUIT,K_UP
from inputmanager import InputManager
from tictactoeboard import TicTacToeBoard
from point import Point
#inputmanager = None
#screen = None
#board = None
def main():
global inputmanager,screen,board
#init graphics
init()
size = (150,150)
screen = set_mode(size)
#init game data
nr_of_rectangles = 9
board = TicTacToeBoard(nr_of_rectangles)
#board.paint(screen)
#init input
inputmanager = InputManager([
("Mouse", 1, "Press", (lambda: board.make_turn(Point(get_pos()[0],get_pos()[1])))),
("Key", K_UP, "Press", (lambda: print("Hello Keyboard!"))),
])
loop()
def loop():
global inputmanager,screen,board
while True:
inputmanager.update()
board.paint(screen)
flip()
if __name__ == '__main__':
main()

View file

@ -0,0 +1,9 @@
from input import Input
class MousePress(Input):
def __init__(self, id, function):
Input.__init__(self, id, function)
def update(self,state):
if state == "Down":
self.fun()

Binary file not shown.

BIN
games/tic-tac-toe/o.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View file

@ -0,0 +1,12 @@
from rectangle import Rectangle
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def inside(self, rectangle):
return ((self.x >= rectangle.x)
and (self.x <= (rectangle.x + rectangle.width))
and (self.y >= rectangle.y)
and (self.y <= rectangle.y + rectangle.height))

BIN
games/tic-tac-toe/point.pyc Normal file

Binary file not shown.

View file

@ -0,0 +1,8 @@
class Rectangle(object):
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height

Binary file not shown.

View file

@ -0,0 +1,32 @@
import unittest
from board import Board
from rectangle import Rectangle
class TestBoard(unittest.TestCase):
def setUp(self):
nr_of_rectangles = 4
dimensions = Rectangle(0, 0, 25, 35)
self.b = Board(nr_of_rectangles, dimensions)
def test_rectangle_placemenets(self):
#rectangle1: 0,0,25,35
#rectangle2: 26,0,25,35
#rectangle3: 0,36,25,35
#rectangle4: 26,36,25,35
r0 = self.b.game_rectangles[0]
r1 = self.b.game_rectangles[1]
r2 = self.b.game_rectangles[2]
r3 = self.b.game_rectangles[3]
self.assertEqual(r0.x, 0)
self.assertEqual(r0.y, 0)
self.assertEqual(r1.x, 25)
self.assertEqual(r1.y, 0)
self.assertEqual(r2.x, 0)
self.assertEqual(r2.y, 35)
self.assertEqual(r3.x, 25)
self.assertEqual(r3.y, 35)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,23 @@
import unittest
from gamerectangle import GameRectangle
class TestGameRectangle(unittest.TestCase):
def setUp(self):
self.index = 0
self.x = 1
self.y = 2
self.width = 34
self.height = 0.23
self.gr = GameRectangle(self.index, self.x, self.y, self.width, self.height)
def test_attributes(self):
self.assertEqual(self.index, self.gr.index)
self.assertEqual(self.gr.state, ' ')
self.assertEqual(self.x, self.gr.x)
self.assertEqual(self.y, self.gr.y)
self.assertEqual(self.width, self.gr.width)
self.assertEqual(self.height, self.gr.height)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,27 @@
import unittest
from rectangle import Rectangle
def main():
x = 1
y = 2
width = 34
height = 0.23
r = Rectangle(x, y, width, height)
class TestRectangle(unittest.TestCase):
def setUp(self):
self.x = 1
self.y = 2
self.width = 34
self.height = 0.23
self.r = Rectangle(self.x, self.y, self.width, self.height)
def test_attributes(self):
self.assertEqual(self.x, self.r.x)
self.assertEqual(self.y, self.r.y)
self.assertEqual(self.r.width, self.r.width)
self.assertEqual(self.r.height, self.r.height)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,51 @@
from board import Board
from rectangle import Rectangle
from point import Point
from pygame.image import load
from pygame.rect import Rect
from pygame import Surface
#inherits Board.
#Used for displaying the board on the screen and interact with it
#thus images are needed for the various rectangles
#as well as a paint function
#Should be updated after every valid player move
class TicTacToeBoard(Board):
def __init__(self, nr_of_rectangles):
self.image_e = load("e.png")
self.image_x = load("x.png")
self.image_o = load("o.png") #TODO add the o image
dimensions = Rectangle(0, 0, self.image_x.get_width(),
self.image_x.get_height())
self.players_turn = 0
Board.__init__(self, nr_of_rectangles, dimensions)
def paint(self, table_image):
for game_rectangle in self.game_rectangles:
x = game_rectangle.x
y = game_rectangle.y
w = game_rectangle.width
h = game_rectangle.height
image = None
if game_rectangle.state == ' ':
image = self.image_e
elif game_rectangle.state == 'x':
image = self.image_x
elif game_rectangle.state == 'o':
image = self.image_o
print(game_rectangle.state)
table_image.blit(image, Rect(x, y, w, h))
def make_turn(self, mouse_point):
for game_rectangle in self.game_rectangles:
if (mouse_point.inside(game_rectangle) and
game_rectangle.state == ' '):
if self.players_turn == 0:
game_rectangle.state = 'x'
elif self.players_turn == 1:
game_rectangle.state = 'o'
self.players_turn = (self.players_turn + 1) % 2

Binary file not shown.

BIN
games/tic-tac-toe/x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB