Skip to content

Instantly share code, notes, and snippets.

@virtualanup
Created November 6, 2013 05:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save virtualanup/7331507 to your computer and use it in GitHub Desktop.
Save virtualanup/7331507 to your computer and use it in GitHub Desktop.
Tic Tac Toe without AI
# tictactoe
# by Virtualanup
import pygame,random
from pygame.locals import *
from sys import exit
import math
from collections import defaultdict
#game constants
FPS=20
#color codes
black=(0,0,0)
white = (255,255,255)
blue=(0,0,200)
red=(200,0,0)
green=(0,200,0)
cross=1
circle=2
empty=0
computer=1
human=2
class Player:
def __init__(self,type,sign):
self.type=type
self.sign=sign
def SetBoard(self,board):
self.board=board
def GetMove(self):
pass
#process click of mouse
def MouseClick(self,cell):
pass
#the human player class. handles mouse clicks
class HumanPlayer(Player):
def __init__(self,sign):
super().__init__(human,sign)#human player
self.lastmove=-1
def GetMove(self):
if(self.lastmove != -1):
move=self.lastmove
self.lastmove=-1
return move
def MouseClick(self,cell):
if not cell in self.board.moves: #it no move in the position
self.lastmove=cell
class BoardAnalyzer:
alllines=[[(a,b) for a in range(0,3)] for b in range(0,3)]+[[(b,a) for a in range(0,3)] for b in range(0,3)]+[[(0,0),(1,1),(2,2)],[(0,2),(1,1),(2,0)]]
def __init__(self):
print("creating new board analyzer")
self.moves=[] #this will store the moves.
self.gameover=False
self.draw=False
self.board=defaultdict(lambda:empty) #board is a dictionary that is initially empty
def Move(self,position,symbol):
#if the board position is free,copy an item to it
if self.board[position] != empty:
return False
self.board[position]=symbol
self.moves.append(position)
self.CheckGameOver()
return True
#undo the last move.
def UndoMove(self):
if len(self.moves) == 0:
return False
self.board[self.moves.pop()]=empty
return True
def GameOver(self):
return self.gameover
def Draw(self):
return self.draw
def CheckGameOver(self):
print("inside check game over")
for line in self.alllines:
px,py,pz=line
if self.board[px] != empty and self.board[px]==self.board[py]==self.board[pz]:
self.gameover = True
self.draw=False
break
else:
if len(self.moves) == 9:
self.draw=True
self.gameover = True
else:
self.gameover = False
#the computer player
class ComputerPlayer(Player):
#analyze the current board position and return heuristic value
def Heuristic(self):
pass
class Board:
gridcolor=blue
circlecolor=red
crosscolor=green
def __init__(self,boardsize=400):
self.players=[]
self.boardsize=boardsize
self.gameboard=BoardAnalyzer()
self.font = pygame.font.Font(None, 30) #load the font for displaying text
def reset(self):
print("resetting game board")
self.gameboard=BoardAnalyzer()
#notify the players about the new game board
for player in self.players:
player.SetBoard(self.gameboard)
#whoever loses gets the first chance
self.player1,self.player2=self.player2,self.player1
def printstatus(self,screen):
textstr=''
if game.gameboard.GameOver():
if game.gameboard.Draw():
textstr="Draw. Click here to reset"
else:
textstr="Player "+str(self.players.index(self.player1)+1)+" wins. Click here to reset"
else:
textstr="Player "+str(self.players.index(self.player1)+1)+"'s turn"
text = self.font.render(textstr, 1,(255,255,255))
textpos = text.get_rect(centerx=screen.get_width()/2,y=self.boardsize+5)
screen.blit(text, textpos)
def AddPlayer(self,player):
player.SetBoard(self.gameboard)
self.players.append(player)
if(len(self.players) > 1):
self.player1=self.players[0]
self.player2=self.players[1]
def draw(self,screen):
#draw the board in blue color
tolerance=20
pygame.draw.line(screen, self.gridcolor, (self.boardsize/3,tolerance), (self.boardsize/3,self.boardsize-tolerance),10)
pygame.draw.line(screen, self.gridcolor, ((2*self.boardsize)/3,tolerance), ((2*self.boardsize)/3,self.boardsize-tolerance),10)
pygame.draw.line(screen, self.gridcolor, (tolerance,(self.boardsize)/3), (self.boardsize-tolerance,(self.boardsize)/3),10)
pygame.draw.line(screen, self.gridcolor, (tolerance,(2*self.boardsize)/3), (self.boardsize-tolerance,(2*self.boardsize)/3),10)
#draw each cross or circle
for move in self.gameboard.moves:
mx,my=move
onethird=int(self.boardsize/3)
if self.gameboard.board[move] == circle:
#draw a circle in that position
pos=mx*onethird+int(onethird/2),my*onethird+int(onethird/2)
pygame.draw.circle(screen, self.circlecolor, pos, int(onethird/3), 10)
elif self.gameboard.board[move] == cross:
tl=mx*onethird+int(onethird/5),my*onethird+int(onethird/5)
tr=(mx+1)*onethird-int(onethird/5),my*onethird+int(onethird/5)
bl=mx*onethird+int(onethird/5),(my+1)*onethird-int(onethird/5)
br=(mx+1)*onethird-int(onethird/5),(my+1)*onethird-int(onethird/5)
pygame.draw.line(screen, self.crosscolor, tl, br,10)
pygame.draw.line(screen, self.crosscolor, tr, bl,10)
#get items from board analyzer and draw the required items
#find the position of the mouse click and pass to the snake
def MouseClick(self,position):
#get the cell position and pass it to the player(s)
mx,my=position
if my < self.boardsize: #if inside range
onethird=int(self.boardsize/3)
cx=int(math.floor(mx/onethird))
cy=int(math.floor(my/onethird))
cell=cx,cy
print("mouse click in ",cell,". Calling for players")
self.player1.MouseClick(cell) #pass along to the player
elif self.gameboard.GameOver():
self.reset()
def update(self):
#update the board
if not self.gameboard.GameOver():
nextpos=self.player1.GetMove()
if nextpos is not None:
#move the player in that position
self.gameboard.Move(nextpos,self.player1.sign)
#if any player caused game over, keep him as player 1
if not self.gameboard.GameOver():
self.player1,self.player2=self.player2,self.player1 #exchange the players
if(__name__ == "__main__"):
pygame.init()
boardsize=400
screen = pygame.display.set_mode((boardsize,boardsize+35))
pygame.display.set_caption('Tic Tac Toe')
gameover=False
clock = pygame.time.Clock()
game=Board()
game.AddPlayer(HumanPlayer(cross))
game.AddPlayer(HumanPlayer(circle))
while gameover==False:
clock.tick(FPS)
screen.fill(black);
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit();exit()
if event.type == pygame.MOUSEBUTTONUP:
game.MouseClick(event.pos)
game.update()
game.draw(screen)
game.printstatus(screen)
pygame.display.update()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment