2016년 5월 14일 토요일

Pygame 틱택토 게임 (Tic-Tac-Toe) (2)

import random, pygame, sys
from pygame.locals import *
FPS = 30 # frames per second, the general speed of the program
WINDOWWIDTH = 340 # size of window's width in pixels
WINDOWHEIGHT = 340 # size of windows' height in pixels
BOXSIZE = 100 # size of box height & width in pixels
GAPSIZE = 10 # size of gap between boxes in pixels
BOARDWIDTH = 3 # number of columns of icons
BOARDHEIGHT = 3 # number of rows of icons
# Colorset
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (100, 100, 100)
LIGHTBLUE = (153, 204, 255)
BGCOLOR = WHITE
BOXCOLOR = BLACK
HIGHLIGHTCOLOR = GRAY
LINECOLOR = WHITE
def main():
global FPSCLOCK, DISPLAYSURF
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
mousex = 0 # used to store x coordinate of mouse event
mousey = 0 # used to store y coordinate of mouse event
pygame.display.set_caption('TicTacToe - harang97')
mainBoard = [[None,None,None],[None,None,None],[None,None,None]]
playerTurn = 'X'
firstSelection = None # stores the (x, y) of the first box clicked.
DISPLAYSURF.fill(BGCOLOR)
drawBoard(mainBoard)
Message = 'None'
while True: # main game loop
mouseClicked = False
DISPLAYSURF.fill(BGCOLOR)
drawBoard(mainBoard)
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousex, mousey = event.pos
elif event.type == MOUSEBUTTONUP:
mousex, mousey = event.pos
mouseClicked = True
boxx, boxy = getBoxAtPixel(mousex, mousey)
if boxx != None and boxy != None:
# the mouse is currently over a box.
if mainBoard[boxx][boxy] == None:
drawHighlightBox(boxx, boxy)
if mainBoard[boxx][boxy] == None and mouseClicked:
mainBoard[boxx][boxy] = playerTurn # set the box as "filled"
drawXO(playerTurn, boxx, boxy)
if playerTurn == 'X':
playerTurn = 'O'
else: playerTurn = 'X'
# Algorithm that check the game is over
if hasWon(mainBoard):
if playerTurn == 'X': Message = 'Player 1 Wins!'
else: Message = 'Player 2 Wins!'
popMessage(Message)
mainBoard = [[None,None,None],[None,None,None],[None,None,None]]
playerTurn = 'X'
elif hasDraw(mainBoard):
Message = '   Draw!    '
popMessage(Message)
mainBoard = [[None,None,None],[None,None,None],[None,None,None]]
playerTurn = 'X'
# Redraw the screen and wait a clock tick.
pygame.display.update()
FPSCLOCK.tick(FPS)
def popMessage(Message):
font = pygame.font.Font('font/nanum.ttf', 32)
textSurface = font.render(Message, True, BLACK, LIGHTBLUE)
textRect = textSurface.get_rect()
textRect.center = (170, 85)
DISPLAYSURF.blit(textSurface, textRect)
pygame.display.update()
pygame.time.wait(2000)
def getBoxAtPixel(x, y):
# Draw Box on display surface
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left, top = leftTopCoordsOfBox(boxx, boxy)
boxRect = pygame.Rect(left, top, BOXSIZE, BOXSIZE)
if boxRect.collidepoint(x, y):
return (boxx, boxy)
return (None, None)
def drawBoard(board):
# Draws all of the boxes in their covered or revealed state.
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left, top = leftTopCoordsOfBox(boxx, boxy)
if board[boxx][boxy] == None:
pygame.draw.rect(DISPLAYSURF, BOXCOLOR, (left, top, BOXSIZE, BOXSIZE))
else:
pygame.draw.rect(DISPLAYSURF, BOXCOLOR, (left, top, BOXSIZE, BOXSIZE))
drawXO(board[boxx][boxy], boxx, boxy)
def leftTopCoordsOfBox(boxx, boxy):
# Convert board coordinates to pixel coordinates
left = boxx* (BOXSIZE + GAPSIZE) + GAPSIZE
top = boxy * (BOXSIZE + GAPSIZE)  + GAPSIZE
return (left, top)
def drawHighlightBox(boxx, boxy):
left, top = leftTopCoordsOfBox(boxx, boxy)
pygame.draw.rect(DISPLAYSURF, HIGHLIGHTCOLOR, (left , top , BOXSIZE , BOXSIZE))
def drawXO(playerTurn, boxx, boxy):
left, top = leftTopCoordsOfBox(boxx, boxy)
if playerTurn == 'X':
pygame.draw.line(DISPLAYSURF, LINECOLOR, (left + 3, top + 3), (left + BOXSIZE - 3, top + BOXSIZE - 3), 4)
pygame.draw.line(DISPLAYSURF, LINECOLOR, (left + BOXSIZE - 3, top + 3), (left + 3, top + BOXSIZE - 3), 4)
else:
HALF = int(BOXSIZE / 2)
pygame.draw.circle(DISPLAYSURF, LINECOLOR, (left + HALF, top + HALF), HALF - 3, 4)
def hasWon(board):
# Returns True if player 1 or 2 wins
for xrow in board: # horizontal
if xrow[0] != None and xrow[0] == xrow[1] and xrow[1] == xrow[2]:
return True
for i in range(3): # vertical
if board[0][i] != None and board[0][i] == board[1][i] and board[1][i] == board[2][i]:
return True
if board[0][0] != None and board[0][0] == board[1][1] and board[1][1] == board[2][2]: # diagnol 1
return True
if board[2][0] != None and board[2][0] == board[1][1] and board[1][1] == board[0][2]: # diagnol 2
return True
return False # no winner
def hasDraw(board):
# Returns True if all the boxes have been filled
for i in board:
if None in i:
return False
return True
if __name__ == '__main__':
main()

(1)에서 구현해야 할 점 구현 완료!

부족한 점
- 승리시 표시하는 배경 박스를 그린 후 배경색이 없는 텍스트를 그리려 했으나, 결국 텍스트 배경색 이용
- 승리&무승부시 텍스트가 떠 있는 상태에서 클릭을 할 경우 다음 판에 반영된다.

보완점
- 텍스트를 사용하는 것이 아니라 팝업 텍스트 자체를 png로 저장한 후 불러오는 방법 고려

알게된 점
- pygame.display.update() 함수를 사용하는 이유는 화면 상에서 그래픽 변경 사항을 저장한 후 실제로 우리가 볼 수 있도록 하기 위해서이다.

댓글 없음:

댓글 쓰기