4
\$\begingroup\$

This is a python game that I am working on. It is a grid based treasure hunt game in which you collect coins from specific tiles (some tiles ask you questions in which you need to answer correctly in order to get coins), and after a number of moves the coins that you end up with are recorded and put in a file. At the moment I haven't fully implemented everything to the final game but I am using SQlite3 for the backend database of storing questions/answers and for the front end Tkinter and Pygame. Any advice on how to improve my code, organise it, make it more efficient or anything else would be good to know. Thanks.

import pygame, sys
import random
from pygame.locals import *
from tkinter import ttk
import tkinter
from tkinter import messagebox
import sqlite3
conn = sqlite3.connect('games.db')
c = conn.cursor()
#creates table 
#c.execute("""CREATE TABLE game (
# questionID integer PRIMARY KEY AUTOINCREMENT,
# question text,
# answer text
# )""")
#execute only once
#SQL QUESTION ADD/REMOVE/GET
def insert_question(emp):
 c.execute("INSERT INTO game VALUES (?, ?, ?)", (emp))
 conn.commit()
def get_question():
 c.execute("SELECT * FROM game")
 return c.fetchall()
def remove_question(emp):
 c.execute("DELETE from game WHERE question = ?", [emp])
 conn.commit()
#Tkinter
window = tkinter.Tk()
window.title("Treasure Hunt Game!")
labelOne = ttk.Label(window, text = """ ~~~~~~~~~~~~~ MENU ~~~~~~~~~~~~~
""")#label displays instruction
labelOne.grid(row = 0, column = 0)#places label in a grid
def showInstructions():
 messagebox.showinfo("Instructions", "shows instructions")#messagebox used for more simple functions (showing messages)
btn = ttk.Button(window, text = "View instructions", command = showInstructions)
btn.grid(row = 1, column = 0)#places button in a grid
def showLeaderboard():
 messagebox.showinfo("Leaderboard", "shows leaderboard")
 window.destroy()
btn = ttk.Button(window, text = "View leaderboard", command = showLeaderboard)
btn.grid(row = 2, column = 0)
def showQuestions():
 emps = get_question()
 messagebox.showinfo("List of questions/answers", emps)
btn = ttk.Button(window, text = "View all questions", command = showQuestions)
btn.grid(row = 3, column = 0)
btn = ttk.Button(window, text = "Continue", command = showLeaderboard)
btn.grid(row = 4, column = 0)
labelTwo = ttk.Label(window, text = "Enter a math question:")
labelTwo.grid(row = 5, column = 0)
mathquestion = tkinter.StringVar()#value type is classified as a string
userEntryQ = ttk.Entry(window, width = 30, textvariable = mathquestion)
userEntryQ.grid(row = 6, column = 0)
labelTwo = ttk.Label(window, text = "Enter the answer to this question:")
labelTwo.grid(row = 7, column = 0)
mathanswer = tkinter.StringVar()
userEntryQ = ttk.Entry(window, width = 30, textvariable = mathanswer)
userEntryQ.grid(row = 8, column = 0)
def answer():
 mathquestion1 = mathquestion.get()
 mathanswer1 = mathanswer.get()
 emp_1 = (None, mathquestion1, mathanswer1)
 insert_question(emp_1)
 emps = get_question()
 print(emps)
btn = ttk.Button(window, text = "Submit", command = answer)
btn.grid(row = 8, column = 1)
labelTwo = ttk.Label(window, text = "Enter question to remove:")
labelTwo.grid(row = 9, column = 0)
removequestion = tkinter.StringVar()
userEntryQ = ttk.Entry(window, width = 30, textvariable = removequestion)
userEntryQ.grid(row = 10, column = 0)
def remove():
 removequestion1 = removequestion.get()
 remove_question(removequestion1)
