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