· 6 years ago · Apr 05, 2019, 01:26 PM
1import pygame
2import sys
3import pygame.freetype
4import time
5import random
6from pygame.locals import *
7from tkinter import ttk
8import tkinter
9from tkinter import messagebox
10import sqlite3
11
12
13import inputbox #This is needed to add an interface where the user can input the anwser to the math question
14import random #The function "random" is used in the get_single_question() to choose a random question from the database
15
16questions_already_solved=[0] #Array needed when the user resolve a question, so it doesn't appear anymore
17
18#SQL DATABASES~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19def SQLQuestion():
20 with sqlite3.connect("games.db") as db:
21 cursor = db.cursor()
22
23 cursor.execute("""CREATE TABLE IF NOT EXISTS game (
24 questionID integer PRIMARY KEY AUTOINCREMENT,
25 question text,
26 answer text
27 )""")
28
29def SQLUser():
30 with sqlite3.connect("User.db") as db:
31 cursor = db.cursor()
32
33 cursor.execute("""CREATE TABLE IF NOT EXISTS user (
34 userID INTEGER PRIMARY KEY,
35 username VARCHAR(20) NOT NULL,
36 password VARCHAR(20) NOT NULL,
37 usertime INTEGER
38 )""")
39
40#USER LOG IN/CREATE/DELETE ACCOUNT~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41class user1():
42
43 def __init__(self, username, password, usertime):
44 self.username = username
45 self.password = password
46 self.usertime = usertime
47
48def GetUserTime():
49 with sqlite3.connect("User.db") as db:
50 c = db.cursor()
51 c.execute("UPDATE user SET usertime = ? WHERE userID = ?", (delta_time_s, usID))
52 db.commit()
53 c.execute("SELECT usertime FROM user WHERE userID = ?",(usID))
54 GetTime = c.fetchone()[0]
55 user1(username=None, password=None,usertime=GetTime)
56
57
58def login(usernameLogin, passwordLogin,btn):
59 while True:
60 username = usernameLogin.get() #Fetches username
61 password = passwordLogin.get() #Fetches password
62 with sqlite3.connect("User.db") as db: #Creates a connection to database
63 c = db.cursor()
64 find_user = ("SELECT * FROM user WHERE username = ? AND password = ?")#Validates inputs for account
65 c.execute(find_user,[(username),(password)])
66 results = c.fetchall() #Fetches values from database for the validation process
67
68 if results: #Validates if the username/password is recognised by checking if it exists within the database
69 for i in results:
70 nameid = i[1]
71 c.execute("SELECT userID FROM user WHERE username = ?",(nameid,))
72 global usID #Global variable (ID) used to identify user account
73 usID = c.fetchone()
74 messagebox.showinfo("", "Welcome "+i[1]+"!")
75 btn.destroy()
76 QuestionMenu(usID)
77 break
78
79 else:
80 messagebox.showinfo("", "Password and username is not recognised")
81 break.lll
82 window.destroy()
83
84def newUser(username1, password1):
85 found = 0
86 while found == 0:
87 username = username1.get()
88 with sqlite3.connect("User.db") as db:
89 c = db.cursor()
90 findUser = ("SELECT * FROM user WHERE username = ?")
91 c.execute(findUser, [(username)]) #Checks existence of username in database using tuple
92
93 if c.fetchall():
94 messagebox.showinfo("Username", "Username taken please try again.")
95 break
96 else:
97 messagebox.showinfo("", "Account has been created!")
98 found = 1
99
100 password = password1.get()
101 insertData = '''INSERT INTO user(username, password)
102 VALUES(?,?)'''#Inserts new account into databse
103 c.execute(insertData, [(username),(password)])
104 db.commit()
105
106def newUserTkinter():
107 window = tkinter.Tk() #
108 window.title("Create new account")
109
110 labelOne = ttk.Label(window, text = "Enter a username:")
111 labelOne.grid(row = 0, column = 0)
112 username1 = tkinter.StringVar(window)#value type is classified as a string
113 usernameEntry = ttk.Entry(window, width = 30, textvariable = username1)
114 usernameEntry.grid(row = 1, column = 0)
115
116 labelTwo = ttk.Label(window, text = "Enter a password:")
117 labelTwo.grid(row = 2, column = 0)
118 password1 = tkinter.StringVar(window)#value type is classified as a string
119 passwordEntry = ttk.Entry(window, width = 30, textvariable = password1)
120 passwordEntry.grid(row = 3, column = 0)
121
122 btn = ttk.Button(window, text="Submit", command=lambda: newUser(username1, password1))
123 btn.grid(row = 3, column = 1)
124
125def removeUser(usernameD, passwordD):
126 exists = 0
127 while exists == 0:#Validates exsistence of account username
128 username = usernameD.get()
129 password = passwordD.get()
130 with sqlite3.connect("User.db") as db:
131 c = db.cursor()
132 findUser = ("SELECT * FROM user WHERE username = ?")
133 c.execute(findUser, [(username)])
134
135 if c.fetchall():
136 messagebox.showinfo("Delete account", "Account deleted!")
137 exists = 1
138 else:
139 messagebox.showinfo("", "Account does not exist")
140 break
141
142 remove_user = ("DELETE from user WHERE username = ? AND password = ?")
143 c.execute(remove_user,[(username),(password)])
144 db.commit()
145
146def removeUserTkinter():
147 window = tkinter.Tk()
148 window.title("Delete account")
149
150 labelOne = ttk.Label(window, text = "Enter account username:")
151 labelOne.grid(row = 0, column = 0)
152 usernameD = tkinter.StringVar(window)#value type is classified as a string
153 usernameEntry = ttk.Entry(window, width = 30, textvariable = usernameD)
154 usernameEntry.grid(row = 1, column = 0)
155
156 labelTwo = ttk.Label(window, text = "Enter account password:")
157 labelTwo.grid(row = 2, column = 0)
158 passwordD = tkinter.StringVar(window)#value type is classified as a string
159 passwordEntry = ttk.Entry(window, width = 30, textvariable = passwordD)
160 passwordEntry.grid(row = 3, column = 0)
161
162 btn = ttk.Button(window, text="Submit", command=lambda: removeUser(usernameD, passwordD))
163 btn.grid(row = 3, column = 1)
164
165def menu():
166 with sqlite3.connect("User.db") as db:
167 c = db.cursor()
168 c.execute("SELECT * FROM user")
169 print(c.fetchall())
170
171 window = tkinter.Tk()
172 window.title("Treasure Hunt Game!")
173
174 labelOne = ttk.Label(window, text = """ ~~~~~~~~~~~~~ USER MENU ~~~~~~~~~~~~~
175 """)#label displays instruction
176 labelOne.grid(row = 0, column = 0)#places label in a grid
177
178 btn = ttk.Button(window, text = "Create account", command = newUserTkinter)
179 btn.grid(row = 1, column = 0)#places button in a grid
180
181 btn = ttk.Button(window, text = "Delete account", command = removeUserTkinter)
182 btn.grid(row = 2, column = 0)#places button in a grid
183
184 labelTwo = ttk.Label(window, text = "Login to your account:")
185 labelTwo.grid(row = 3, column = 0)
186
187 usernameLogin = tkinter.StringVar(window)#value type is classified as a string
188 usernameEntry = ttk.Entry(window, width = 30, textvariable = usernameLogin)
189 usernameEntry.grid(row = 5, column = 0)
190
191 labelTwo = ttk.Label(window, text = "Username")
192 labelTwo.grid(row = 4, column = 0)
193
194 passwordLogin = tkinter.StringVar(window)#value type is classified as a string
195 passwordEntry = ttk.Entry(window, width = 30, textvariable = passwordLogin)
196 passwordEntry.grid(row = 7, column = 0)
197
198 labelTwo = ttk.Label(window, text = "Password")
199 labelTwo.grid(row = 6, column = 0)
200
201 btn = ttk.Button(window, text="Log in", command=lambda: login(usernameLogin, passwordLogin, window))
202 btn.grid(row = 7, column = 1)
203
204#SQL QUESTION ADD/REMOVE/GET~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
205def insert_question(emp):
206 conn = sqlite3.connect('games.db')
207 c = conn.cursor()
208 c.execute("INSERT INTO game VALUES (?, ?, ?)", (emp))
209 conn.commit()
210
211def get_question():
212 conn = sqlite3.connect('games.db')
213 c = conn.cursor()
214 c.execute("SELECT * FROM game")
215 return c.fetchall()
216
217def get_number_total_question(): #Get the total number of question
218 conn = sqlite3.connect('games.db')
219 c = conn.cursor()
220 c.execute("SELECT COUNT(*) FROM game")
221 return c.fetchone()[0]
222
223def get_single_question(question_number): #Get a question from the database
224 conn = sqlite3.connect('games.db')
225 c = conn.cursor()
226 c.execute("SELECT question FROM game WHERE questionID="+str(question_number))
227 return c.fetchone()[0]
228
229def get_answer(question_number): #Get the answer from the database
230 conn = sqlite3.connect('games.db')
231 c = conn.cursor()
232 c.execute("SELECT answer FROM game WHERE questionID="+str(question_number))
233 return c.fetchone()[0]
234
235def remove_question(emp):
236 conn = sqlite3.connect('games.db')
237 c = conn.cursor()
238 c.execute("DELETE from game WHERE question = ?", [emp])
239 conn.commit()
240
241#Game Menu Tkinter~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242def showInstructions():
243 messagebox.showinfo("Instructions", """You are a treasure hunter, your goal is to collect atleast 100
244gold by the end of the game from treasure chests randomly scattered across the grid.There are 10 chests within a grid and
245each treasure chest is worth 10 gold but can only be reclaimed 3 times before it is replaced by a bandit.
246Landing on a bandit will cause you to lose all of your
247gold and if all the chests have been replaced by bandits and you have less then 100 gold this means you lose!
248
249Press enter to continue...""")#messagebox used for more simple functions (showing messages)
250
251def showLeaderboard():
252 messagebox.showinfo("Leaderboard", "shows leaderboard")
253
254def con():
255 messagebox.showinfo("Game", "Time to play!")
256 pass
257 game()
258
259def showQuestions():
260 emps = get_question()
261 messagebox.showinfo("List of questions/answers", emps)
262
263def AddQuestion(mathquestion, mathanswer):
264 mathquestion1 = mathquestion.get()
265 mathanswer1 = mathanswer.get()
266 emp_1 = (None, mathquestion1, mathanswer1)
267 insert_question(emp_1)
268 messagebox.showinfo("Question inputed!")
269
270 emps = get_question()
271 print(emps)
272
273def removeQuestion(DeleteQuestion):
274 exists = 0
275 while exists == 0:#Validates exsistence of question
276 DeleteQuestion1 = DeleteQuestion.get()
277 conn = sqlite3.connect('games.db')
278 c = conn.cursor()
279 findQuestion = ("SELECT * FROM game WHERE question = ?")
280 c.execute(findQuestion, [(DeleteQuestion1)])
281
282 if c.fetchall():
283 messagebox.showinfo("Delete qustion","Question deleted!")
284 exists = 1
285 else:
286 messagebox.showinfo("","Question does not exist")
287 break
288
289 remove_question(DeleteQuestion1)
290
291def removeQuestionTk():
292 window = tkinter.Tk()
293 window.title("Remove a question.")
294
295 labelOne = ttk.Label(window, text = "Enter question to remove:")
296 labelOne.grid(row = 0, column = 0)
297 DeleteQuestion = tkinter.StringVar(window)#value type is classified as a string
298 questionEntry = ttk.Entry(window, width = 30, textvariable = DeleteQuestion)
299 questionEntry.grid(row = 1, column = 0)
300
301 btn = ttk.Button(window, text="Submit", command=lambda: removeQuestion(DeleteQuestion))
302 btn.grid(row = 1, column = 1)
303
304def QuestionMenu(getID):
305 with sqlite3.connect("games.db") as db:
306 c = db.cursor()
307
308 with sqlite3.connect("user.db") as us:
309 u = us.cursor()
310
311 u.execute("SELECT username FROM user WHERE userID = ?",(getID))
312 username = u.fetchone()[0]
313 MenuName = ("Welcome",username,"!")
314
315 window = tkinter.Tk()
316 window.title("Treasure Hunt Game!")
317
318 labelOne = ttk.Label(window, text = """ ~~~~~~~~~~~~~ GAME MENU ~~~~~~~~~~~~~
319 """)#label displays instruction
320 labelOne.grid(row = 0, column = 0)#places label in a grid
321
322 labelname = ttk.Label(window, text = MenuName)
323 labelname.grid(row = 1, column = 0)
324
325 btn = ttk.Button(window, text = "View instructions", command = showInstructions)#label displays instruction
326 btn.grid(row = 2, column = 0)#places button in a grid
327
328 btn = ttk.Button(window, text = "View leaderboard", command = showLeaderboard)
329 btn.grid(row = 3, column = 0)
330
331 btn = ttk.Button(window, text = "View all questions", command = showQuestions)
332 btn.grid(row = 4, column = 0)
333
334 btn = ttk.Button(window, text = "Continue", command = con)
335 btn.grid(row = 5, column = 0)
336
337 labelTwo = ttk.Label(window, text = "Enter a math question:")
338 labelTwo.grid(row = 6, column = 0)
339 mathquestion = tkinter.StringVar()#value type is classified as a string
340 userEntryQ = ttk.Entry(window, width = 30, textvariable = mathquestion)
341 userEntryQ.grid(row = 7, column = 0)
342
343 labelTwo = ttk.Label(window, text = "Enter the answer to this question:")
344 labelTwo.grid(row = 8, column = 0)
345 mathanswer = tkinter.StringVar()
346 userEntryQ = ttk.Entry(window, width = 30, textvariable = mathanswer)
347 userEntryQ.grid(row = 9, column = 0)
348
349 btn = ttk.Button(window, text = "Submit", command=lambda: AddQuestion(mathquestion, mathanswer))
350 btn.grid(row = 9, column = 1)
351
352 btn = ttk.Button(window, text = "Remove a question", command = removeQuestionTk)
353 btn.grid(row = 10, column = 0)#places button in a grid
354
355SQLUser()
356SQLQuestion()
357menu()
358
359#MAIN GAME~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
360
361#colours
362black = (0, 0, 0)
363white = (255, 255, 255)
364brown = (153, 76, 0)
365blue = (0, 0, 255)
366grey = (192,192,192)
367
368#game dimensions (20,30,20) BASE VALUES
369tilesize = 20
370mapwidth = 30
371mapheight = 20
372
373coins = 0
374ship = 1
375water = 2
376rock = 3
377movesMade = 4
378stopwatch = 5
379
380inventory = {
381 coins: 0,
382 movesMade: 0,
383 stopwatch: ""
384 }
385
386#position of the player
387playerPos = [0,0]
388
389resources = [coins, movesMade, stopwatch]
390
391def playsound():
392 pygame.mixer.music.load("explosion.mp3")
393 pygame.mixer.music.play()
394
395def game():
396 pygame.mixer.init()
397 print(usID)
398 pygame.init()
399 pygame.display.set_mode((200,200))
400
401 #dictionary for texture of the map
402 textures = { #the transform function scales the photo to the tile size
403 ship : pygame.transform.smoothscale(pygame.image.load('ship3.png').convert_alpha(), (tilesize, tilesize)),
404 water: pygame.transform.smoothscale(pygame.image.load('water.png'), (tilesize, tilesize)),
405 rock: pygame.transform.smoothscale(pygame.image.load('rock1.png').convert_alpha(), (tilesize, tilesize)),
406 coins: pygame.transform.smoothscale(pygame.image.load('chest.png'), (tilesize, tilesize)),
407 movesMade: pygame.transform.smoothscale(pygame.image.load('player.png'), (tilesize, tilesize)),
408 stopwatch: pygame.transform.smoothscale(pygame.image.load('stopwatch.png'), (tilesize, tilesize))
409 }
410
411 #image that will represent player
412 PLAYER = pygame.transform.smoothscale(pygame.image.load('player.png'), (tilesize, tilesize))
413
414 #utilise list comprehension to create grid
415 tilemap = [[water for w in range(mapwidth)] for h in range(mapheight)]
416
417 #set up display
418 displaysurf = pygame.display.set_mode((mapwidth*tilesize,mapheight*tilesize + 60))
419
420 #Fonts used to display text
421 font = pygame.freetype.SysFont('Times New Roman', 20)
422 invfont = pygame.font.Font('FreeSansBold.ttf', 18)
423
424 #loops through each row - Creates the game map
425 coinstot=0 #TEST
426 coins_per_row=0 #TEST
427 for rw in range(mapheight):
428 for cl in range(mapwidth):
429 randomnumber = random.randint(0,15)
430 if randomnumber == 0 or randomnumber == 1:
431 tile = rock
432 elif randomnumber == 2 or randomnumber == 3 :
433 tile = ship
434 #elif randomnumber == 4 and coins_per_row<1 and coinstot<=10 : #TEST
435 # tile = coins #TEST
436 # coins_per_row+=1 #TEST
437 else:
438 tile = water
439 #sets position in the grid
440 tilemap[rw][cl] = tile
441 coinstot+=coins_per_row #TEST
442 coins_per_row=0 #TEST
443
444 visit = {}
445 start_time = pygame.time.get_ticks() #Sets start time for game
446 while True:
447 displaysurf.fill(black) #background color
448
449 #user events
450 for event in pygame.event.get():
451 if event.type == QUIT:
452 pygame.quit()
453 sys.exit()
454 elif event.type == KEYDOWN:
455 if event.key == K_RIGHT and playerPos[0] < mapwidth - 1:
456 NextTileX1 = tilemap[playerPos[1]][playerPos[0]+1]
457 if NextTileX1 == rock:
458 playsound()
459 pass
460 else:
461 playerPos[0] += 1
462 if event.key == K_LEFT and playerPos[0] > 0:
463 NextTileX2 = tilemap[playerPos[1]][playerPos[0]-1]
464 if NextTileX2 == rock:
465 playsound()
466 pass
467 else:
468 playerPos[0] -= 1
469
470 if event.key == K_UP and playerPos[1] > 0:
471 NextTileY1 = tilemap[playerPos[1]-1][playerPos[0]]
472 if NextTileY1 == rock:
473 playsound()
474 pass
475 else:
476 playerPos[1] -= 1
477
478 if event.key == K_DOWN and playerPos[1] < mapheight -1:
479 NextTileY2 = tilemap[playerPos[1]+1][playerPos[0]]
480 if NextTileY2 == rock:
481 playsound()
482 pass
483 else:
484 playerPos[1] += 1
485 if event.key == K_SPACE:
486 pos = (playerPos[1], playerPos[0])
487 if not pos in visit: # checks whether a tile has been used
488 visit[pos] = True
489 currentTile = tilemap[playerPos[1]][playerPos[0]]
490 if currentTile == rock:
491 inventory[movesMade] += 1
492 percent = 30 # coins are kept with a probability of 30 percent and will be lost by 70 percent
493 ran1 = random.randint(0,100) # random value in [0, 99]
494 if ran1 >= percent and inventory[coins] > 30:
495 inventory[coins] -= 30
496 else:
497 inventory[coins] += 20
498
499 elif currentTile == ship:
500 n_question=0 #The "0 question" doesn't exist, so I use that number to inizialize the variable
501
502 if (len(questions_already_solved)-1)!=get_number_total_question(): #COMMENT THIS LINE TO MAKE THE QUESTIONS REPEATABLE
503 while n_question in questions_already_solved: #COMMENT THIS LINE TO MAKE THE QUESTIONS REPEATABLE
504 n_question=random.randint(1,get_number_total_question()) #INDENT THIS LINE CORRECTLY TO MAKE THE QUESTIONS REPEATABLE
505
506 question = get_single_question(n_question) #Fetches question from the Database
507 system_answer = get_answer(n_question) # Fetches answer of the question from the database
508
509 screen = pygame.display.set_mode((600, 460))
510
511 user_answer = inputbox.ask(screen, question)
512 if user_answer == system_answer: #If statement validates answer
513 messagebox.showinfo("","Correct answer!")
514 inventory[coins] += 10 #10 coins are added to the inventory
515 questions_already_solved.append(n_question) #COMMENT THIS LINE TO MAKE THE QUESTIONS REPEATABLE
516
517 else: #TEST
518 messagebox.showinfo("","Wrong answer!")
519
520 else:
521 screen = pygame.display.set_mode((600, 460))
522 user_answer = inputbox.ask(screen, "No more questions! Press ENTER to continue...")#COMMENT THIS LINE TO MAKE THE QUESTIONS REPEATABLE
523
524
525 #loops through each row
526 for row in range(mapheight):
527 #loops through each column in row
528 for column in range(mapwidth):
529 displaysurf.blit(textures[tilemap[row][column]], (column*tilesize,row*tilesize))
530
531 displaysurf.blit(PLAYER,(playerPos[0]*tilesize,playerPos[1]*tilesize))
532
533 placePosition = 10
534 for item in resources:
535 displaysurf.blit(textures[item],(placePosition, mapheight*tilesize + 20))
536 placePosition += 30
537 #text displays amount of coin
538 textObj = invfont.render(str(inventory[item]), True, white, black)
539 displaysurf.blit(textObj,(placePosition, mapheight*tilesize + 20))
540 placePosition += 50
541
542 if inventory[coins] < 100:
543 current_time = pygame.time.get_ticks() #Displays real time in milliseconds
544 global delta_time_s
545 delta_time_s = (current_time - start_time) // 1000 #Convert from milliseconds to seconds
546
547 text_surf, text_rect = font.render(str(delta_time_s), (255, 255, 255), size=30) #Renders time text to a surface object
548 marginwidth = -30# margins to the window
549 marginheight = -240
550 size = (200, 200) # window size
551 text_pos = (size[0] - text_rect.width - marginwidth, size[1] - text_rect.height - marginheight)
552
553 displaysurf.blit(text_surf, text_pos)
554
555 if inventory[coins] >= 100:
556 print(delta_time_s)
557 GetUserTime()
558 break
559 pygame.display.update()