btn = ttk.Button(window, text = "Submit", command = remove)
btn.grid(row = 10, column = 1)
window.mainloop()
#MAIN GAME
#colours
black = (0, 0, 0)
white = (255, 255, 255)
brown = (153, 76, 0)
blue = (0, 0, 255)
grey = (192,192,192)
#game dimensions
tilesize = 20
mapwidth = 30
mapheight = 20
coins = 0
ship = 1
water = 2
rock = 3
movesMade = 4
#dictionary for texture of the map
textures = { #the transform function scales the photo to the tile size
 ship : pygame.transform.smoothscale(pygame.image.load('ship.png'), (tilesize, tilesize)),
 water: pygame.transform.smoothscale(pygame.image.load('water.png'), (tilesize, tilesize)),
 rock: pygame.transform.smoothscale(pygame.image.load('rock.png'), (tilesize, tilesize)),
 coins: pygame.transform.smoothscale(pygame.image.load('chest.png'), (tilesize, tilesize)),
 movesMade: pygame.transform.smoothscale(pygame.image.load('player.png'), (tilesize, tilesize))
 }
inventory = {
 coins: 0,
 movesMade: 0
 }
#image that will represent player
PLAYER = pygame.transform.smoothscale(pygame.image.load('player.png'), (tilesize, tilesize))
#position of the player
playerPos = [0,0]
resources = [coins, movesMade]
#utilise list comprehension to create grid
tilemap = [[water for w in range(mapwidth)] for h in range(mapheight)]
pygame.init()
#set up display
displaysurf = pygame.display.set_mode((mapwidth*tilesize,mapheight*tilesize + 60))
invfont = pygame.font.Font('FreeSansBold.ttf', 18)
#loops through each row
for rw in range(mapheight):
 for cl in range(mapwidth):
 randomnumber = random.randint(0,15)
 if randomnumber == 0 or randomnumber == 1:
 tile = rock
 elif randomnumber == 2 or randomnumber == 3 :
 tile = ship
 else:
 tile = water
 #sets position in the grid
 tilemap[rw][cl] = tile
visit = {}
while True:
 displaysurf.fill(black) #background color
 #user events
 for event in pygame.event.get():
 if event.type == QUIT:
 pygame.quit()
 sys.exit()
 elif event.type == KEYDOWN:
 if event.key == K_RIGHT and playerPos[0] < mapwidth - 1:
 playerPos[0] += 1
 if event.key == K_LEFT and playerPos[0] > 0:
 playerPos[0] -= 1
 if event.key == K_UP and playerPos[1] > 0:
 playerPos[1] -= 1
 if event.key == K_DOWN and playerPos[1] < mapheight -1:
 playerPos[1] += 1
 if event.key == K_SPACE:
 pos = (playerPos[1], playerPos[0])
 if not pos in visit: # checks whether a tile has been used
 visit[pos] = True 
 currentTile = tilemap[playerPos[1]][playerPos[0]]
 if currentTile == rock:
 inventory[movesMade] += 1
 percent = 30 # coins are kept with a probability of 30 percent and will be lost by 70 percent
 ran1 = random.randint(0,100) # random value in [0, 99]
 if ran1 >= percent:
 inventory[coins] = 0
 else:
 inventory[coins] += 100
 elif currentTile == ship:
 inventory[coins] += 20
 inventory[movesMade] += 1
 #loops through each row 
 for row in range(mapheight):
 #loops through each column in row
 for column in range(mapwidth):
 displaysurf.blit(textures[tilemap[row][column]], (column*tilesize,row*tilesize))
 displaysurf.blit(PLAYER,(playerPos[0]*tilesize,playerPos[1]*tilesize))
 placePosition = 10
 for item in resources:
 displaysurf.blit(textures[item],(placePosition, mapheight*tilesize + 20))
 placePosition += 30
 #text displays amount of coin
 textObj = invfont.render(str(inventory[item]), True, white, black)
 displaysurf.blit(textObj,(placePosition, mapheight*tilesize + 20))
 placePosition += 50
 #if inventory[coins] > 100:
 # break
 pygame.display.update()
asked Feb 12, 2019 at 22:34
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Some suggestions:

  • There is very little structure. A game like this would typically have at least Game, Question, Answer, Storage and Window classes and a main method which just creates a Game and runs it.
  • Pull out fields or constants (as appropriate) for magic values such as strings and numbers, so a reader can know at a glance what they are, rather than just their value.
  • Run the code through flake8 and pycodestyle to get hints about non-pythonic code such as the variable names.
answered Feb 13, 2019 at 2:45
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.