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