mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-01-04 09:07:41 -08:00
Classic TicTacToe just in Executable format
First, pick either 'X' or 'O' from the screen then, play the normal one Player TicTacToe. Playing on Terminal is kinda boring so, I made it into an executable file.
This commit is contained in:
23
89_Tic-Tac-Toe/python/TicTacToe_exe/Images.py
Normal file
23
89_Tic-Tac-Toe/python/TicTacToe_exe/Images.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import os
|
||||||
|
import game_config as gc
|
||||||
|
|
||||||
|
from pygame import image, transform
|
||||||
|
|
||||||
|
def GetName(val):
|
||||||
|
return str(val) + ".png"
|
||||||
|
|
||||||
|
class Image:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.name = GetName(val) #names of image with .png
|
||||||
|
self.image_path = os.path.join(gc.ASSET_DIR, self.name) #path of image from the assets file
|
||||||
|
self.image = image.load(self.image_path) #loaded the image
|
||||||
|
self.image = transform.scale(self.image, (gc.IMAGE_SIZE - 2 * gc.MARGIN, gc.IMAGE_SIZE - 2 * gc.MARGIN)) #fixed image as per req.
|
||||||
|
# self.box = self.image.copy() # box
|
||||||
|
#self.box.fill((200, 200, 200))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
for i in gc.ASSET_FILES:
|
||||||
|
temp = Image(i)
|
||||||
|
print(temp.name,temp.image_path,temp.image,temp)
|
||||||
3
89_Tic-Tac-Toe/python/TicTacToe_exe/README.md
Normal file
3
89_Tic-Tac-Toe/python/TicTacToe_exe/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Making of .exe file command
|
||||||
|
pip install pyinstaller // if you don't have it, also make sure the path you are using is correct
|
||||||
|
pyinstaller --onefile (I wanted it all to be in 1 file) -w (since i used pygames) app.py (name of my main python file)
|
||||||
145
89_Tic-Tac-Toe/python/TicTacToe_exe/TicTacToe.py
Normal file
145
89_Tic-Tac-Toe/python/TicTacToe_exe/TicTacToe.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
from ctypes.wintypes import PINT
|
||||||
|
from pickle import TRUE
|
||||||
|
from numpy import flip, source
|
||||||
|
import pygame
|
||||||
|
import game_config as gc
|
||||||
|
from process import TicTacToe as T
|
||||||
|
from pygame import display, event, image
|
||||||
|
from time import sleep
|
||||||
|
import Images
|
||||||
|
|
||||||
|
def initial() -> pygame.Surface:
|
||||||
|
pygame.init()
|
||||||
|
display.set_caption('Tic-Tac-Toe')
|
||||||
|
screen = display.set_mode((gc.SCREEN_SIZE, gc.SCREEN_SIZE))
|
||||||
|
print( type(screen) )
|
||||||
|
return screen
|
||||||
|
|
||||||
|
def find_xy(x, y):
|
||||||
|
row = y // gc.IMAGE_SIZE
|
||||||
|
col = x // gc.IMAGE_SIZE
|
||||||
|
return row, col
|
||||||
|
|
||||||
|
def update_board_display(screen : pygame.Surface, Game : T ):#Update only
|
||||||
|
screen.blit(image.load('assets/blank.png'), (0, 0))
|
||||||
|
#sleep(1)
|
||||||
|
screen.fill((0, 0, 0))
|
||||||
|
for i in range(gc.NUM_TILES_SIDE):
|
||||||
|
for j in range(gc.NUM_TILES_SIDE):
|
||||||
|
tile = Images.Image(Game.board[i][j])
|
||||||
|
screen.blit(tile.image, (j * gc.IMAGE_SIZE + gc.MARGIN, i * gc.IMAGE_SIZE + gc.MARGIN))
|
||||||
|
display.flip()
|
||||||
|
#sleep(1)
|
||||||
|
|
||||||
|
def GameOver(Game : T,screen : pygame.Surface) -> bool:
|
||||||
|
val = Game.CheckWin()
|
||||||
|
if val == 1:
|
||||||
|
display.flip()
|
||||||
|
update_board_display(screen,Game=Game)
|
||||||
|
sleep(1.5)
|
||||||
|
screen.blit(image.load('assets/win.png'), (0, 0))
|
||||||
|
display.flip()
|
||||||
|
sleep(2.3)
|
||||||
|
return True
|
||||||
|
if val == 0:
|
||||||
|
display.flip()
|
||||||
|
update_board_display(screen,Game=Game)
|
||||||
|
sleep(1.5)
|
||||||
|
screen.blit(image.load('assets/lose.png'), (0, 0))
|
||||||
|
display.flip()
|
||||||
|
sleep(2.3)
|
||||||
|
return TRUE
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def run(Game : T,screen : pygame.Surface, running : bool):
|
||||||
|
update_board_display(screen,Game)
|
||||||
|
display.flip()
|
||||||
|
while running:
|
||||||
|
current_events = event.get()
|
||||||
|
for e in current_events:
|
||||||
|
if e.type == pygame.QUIT:# clicked X
|
||||||
|
running = False
|
||||||
|
|
||||||
|
if e.type == pygame.KEYDOWN: #keyboard
|
||||||
|
if e.key == pygame.K_ESCAPE:# Esc to end it
|
||||||
|
running = False
|
||||||
|
|
||||||
|
if e.type == pygame.MOUSEBUTTONDOWN: #clickd
|
||||||
|
mouse_x, mouse_y = pygame.mouse.get_pos()# got position
|
||||||
|
row, col = find_xy(mouse_x, mouse_y)#location of click
|
||||||
|
if row >= gc.NUM_TILES_SIDE or col >= gc.NUM_TILES_SIDE:# if it's on screen
|
||||||
|
continue
|
||||||
|
if Game.MoveRecord(row,col) == True:#if the move is possible
|
||||||
|
if GameOver(Game,screen):#if game ends with it
|
||||||
|
running = False
|
||||||
|
break
|
||||||
|
#game is still on
|
||||||
|
a,b = Game.NextMove()# computer makes the move
|
||||||
|
print(a,b, " here ")
|
||||||
|
if a == -1 and b == -1: #special condition for tie
|
||||||
|
running = False #end the game
|
||||||
|
screen.blit(image.load('assets/tie.png'), (0, 0))
|
||||||
|
display.flip()
|
||||||
|
sleep(2.3)
|
||||||
|
break;
|
||||||
|
else:#not a tie
|
||||||
|
if GameOver(Game,screen):#if game ends with it
|
||||||
|
running = False
|
||||||
|
break
|
||||||
|
|
||||||
|
update_board_display(screen=screen,Game=Game)
|
||||||
|
display.flip()
|
||||||
|
sleep(2.1)
|
||||||
|
|
||||||
|
#screen.blit(tile.image, (j * gc.IMAGE_SIZE + gc.MARGIN, i * gc.IMAGE_SIZE + gc.MARGIN))
|
||||||
|
|
||||||
|
def X_or_O(screen : pygame.Surface) -> str:
|
||||||
|
X = Images.Image("x")
|
||||||
|
O = Images.Image("o")
|
||||||
|
#pygame.transform.scale()
|
||||||
|
# Surface, (width, height) -> Surface
|
||||||
|
X.image = pygame.transform.scale(X.image,(gc.SCREEN_SIZE//2,gc.SCREEN_SIZE))
|
||||||
|
O.image = pygame.transform.scale(O.image,(gc.SCREEN_SIZE//2,gc.SCREEN_SIZE))
|
||||||
|
screen.blit(X.image, (gc.MARGIN, gc.MARGIN))
|
||||||
|
screen.blit(O.image, (gc.MARGIN +gc.SCREEN_SIZE//2 , gc.MARGIN))
|
||||||
|
#screen.blits( blit_sequence=[ (X.image , (0,0) , pygame.Rect(0,0,gc.SCREEN_SIZE//2,gc.SCREEN_SIZE//2)), (O.image , (gc.SCREEN_SIZE//2,gc.SCREEN_SIZE//2) , pygame.Rect(gc.SCREEN_SIZE//2,gc.SCREEN_SIZE//2,gc.SCREEN_SIZE,gc.SCREEN_SIZE)) ] )
|
||||||
|
display.flip()
|
||||||
|
pick = "-1"
|
||||||
|
while True:
|
||||||
|
current_events = event.get()
|
||||||
|
for e in current_events:
|
||||||
|
if e.type == pygame.QUIT:# clicked X
|
||||||
|
return pick
|
||||||
|
|
||||||
|
if e.type == pygame.KEYDOWN: #keyboard
|
||||||
|
if e.key == pygame.K_ESCAPE:# Esc to end it
|
||||||
|
return pick
|
||||||
|
if e.type == pygame.MOUSEBUTTONDOWN:
|
||||||
|
x,y = pygame.mouse.get_pos()
|
||||||
|
if (x < gc.SCREEN_SIZE and x >= 0) or (y < gc.SCREEN_SIZE and y > 0):# if it's on screen
|
||||||
|
if x > gc.SCREEN_SIZE//2:
|
||||||
|
pick = "O"
|
||||||
|
else: pick = "X"
|
||||||
|
screen.fill((0,0,0))
|
||||||
|
display.flip()
|
||||||
|
sleep(1.1)
|
||||||
|
return pick
|
||||||
|
return pick
|
||||||
|
|
||||||
|
|
||||||
|
def play():
|
||||||
|
screen = initial()
|
||||||
|
running = True
|
||||||
|
pick = X_or_O(screen=screen)
|
||||||
|
if pick == "-1":
|
||||||
|
return
|
||||||
|
Game = T(pick,gc.NUM_TILES_SIDE)
|
||||||
|
run(Game,screen,running)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
print("Hello World!")
|
||||||
|
play()
|
||||||
|
print('Goodbye!')
|
||||||
|
|
||||||
11
89_Tic-Tac-Toe/python/TicTacToe_exe/game_config.py
Normal file
11
89_Tic-Tac-Toe/python/TicTacToe_exe/game_config.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
IMAGE_SIZE = 103
|
||||||
|
SCREEN_SIZE = 321
|
||||||
|
NUM_TILES_SIDE = 3
|
||||||
|
NUM_TILES_TOTAL = 9
|
||||||
|
MARGIN = 2
|
||||||
|
|
||||||
|
ASSET_DIR = 'assets'
|
||||||
|
ASSET_FILES = [x for x in os.listdir(ASSET_DIR)]
|
||||||
|
#assert len(ASSET_FILES) == 8
|
||||||
166
89_Tic-Tac-Toe/python/TicTacToe_exe/process.py
Normal file
166
89_Tic-Tac-Toe/python/TicTacToe_exe/process.py
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
|
||||||
|
class TicTacToe:
|
||||||
|
def __init__(self,pick,sz=3):
|
||||||
|
self.pick = pick
|
||||||
|
self.dim_sz = sz
|
||||||
|
self.board = self.ClearBoard()
|
||||||
|
|
||||||
|
def ClearBoard(self):
|
||||||
|
board = [['blur' for i in range(self.dim_sz)] for j in range(self.dim_sz)]
|
||||||
|
# made a 3x3 by-default board
|
||||||
|
return board
|
||||||
|
|
||||||
|
def MoveRecord(self,r,c):
|
||||||
|
if r > self.dim_sz or c > self.dim_sz:
|
||||||
|
return "Out of Bounds"
|
||||||
|
if self.board[r][c] != 'blur':
|
||||||
|
return "Spot Pre-Occupied"
|
||||||
|
self.board[r][c] = self.pick
|
||||||
|
return True
|
||||||
|
|
||||||
|
def CheckWin(self):# 1 you won, 0 computer won, -1 tie
|
||||||
|
|
||||||
|
#Flag syntax -> first player no. , User is Player#1 ; Check set 1 -> row and '\' diagonal & Check set 2 -> col and '/' diagonal
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(0,self.dim_sz):#Rows
|
||||||
|
flag11 = True
|
||||||
|
flag21 = True
|
||||||
|
|
||||||
|
flag12 = True
|
||||||
|
flag22 = True
|
||||||
|
for j in range(0,self.dim_sz):
|
||||||
|
|
||||||
|
ch2 = self.board[i][j]
|
||||||
|
ch1 = self.board[j][i]
|
||||||
|
#Row
|
||||||
|
if ch1 == self.pick:# if it's mine, computer didn't make it
|
||||||
|
flag21 = False
|
||||||
|
elif ch1 == 'blur':#if it's blank no one made it
|
||||||
|
flag11 = False
|
||||||
|
flag21 = False
|
||||||
|
else: flag11 = False# else i didn't make it
|
||||||
|
|
||||||
|
if ch2 == self.pick:#Same but for Col
|
||||||
|
flag22 = False
|
||||||
|
elif ch2 == 'blur':
|
||||||
|
flag12 = False
|
||||||
|
flag22 = False
|
||||||
|
else: flag12 = False
|
||||||
|
|
||||||
|
if flag11 is True or flag12 is True:# I won
|
||||||
|
return 1
|
||||||
|
if flag21 is True or flag22 is True:#Computer Won
|
||||||
|
return 0
|
||||||
|
|
||||||
|
#Diagonals#
|
||||||
|
flag11 = True
|
||||||
|
flag21 = True
|
||||||
|
|
||||||
|
flag12 = True
|
||||||
|
flag22 = True
|
||||||
|
for i in range(0,self.dim_sz):
|
||||||
|
|
||||||
|
ch2 = self.board[i][i]
|
||||||
|
ch1 = self.board[i][self.dim_sz-1-i]
|
||||||
|
|
||||||
|
if ch1 == self.pick:
|
||||||
|
flag21 = False
|
||||||
|
elif ch1 == 'blur':
|
||||||
|
flag11 = False
|
||||||
|
flag21 = False
|
||||||
|
else:flag11 = False
|
||||||
|
|
||||||
|
if ch2 == self.pick:
|
||||||
|
flag22 = False
|
||||||
|
elif ch2 == 'blur':
|
||||||
|
flag12 = False
|
||||||
|
flag22 = False
|
||||||
|
else:flag12 = False
|
||||||
|
|
||||||
|
if flag11 or flag12:
|
||||||
|
return 1
|
||||||
|
if flag21 or flag22:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
def NextMove(self):
|
||||||
|
AvailableMoves = []# will carry all available moves
|
||||||
|
PlayerWinSpot = []#if player (user Wins)
|
||||||
|
CompPick = 'O'
|
||||||
|
if self.pick == 'O':
|
||||||
|
CompPick = 'X'
|
||||||
|
for i in range(0,self.dim_sz):
|
||||||
|
for j in range(0,self.dim_sz):
|
||||||
|
|
||||||
|
if self.board[i][j] == 'blur':#BLANK
|
||||||
|
t = (i,j)
|
||||||
|
AvailableMoves.append(t)#add it to available moves
|
||||||
|
self.board[i][j] = CompPick#Check if I (Computer can win)
|
||||||
|
if self.CheckWin() ==0:#Best Case I(Computer) win!
|
||||||
|
return i,j;
|
||||||
|
self.board[i][j] = self.pick
|
||||||
|
if self.CheckWin() == 1: #Second Best Case, he (player) didn't won
|
||||||
|
PlayerWinSpot.append(t)
|
||||||
|
self.board[i][j] = 'blur'
|
||||||
|
|
||||||
|
if len(PlayerWinSpot) != 0:
|
||||||
|
self.board[PlayerWinSpot[0][0]] [PlayerWinSpot[0][1]] = CompPick
|
||||||
|
return PlayerWinSpot[0][0],PlayerWinSpot[0][1]
|
||||||
|
print(AvailableMoves)
|
||||||
|
if len(AvailableMoves) == 1:
|
||||||
|
self.board[ AvailableMoves[0][0] ][ AvailableMoves[0][1] ] = CompPick
|
||||||
|
return [ AvailableMoves[0][0] ],[ AvailableMoves[0][1] ]
|
||||||
|
if len(AvailableMoves) == 0:
|
||||||
|
return -1,-1
|
||||||
|
|
||||||
|
c1 , c2 = self.dim_sz//2,self.dim_sz//2
|
||||||
|
print(c1,c2,self.dim_sz)
|
||||||
|
if (c1,c2) in AvailableMoves:#CENTER
|
||||||
|
self.board[c1][c2] = CompPick
|
||||||
|
return c1,c2
|
||||||
|
for i in range(c1-1,-1,-1):#IN TO OUT
|
||||||
|
gap = c1 - i
|
||||||
|
#checking - 4 possibilities at max
|
||||||
|
#EDGES
|
||||||
|
if (c1-gap,c2-gap) in AvailableMoves:
|
||||||
|
self.board[c1-gap][c2-gap] = CompPick
|
||||||
|
return c1-gap,c2-gap
|
||||||
|
if (c1-gap,c2+gap) in AvailableMoves:
|
||||||
|
self.board[c1-gap][c2+gap] = CompPick
|
||||||
|
return c1-gap,c2+gap
|
||||||
|
if (c1+gap,c2-gap) in AvailableMoves:
|
||||||
|
self.board[c1+gap][c2-gap] = CompPick
|
||||||
|
return c1+gap,c2-gap
|
||||||
|
if (c1+gap,c2+gap) in AvailableMoves:
|
||||||
|
self.board[c1+gap][c2+gap] = CompPick
|
||||||
|
return c1+gap,c2+gap
|
||||||
|
|
||||||
|
#Four Lines
|
||||||
|
|
||||||
|
for i in range(0,gap):
|
||||||
|
if (c1-gap,c2-gap+i) in AvailableMoves:#TOP LEFT TO TOP RIGHT
|
||||||
|
self.board[c1-gap][c2-gap+i] = CompPick
|
||||||
|
return c1-gap,c2-gap+i
|
||||||
|
if (c1+gap,c2-gap+i) in AvailableMoves:#BOTTOM LEFT TO BOTTOM RIGHT
|
||||||
|
self.board[c1+gap][c2-gap+i] = CompPick
|
||||||
|
return c1+gap,c2-gap+i
|
||||||
|
if (c1-gap,c2-gap) in AvailableMoves:#LEFT TOP TO LEFT BOTTOM
|
||||||
|
self.board[c1-gap+i][c2-gap] = CompPick
|
||||||
|
return c1-gap+i,c2-gap
|
||||||
|
if (c1-gap+i,c2+gap) in AvailableMoves:#RIGHT TOP TO RIGHT BOTTOM
|
||||||
|
self.board[c1-gap+i][c2+gap] = CompPick
|
||||||
|
return c1-gap+i,c2+gap
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
Game = TicTacToe("X")
|
||||||
|
for i in range(0,10):
|
||||||
|
print(Game.board)
|
||||||
|
move = list(map(int,input().split()) )
|
||||||
|
print(Game.MoveRecord(move[0],move[1]))
|
||||||
|
print(Game.CheckWin())
|
||||||
|
t = Game.NextMove()
|
||||||
|
print("(",t[0],", ",t[1],")")
|
||||||
|
print(Game.CheckWin())
|
||||||
Reference in New Issue
Block a user