forked from fubrasp/puissance4Like
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Game.py
182 lines (160 loc) · 6.84 KB
/
Game.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import time
import random
from GameView import *
class Game:
NUMBER_OF_CHIPS = 42
def __init__(self):
self.gamer = 1
self.playedChips = 0
self.potentialWinner = False
self.gameView = GameView()
def get_gamer(self):
# Cette fonction retourne le numero du joueur qui doit jouer
if self.playedChips % 2 == 0:
gamer_id = GameBoard.YELLOW_CHIP
else:
gamer_id = GameBoard.RED_CHIP
return gamer_id
def display_winner(self):
if self.gamer == "" or self.gamer is None:
return "personne n'a gagne"
else:
return self.gamer + " a gagne"
def start(self):
while self.potentialWinner != GameBoard.YELLOW_CHIP \
and self.potentialWinner != GameBoard.RED_CHIP \
and self.playedChips < Game.NUMBER_OF_CHIPS:
time.sleep(0.05)
# Le joueur joue
gamer = self.get_gamer()
print(f"Joueur actuel : {gamer}") # Debug
if gamer == GameBoard.RED_CHIP:
print("L'IA joue...") # Debug
self.minimax_move(gamer, True)
else:
print("Le joueur humain joue...") # Debug
for event in self.gameView.pyGame.event.get():
self.gameView.gameBoard.display()
if event.type == self.gameView.pyGame.MOUSEBUTTONUP:
x, y = self.gameView.pyGame.mouse.get_pos()
print(f"Clic détecté à la position : ({x}, {y})") # Debug
column = self.gameView.determine_column(x)
print(f"Colonne déterminée : {column}") # Debug
self.make_move(column, gamer)
if event.type == self.gameView.pyGame.QUIT:
sys.exit(0)
self.gamer = GameBoard.YELLOW_CHIP if self.gamer == GameBoard.RED_CHIP else GameBoard.RED_CHIP
def random_move(self, gamer):
available_columns = [i for i in range(7) if self.gameView.gameBoard.is_column_available(i)]
if available_columns:
column = random.choice(available_columns)
self.make_move(column, gamer)
def minimax_move(self, gamer, is_maximizing):
best_move = None
best_value = -float('inf') if is_maximizing else float('inf')
for column in range(7):
if self.gameView.gameBoard.is_column_available(column):
self.gameView.gameBoard.put_chip(column, gamer)
self.playedChips += 1
move_value = self.minimax(3, not is_maximizing, -float('inf'), float('inf'))
self.gameView.gameBoard.remove_chip(column)
self.playedChips -= 1
if is_maximizing:
if move_value > best_value:
best_value = move_value
best_move = column
else:
if move_value < best_value:
best_value = move_value
best_move = column
if best_move is not None:
self.make_move(best_move, gamer)
def minimax(self, depth, is_maximizing, alpha, beta):
winner = self.gameView.gameBoard.get_winner()
if winner == "rouge":
return 1000000000
elif winner == "jaune":
return -1000000000
elif self.playedChips == Game.NUMBER_OF_CHIPS:
return 0
if depth == 0:
return self.evaluate_board()
if is_maximizing:
max_eval = -float('inf')
for column in range(7):
if self.gameView.gameBoard.is_column_available(column):
self.gameView.gameBoard.put_chip(column, GameBoard.RED_CHIP)
self.playedChips += 1
eval = self.minimax(depth - 1, False, alpha, beta)
self.gameView.gameBoard.remove_chip(column)
self.playedChips -= 1
max_eval = max(eval, max_eval)
alpha = max(alpha, eval)
if beta <= alpha:
break
return max_eval
else:
min_eval = float('inf')
for column in range(7):
if self.gameView.gameBoard.is_column_available(column):
self.gameView.gameBoard.put_chip(column, GameBoard.YELLOW_CHIP)
self.playedChips += 1
eval = self.minimax(depth - 1, True, alpha, beta)
self.gameView.gameBoard.remove_chip(column)
self.playedChips -= 1
min_eval = min(eval, min_eval)
beta = min(beta, eval)
if beta <= alpha:
break
return min_eval
def evaluate_board(self):
score = 0
def evaluate_line(line):
yellow_count = line.count(GameBoard.YELLOW_CHIP)
red_count = line.count(GameBoard.RED_CHIP)
if yellow_count > 0 and red_count > 0:
return 0
elif yellow_count == 4:
return -1000000
elif red_count == 4:
return 1000000
elif yellow_count == 3:
return -100
elif red_count == 3:
return 100
elif yellow_count == 2:
return -10
elif red_count == 2:
return 10
return 0
for row in range(6):
for col in range(4):
line = [self.gameView.gameBoard.board[row][col + i] for i in range(4)]
score += evaluate_line(line)
# Check vertical lines
for col in range(7):
for row in range(3):
line = [self.gameView.gameBoard.board[row + i][col] for i in range(4)]
score += evaluate_line(line)
# Check positively sloped diagonals
for row in range(3):
for col in range(4):
line = [self.gameView.gameBoard.board[row + i][col + i] for i in range(4)]
score += evaluate_line(line)
# Check negatively sloped diagonals
for row in range(3):
for col in range(4):
line = [self.gameView.gameBoard.board[row + 3 - i][col + i] for i in range(4)]
score += evaluate_line(line)
return score
def make_move(self, column, gamer):
if self.gameView.gameBoard.is_column_available(column):
self.gameView.gameBoard.put_chip(column, gamer)
self.playedChips += 1
self.potentialWinner = self.gameView.gameBoard.get_winner()
print("Gagnant ? : " + str(self.potentialWinner)) # Debug
self.gameView.render()
self.gameView.pyGame.display.flip()