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