This repository has been archived by the owner on Jun 21, 2020. It is now read-only.
forked from Gravitar64/A-beautiful-code-in-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Teil_16_Vier_gewinnt.py
180 lines (147 loc) · 4.11 KB
/
Teil_16_Vier_gewinnt.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
# 4-gewinnt
from collections import defaultdict
import time
board = {}
RICHTUNGEN = [(-1, -1), (0, -1), (1, -1), (-1, 0),
(1, 0), (-1, 1), (0, 1), (1, 1)]
SPALTEN = 7
ZEILEN = 6
ZELLEN = SPALTEN * ZEILEN
pos_zu_quadindex = defaultdict(list)
def quadPositionen(pos, vec):
positionen = set()
sp, ze = pos
rsp, rze = vec
neue_sp, neue_ze = sp + rsp*3, ze+rze*3
if neue_sp < 0 or neue_sp >= SPALTEN or neue_ze < 0 or neue_ze >= ZEILEN:
return False
for i in range(4):
positionen.add((sp+rsp*i, ze+rze*i))
return positionen
def findeQuads():
zähler = 0
quads = {}
bekannte_positionen = set()
for i in range(ZELLEN):
for richtung in RICHTUNGEN:
positionen = quadPositionen(i2pos(i), richtung)
if not positionen or positionen in bekannte_positionen:
continue
quads[zähler] = [0, 0, positionen] # Anzahl der gelben[0], roten[1] Steine im Quad
for position in positionen:
pos_zu_quadindex[position].append(zähler)
bekannte_positionen.add(frozenset(positionen))
zähler += 1
return quads
def i2pos(i):
return (i % SPALTEN, i // SPALTEN)
def lieferZeile(spalte):
for zeile in reversed(range(ZEILEN)):
if (spalte, zeile) not in board:
return zeile
def lieferSpalten():
gültige_spalten = []
for spalte in range(SPALTEN):
gültige_spalten.append(spalte) if (spalte, 0) not in board else None
return gültige_spalten
def SteinSetzen(player, pos):
win = False
board[pos] = 'O' if player else 'X'
for index in pos_zu_quadindex[pos]:
quad = quads[index]
quad[player] += 1
if quad[player] == 4:
win = True
return win
def SteinLöschen(player, pos):
del board[pos]
for index in pos_zu_quadindex[pos]:
quads[index][player] -= 1
def gültigeZüge():
gültig = []
for spalte in lieferSpalten():
zeile = lieferZeile(spalte)
gültig.append((spalte, zeile))
return gültig
def printBoard():
for i in range(ZELLEN):
print(board[i2pos(i)], end=' ') if i2pos(
i) in board else print('.', end=' ')
print() if (i+1) % SPALTEN == 0 else None
def bewertung():
score = 0
for pos in board:
for index in pos_zu_quadindex[pos]:
gelbe, rote, _ = quads[index]
if gelbe > 0 and rote > 0:
continue
score += rote*10
score -= gelbe*10
return score
def löscheQuads():
to_del = []
for index, values in quads.items():
if values[0] == 0 or values[1] == 0:
continue
to_del.append(index)
for position in values[2]:
pos_zu_quadindex[position].remove(index)
for index in to_del:
del quads[index]
def computer(spieler):
win = False
score, bester_zug = minimax(8, -999999, 999999, spieler, win)
win = SteinSetzen(spieler, bester_zug)
print(f'Spieler {1 if spieler else 2} setzt {bester_zug} mit der Bewertung {score}')
return win
def minimax(tiefe, alpha, beta, spieler, win):
if win:
score = -99999-tiefe if spieler else 99999+tiefe
return (score, None)
if tiefe == 0 or len(board) == ZELLEN:
return (bewertung(), None)
value = -999999 if spieler else 999999
for zug in gültigeZüge():
win = SteinSetzen(spieler, zug)
score,_ = minimax(tiefe-1, alpha, beta, not spieler, win)
SteinLöschen(spieler,zug)
if spieler:
if score > value:
bester_zug = zug
value = score
alpha = max(value, alpha)
else:
if score < value:
bester_zug = zug
value = score
beta = min(value, beta)
if alpha >= beta:
break
return (value, bester_zug)
def human(player):
spalte = int(input(f'Ihr Zug {lieferSpalten()}: '))
zeile = lieferZeile(spalte)
win = SteinSetzen(player, (spalte, zeile))
return win
def spielende(win):
if win:
print(f'Spieler {1 if player else 2} hat gewonnen')
return True
if len(board) == ZELLEN:
print('UNENTSCHIEDEN!!!!')
return True
quads = findeQuads()
start = time.perf_counter()
player = True
while True:
if player:
win = human(player)
else:
win = computer(player)
printBoard()
print('\n')
if spielende(win):
break
löscheQuads()
player = not player
print(time.perf_counter()-start)