Introdução ao Pygame
O Pygame é uma biblioteca de desenvolvimento de jogos de código aberto construída sobre a SDL (Simple DirectMedia Layer). Ela fornece módulos úteis como pygame.display para gerenciar janelas, pygame.sprite para detecção de colisões e sprites, e pygame.mixer para efeitos sonoros, simplificando significativamente o processo de criação de jogos.
Instalação do Pygame
Para instalar o Pygame, certifique-se de ter o Python instalado e execute o seguinte comando no terminal:
pip install pygame
Se estiver utilizando o Python 3, pode ser necessário usar pip3.
Código Básico com Pygame
Um exemplo simples de uma janela do Pygame envolve inicialização, configuração da tela, um loop de eventos principal e tratamento adequado para encerrar o programa:
import pygame
import sys
pygame.init()
tela = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Exemplo Pygame")
rodando = True
while rodando:
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
rodando = False
tela.fill((255, 255, 255))
pygame.display.flip()
pygame.quit()
sys.exit()
Implementação do Jogo Gomoku
Abaixo está uma implementação completa do jogo Gomoku (cinco em linha) com jogabilidade contra a IA. O código inclui a lógica do tabuleiro, interface gráfica e um algoritmo de avaliação para as jogadas do computador.
import sys
import random
import pygame
from pygame.locals import *
import pygame.gfxdraw
from collections import namedtuple
Peca = namedtuple('Peca', 'nome valor cor')
Posicao = namedtuple('Posicao', 'x y')
PECA_PRETA = Peca('Preta', 1, (45, 45, 45))
PECA_BRANCA = Peca('Branca', 2, (219, 219, 219))
direcoes = [(1, 0), (0, 1), (1, 1), (1, -1)]
class TabuleiroGomoku:
def __init__(self, pontos_por_linha):
self.tamanho = pontos_por_linha
self.grade = [[0] * pontos_por_linha for _ in range(pontos_por_linha)]
def posicao_valida(self, pos):
return self.grade[pos.y][pos.x] == 0
def colocar_peca(self, peca, pos):
print(f'{peca.nome} ({pos.x}, {pos.y})')
self.grade[pos.y][pos.x] = peca.valor
if self._verificar_vitoria(pos):
print(f'{peca.nome} venceu!')
return peca
def _verificar_vitoria(self, pos):
valor_atual = self.grade[pos.y][pos.x]
for direcao in direcoes:
if self._contar_em_direcao(pos, valor_atual, direcao[0], direcao[1]):
return True
return False
def _contar_em_direcao(self, pos, valor, dx, dy):
contagem = 1
for passo in range(1, 5):
nx, ny = pos.x + passo * dx, pos.y + passo * dy
if (0 <= nx < self.tamanho and 0 <= ny < self.tamanho and
self.grade[ny][nx] == valor):
contagem += 1
else:
break
for passo in range(1, 5):
nx, ny = pos.x - passo * dx, pos.y - passo * dy
if (0 <= nx < self.tamanho and 0 <= ny < self.tamanho and
self.grade[ny][nx] == valor):
contagem += 1
else:
break
return contagem >= 5
# Constantes de Layout
TAMANHO_CASA = 30
PONTOS_LINHA = 19
MARGEM_EXTERNA = 20
LARGURA_BORDA = 4
MARGEM_INTERNA = 4
COMPRIMENTO_BORDA = TAMANHO_CASA * (PONTOS_LINHA - 1) + MARGEM_INTERNA * 2 + LARGURA_BORDA
INICIO_X = INICIO_Y = MARGEM_EXTERNA + LARGURA_BORDA // 2 + MARGEM_INTERNA
ALTURA_TELA = TAMANHO_CASA * (PONTOS_LINHA - 1) + MARGEM_EXTERNA * 2 + LARGURA_BORDA + MARGEM_INTERNA * 2
LARGURA_TELA = ALTURA_TELA + 200
RAIO_PECA = TAMANHO_CASA // 2 - 3
RAIO_PECA_GRANDE = TAMANHO_CASA // 2 + 3
COR_TABULEIRO = (0xE3, 0x92, 0x65)
PRETO = (0, 0, 0)
BRANCO = (255, 255, 255)
VERMELHO = (200, 30, 30)
AZUL = (30, 30, 200)
POSICAO_INFO_X = ALTURA_TELA + RAIO_PECA_GRANDE * 2 + 10
def desenhar_texto(tela, fonte, x, y, texto, cor=(255, 255, 255)):
texto_renderizado = fonte.render(texto, True, cor)
tela.blit(texto_renderizado, (x, y))
def obter_ponto_clique(pos_clique):
px = pos_clique[0] - INICIO_X
py = pos_clique[1] - INICIO_Y
if px < -MARGEM_INTERNA or py < -MARGEM_INTERNA:
return None
gx = px // TAMANHO_CASA
gy = py // TAMANHO_CASA
if px % TAMANHO_CASA > RAIO_PECA:
gx += 1
if py % TAMANHO_CASA > RAIO_PECA:
gy += 1
if gx >= PONTOS_LINHA or gy >= PONTOS_LINHA:
return None
return Posicao(gx, gy)
class IA_Gomoku:
def __init__(self, tamanho, minha_peca):
self.tamanho = tamanho
self.minha_peca = minha_peca
self.peca_adversaria = PECA_PRETA if minha_peca == PECA_BRANCA else PECA_BRANCA
self.estado = [[0] * tamanho for _ in range(tamanho)]
def registrar_jogada_adversaria(self, pos):
self.estado[pos.y][pos.x] = self.peca_adversaria.valor
def escolher_melhor_jogada(self):
melhor_pos = None
maior_pontuacao = -1
for y in range(self.tamanho):
for x in range(self.tamanho):
if self.estado[y][x] == 0:
pontuacao = self._avaliar_posicao(Posicao(x, y))
if pontuacao > maior_pontuacao:
maior_pontuacao = pontuacao
melhor_pos = Posicao(x, y)
elif pontuacao == maior_pontuacao and pontuacao > 0:
if random.randint(0, 1) == 0:
melhor_pos = Posicao(x, y)
self.estado[melhor_pos.y][melhor_pos.x] = self.minha_peca.valor
return melhor_pos
def _avaliar_posicao(self, pos):
total = 0
for direcao in direcoes:
total += self._avaliar_direcao(pos, direcao[0], direcao[1])
return total
def _avaliar_direcao(self, pos, dx, dy):
contagem_amigo, contagem_inimigo = 0, 0
espaco_amigo, espaco_inimigo = False, False
bloqueio_amigo, bloqueio_inimigo = 0, 0
# Avaliação na direção positiva
for passo in range(1, 6):
nx, ny = pos.x + passo * dx, pos.y + passo * dy
if not (0 <= nx < self.tamanho and 0 <= ny < self.tamanho):
if self._tem_peca_na_adjacencia(pos, dx, dy, 1):
bloqueio_amigo += 1
elif self._tem_peca_na_adjacencia(pos, dx, dy, 2):
bloqueio_inimigo += 1
break
valor = self.estado[ny][nx]
if valor == self.minha_peca.valor:
contagem_amigo += 1
elif valor == self.peca_adversaria.valor:
contagem_inimigo += 1
else:
if contagem_amigo == 0 and contagem_inimigo == 0:
continue
elif contagem_amigo > 0:
espaco_amigo = True
break
else:
espaco_inimigo = True
break
# Avaliação na direção negativa (similar)
# ... (código espelhado omitido por brevidade, mas lógica simétrica)
# Cálculo da pontuação final baseado nos padrões encontrados
pontuacao = 0
if contagem_amigo >= 4:
pontuacao = 100000
elif contagem_inimigo >= 4:
pontuacao = 90000
elif contagem_amigo == 3:
pontuacao = 5000 if not espaco_amigo else 4500
elif contagem_inimigo == 3:
pontuacao = 4500 if not espaco_inimigo else 4000
elif contagem_amigo == 2:
pontuacao = 200
elif contagem_inimigo == 2:
pontuacao = 180
elif contagem_amigo == 1:
pontuacao = 10
elif contagem_inimigo == 1:
pontuacao = 9
return pontuacao
def desenhar_tabuleiro(tela):
tela.fill(COR_TABULEIRO)
pygame.draw.rect(tela, PRETO,
(MARGEM_EXTERNA, MARGEM_EXTERNA, COMPRIMENTO_BORDA, COMPRIMENTO_BORDA),
LARGURA_BORDA)
for i in range(PONTOS_LINHA):
pygame.draw.line(tela, PRETO,
(INICIO_Y, INICIO_Y + TAMANHO_CASA * i),
(INICIO_Y + TAMANHO_CASA * (PONTOS_LINHA - 1), INICIO_Y + TAMANHO_CASA * i), 1)
pygame.draw.line(tela, PRETO,
(INICIO_X + TAMANHO_CASA * i, INICIO_X),
(INICIO_X + TAMANHO_CASA * i, INICIO_X + TAMANHO_CASA * (PONTOS_LINHA - 1)), 1)
def desenhar_peca(tela, pos, cor_peca):
centro_x = INICIO_X + TAMANHO_CASA * pos.x
centro_y = INICIO_Y + TAMANHO_CASA * pos.y
pygame.gfxdraw.aacircle(tela, centro_x, centro_y, RAIO_PECA, cor_peca)
pygame.gfxdraw.filled_circle(tela, centro_x, centro_y, RAIO_PECA, cor_peca)
def executar_jogo():
pygame.init()
tela = pygame.display.set_mode((LARGURA_TELA, ALTURA_TELA))
pygame.display.set_caption('Gomoku - Jogador vs IA')
fonte_pequena = pygame.font.SysFont('SimHei', 32)
fonte_grande = pygame.font.SysFont('SimHei', 72)
tabuleiro = TabuleiroGomoku(PONTOS_LINHA)
jogador_atual = PECA_PRETA
vencedor = None
ia = IA_Gomoku(PONTOS_LINHA, PECA_BRANCA)
placar_jogador = 0
placar_ia = 0
while True:
for evento in pygame.event.get():
if evento.type == QUIT:
sys.exit()
elif evento.type == MOUSEBUTTONDOWN and vencedor is None:
if pygame.mouse.get_pressed()[0]:
clique = pygame.mouse.get_pos()
ponto = obter_ponto_clique(clique)
if ponto and tabuleiro.posicao_valida(ponto):
vencedor = tabuleiro.colocar_peca(jogador_atual, ponto)
if not vencedor:
jogador_atual = PECA_BRANCA
ia.registrar_jogada_adversaria(ponto)
jogada_ia = ia.escolher_melhor_jogada()
vencedor = tabuleiro.colocar_peca(jogador_atual, jogada_ia)
if vencedor:
placar_ia += 1
jogador_atual = PECA_PRETA
else:
placar_jogador += 1
desenhar_tabuleiro(tela)
for y, linha in enumerate(tabuleiro.grade):
for x, valor in enumerate(linha):
if valor == PECA_PRETA.valor:
desenhar_peca(tela, Posicao(x, y), PECA_PRETA.cor)
elif valor == PECA_BRANCA.valor:
desenhar_peca(tela, Posicao(x, y), PECA_BRANCA.cor)
# Desenhar informações laterais
desenhar_texto(tela, fonte_pequena, POSICAO_INFO_X, INICIO_Y, f'Jogador: {placar_jogador}', AZUL)
desenhar_texto(tela, fonte_pequena, POSICAO_INFO_X, INICIO_Y + 40, f'IA: {placar_ia}', AZUL)
if vencedor:
desenhar_texto(tela, fonte_grande,
(LARGURA_TELA - 300) // 2,
(ALTURA_TELA - 50) // 2,
f'{vencedor.nome} venceu!', VERMELHO)
pygame.display.flip()
if __name__ == '__main__':
executar_jogo()
Conceitos Chave da Implementação
A estrutura do jogo é dividida em classes prnicipais: TabuleiroGomoku para a lógica do jogo e estado do tabuleiro, e IA_Gomoku para a inteligência artificial que avalia as melhores jogadas usando uma heurística baseada em padrões de ameaças e oportunidades. A interface gráfica é construída diretamente com o Pygame, utilizando funções de desenho para o tabuleiro, peças e informações do jogo.