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