-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
200 lines (162 loc) · 6.54 KB
/
main.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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
from functools import partial
# partial enables us to make a function wrapper for buttons
import tkinter as tk
import tkinter.messagebox as tkMsg
import game
import connector as connection
from enum import Enum
class mode(Enum):
BOT = 1
SERVER = 2
CLIENT = 3
MainWindow = tk.Tk()
MainWindow.title("Tac-Tic-Toe")
Buttonsize = 5
# hardcoded port for the client-server connection
port = 5600
def showMap(Gamesize, Gamemode):
Size = int(Gamesize)
game.startGame(Gamesize, Gamemode==mode.BOT)
buttons = [[None for x in range(Size)] for y in range(Size)]
# in case the window was used before, clean it up
clearWindow(MainWindow)
# add Gamesize*Gamesize buttons in 2 dimensions to MainWindow
for r in range(Size):
for c in range(Size):
state = str(game.getValue(r, c))
newButton = tk.Button(MainWindow, text=state, borderwidth=1)
newButton.config(height=int(Buttonsize/2), width=Buttonsize);
newButton.grid(row=r, column=c)
buttons[r][c] = newButton
buttons[r][c]["command"] = partial(Move, r, c, buttons, 1, Gamemode) # 1: it's a move of the player on this end
# add Menu button to MainWindow
def localShowMenu():
if tkMsg.askyesno("Spiel beenden?", "Möchten Sie das Spiel beenden und in das Menü zurückkehren?"):
showMenu()
btn_Menu = tk.Button(MainWindow, text='Menü')
btn_Menu["command"] = localShowMenu
btn_Menu.config(width=Size*Buttonsize)
btn_Menu.grid(row=Size, column=0, columnspan=Size)
MainWindow.update()
if (Gamemode == mode.CLIENT):
waitForMove(buttons, Gamemode) # Server has the first move
def Move(r, c, buttons, ownmove, Gamemode):
result = game.setMove(r, c)
# do things only when the move was valid
if result:
# the bot has moved after player, so the field must be refreshed to
# display moves made by bot
if result is 2 or result is 3:
refresh_field(buttons)
else: # update only the button that was set by the player
buttons[r][c]["text"] = game.getValue(r, c)
winner = game.finished()
if winner:
if (ownmove and (Gamemode == mode.SERVER or Gamemode == mode.CLIENT)):
sendMove(r, c) # send move to opponent, so he also knows who won
try:
connection.close()
finally:
tkMsg.showinfo("Spielende", str(winner) + " hat das Spiel gewonnen!")
showMenu()
if (ownmove and (Gamemode == mode.SERVER or Gamemode == mode.CLIENT)):
sendMove(r, c)
MainWindow.update()
waitForMove(buttons, Gamemode)
def waitForMove(buttons, Gamemode):
global connection
if connection is None:
print("Fehler: Warten auf Zug des Gegenspielers nicht möglich. Es besteht keine Verbindung!")
else:
message = connection.receive()
row = int(message.split('#')[0])
col = int(message.split('#')[1])
Move(row, col, buttons, 0, Gamemode)
def sendMove(r, c):
global connection
if connection is None:
print("Fehler: Senden des Zuges nicht möglich. Es besteht keine Verbindung!")
else:
message = str(r)+'#'+str(c)
connection.send(message)
def refresh_field(buttons):
for r in range(game.getSize()):
for c in range(game.getSize()):
buttons[r][c]["text"] = game.getValue(r, c)
def closeMenu():
MainWindow.destroy()
def showMenu():
global port
def localStartGame(mode):
showMap(txt_gamesize.get(), mode)
def connectClient():
ip = txt_IP.get()
global connection
if (connection.startClient(ip, port)):
message = "Someone there?"
connection.send(message)
print("Client: Sent message: "+message)
print("Client: Received message: "+str(connection.receive()))
gamesize = int(connection.receive())
showMap(gamesize, mode.CLIENT)
else:
print("Connection failed.")
def connectServer():
global connection
if (connection.startServer(port)):
message = str(connection.receive())
if message:
print("Server: Received message: "+message)
message = "Acknowledged!"
connection.send(message)
print("Server: Sent message: " + message)
gamesize = txt_gamesize.get()
connection.send(str(gamesize))
showMap(gamesize, mode.SERVER)
print("Connection failed.")
# in case the window was used before, clean it up
clearWindow(MainWindow)
lbl_gamesize = tk.Label(MainWindow)
txt_gamesize = tk.Entry(MainWindow)
btn_KI = tk.Button(MainWindow)
lbl_player = tk.Label(MainWindow)
btn_newGame = tk.Button(MainWindow)
btn_join = tk.Button(MainWindow)
lbl_IP = tk.Label(MainWindow)
txt_IP = tk.Entry(MainWindow)
btn_exit = tk.Button(MainWindow)
lbl_KI = tk.Label(MainWindow)
lbl_gamesize["text"] = "Spielfeldgröße"
btn_KI["text"] = "Neues Spiel starten"
lbl_player["text"] = "Gegen anderen Spieler"
btn_newGame["text"] = "Neues Spiel starten"
btn_join["text"] = "an Spiel teilnehmen"
lbl_IP["text"] = "IP Adresse"
btn_exit["text"] = "Beenden"
txt_gamesize.insert(0, "3")
lbl_KI["text"] = "Gegen KI"
btn_exit["command"] = closeMenu
btn_KI["command"] = partial(localStartGame, mode.BOT) # 1 means to use bot as opponent
btn_newGame["command"] = connectServer
btn_join["command"] = connectClient
lbl_gamesize.grid(row=0, column=0, pady=5)
txt_gamesize.grid(row=0, column=1, pady=5, padx=5)
lbl_KI.grid(row=1, column=0, pady=5)
btn_KI.grid(row=1, column=1, pady=5)
lbl_player.grid(row=2, column=0, pady=5, padx=5)
btn_newGame.grid(row=2, column=1, pady=5)
btn_join.grid(row=3, column=1)
lbl_IP.grid(row=4, column=0, pady=5)
txt_IP.grid(row=4, column=1, pady=5)
btn_exit.grid(row=5, column=1, pady=5)
MainWindow.mainloop()
def clearWindow(tkWindow):
# remove everything from MainWindow
for widget in tkWindow.winfo_children():
widget.destroy()
if __name__ == '__main__':
print("Tac-Tic-Toe Copyright (C) 2016 Felix & Hagen\n\
This program comes with ABSOLUTELY NO WARRANTY; for details see GPL.\n\
This is free software, and you are welcome to redistribute it\n\
under certain conditions; see GPL for details.")
showMenu()