""" Programma per giocare a Forza 4 tra due giocatori umani. Questa è la versione del programma scritta a lezione durante il laboratorio. È funzionante, ma non considera due casi: - il tentativo di inserire la pedina in una colonna piena; - la situazione di pareggio. """ from ezgraphics import GraphicsWindow # STATO DEL GIOCO: # - >>disposizione dei gettoni nel campo di gioco<< # usiamo una tabella della dimensione del campo di gioco # ogni elemento della tabella corrisponde ad una posizione # nel campo di gioco # gli elementi avranno valore -1 per il gettone blu, 0 per # la cella vuota, 1 per la cella rossa # - >>giocatore che deve fare la prossima mossa<< # una variabile intera che assume i valori 1 e -1 # corrispondenti ai due giocatori # DIMENSIONE IN PIXEL DI UNA CELLETTA CELL_SIZE = 40 # BOARD_SIZE È IL NUMERO DI CELLE IN ORIZZONTALE E IN VERTICALE # DEL CAMPO DA GIOCO BOARD_SIZE = 10 # COORDINATE MASSIMA (SIA X CHE Y) CALCOLATA A PARTIRE DA CELL_SIZE E BOARD_SIZE WINDOW_SIZE = CELL_SIZE * BOARD_SIZE def disegna_campo_gioco(canvas): for i in range(BOARD_SIZE): # disegnare la riga orizzontale i-esima canvas.drawLine(0, CELL_SIZE * i, WINDOW_SIZE - 1, CELL_SIZE * i) for i in range(BOARD_SIZE): # disegnare la riga orizzontale i-esima canvas.drawLine(CELL_SIZE * i, 0, CELL_SIZE * i, WINDOW_SIZE - 1) def crea_tabella(num_righe, num_colonne, v): """ Crea una matrice di num_rige * num_colonne tutta piena di 0. """ riga = [v] * num_colonne # partiamo da una tabella inizialmente vuota tabella = [] for _ in range(num_righe): # e aggiungiamo alla tabella una nuova riga alla volta tabella.append(riga[:]) return tabella def coordinate_gettone(x, y, m): # calcolo la colonna dove ho cliccato j = x // CELL_SIZE # trovo la prima cella dal basso contenente 0 # nella colonna j di m for i in range(BOARD_SIZE - 1, -1, -1): if m[i][j] == 0: return i, j def disegna_gettone(canvas, i, j, giocatore): if giocatore == -1: canvas.setColor("blue") else: canvas.setColor("red") canvas.drawOval(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE) def giocatore_vincente(m, i, j): """ Considera la cella in riga "r" e colonna "c" della griglia rappresentata in "board". Se da quella cella parte una sequenza di gettoni che rende vincente il giocatore g, allora restituisce g. In caso contrario, restituisce uno 0. """ player = m[i][j] if (j <= len(m[0]) - 4 and m[i][j + 1] == player and m[i][j + 2] == player and m[i][j + 3] == player): return player if (i <= len(m) - 4 and m[i + 1][j] == player and m[i + 2][j] == player and m[i + 3][j] == player): return player if (i <= len(m) - 4 and j <= len(m[0]) - 4 and m[i + 1][j + 1] == player and m[i + 2][j + 2] == player and m[i + 3][j + 3] == player): return player if (i <= len(m) - 4 and j >= 3 and m[i + 1][j - 1] == player and m[i + 2][j - 2] == player and m[i + 3][j - 3] == player): return player return 0 def vincitore(m): """ Restituisce il giocatore vincitore in una determinata configurazione di gioco, 0 se non vince nessuno. """ for i in range(len(m)): for j in range(len(m[0])): winner = giocatore_vincente(m, i, j) if winner != 0: return winner return 0 def main(): win = GraphicsWindow(WINDOW_SIZE, WINDOW_SIZE) win.setTitle("Forza 4") canvas = win.canvas() disegna_campo_gioco(canvas) # Le variabili campo_gioco e giocatore_corrente mantengono lo # stato del gioco campo_gioco = crea_tabella(BOARD_SIZE, BOARD_SIZE, 0) giocatore_corrente = -1 while True: x, y = win.getMouse() # TODO: gestire il caso in cui nella colonna selezionata non c'è spazio # e quindi il click non è valido (coordinate_gettone restituisce None) i, j = coordinate_gettone(x, y, campo_gioco) campo_gioco[i][j] = giocatore_corrente disegna_gettone(canvas, i, j, giocatore_corrente) # restituisce 0 se non ha vinto nessuno, -1 o 1 se ha vinto uno dei due giocatori. num_vincente = vincitore(campo_gioco) if num_vincente != 0: win.close() print("Ha vinto il giocatore", num_vincente) break # TODO: gestire il caso in cui il campo da gioco è completamente # pieno e quindi c'è un pareggio # cambia da 1 a -1 e viceversa giocatore_corrente = giocatore_corrente * -1 main()