Mastermind Game, Pygame, Adding the guess Indicators - python

I have got my game working, and i am happy with how it looks, I need to add the 4 indicators next to each row in the game, to signal whether the guess by the user is close to the computer guess
A quick explanation of the game
If the user guesses a colour but it is in the wrong position then it should change a indicator to orange
if its in the correct position it shoulde change to red. Then the user uses this to keep guessing
I think i could possibly draw 4 circles next to each row and then change the colour of them depending
On the guess from the user. However I am not sure on how to do this
There also might be a mor efficient way to do this, so of there is any suggestions would be great
The code looks like this
I have added some code, for the computer guess and if you guess correctly
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0 , 0, 255)
WIDTH = 20
HEIGHT = 20
WIDTH1 = 30
HEIGHT1 = 30
MARGIN = 5
MARGIN1 = 10
array_width = 4
array_height = 8
grid = []
for row in range(10):
grid.append([])
for column in range(10):
grid[row].append(0)
colors = [(0, 0, 0) for i in range(array_width * array_height)]
blocks = [False for i in range(array_width * array_height)]
pygame.init()
# Set the HEIGHT and WIDTH of the screen
WINDOW_SIZE = [300, 300]
screen = pygame.display.set_mode(WINDOW_SIZE)
# Set title of screen
pygame.display.set_caption("MASTERMIND GAME")
sair = True
done = False
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
grid[row][column] = 1
#TEXT BOX VARIABLES AND DATA
base_font = pygame.font.Font(None, 32)
user_text = ""
input_rect = pygame.Rect (10,250,100,50)
color_active = pygame.Color('lightskyblue3')
color_passive = pygame.Color('gray15')
color=color_passive
active = False
current_color = "white"
grid = [[current_color for column in range(4)] for row in range(8)]
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
print (blocks)
pos = pygame.mouse.get_pos()
column = pos[0] // (WIDTH + MARGIN)
row = pos[1] // (HEIGHT + MARGIN)
print(row)
print(column)
# TEXT BOX CREATION AND USAGE
# check if column and row are valid grid indices
if 0 <= row < array_height and 0 <= column < array_width:
try:
grid[row][column] = current_color
except:
print("invalid color")
if event.type == pygame.MOUSEBUTTONDOWN:
if input_rect.collidepoint(event.pos):
active = True
else:
active = False
if event.type == pygame.KEYDOWN:
if active == True:
if event.key == pygame.K_BACKSPACE:
user_text = user_text[0:-1]
else:
user_text += event.unicode
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
user_text = user_text
print(user_text)
if user_text != "":
current_color = user_text
user_text = ""
print("Click ", pos, "Grid coordinates: ", row, column)
if active:
color = color_active
else:
color=color_passive
screen.fill(0)
pygame.draw.rect(screen,color,input_rect,2)
text_surface= base_font.render(user_text,True,(255,255,255))
screen.blit(text_surface, (input_rect.x +5, input_rect.y + 5))
for row, gridrow in enumerate(grid):
for column, color in enumerate(gridrow):
pygame.draw.rect(screen,
color,
[(MARGIN + WIDTH) * column + MARGIN,
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
clock.tick(60)
pygame.display.flip()
pygame.quit
Thanks

The question has several sub-questions and I just answered one. So there are plenty of opportunities for additional answers from other contributors.
Create a new grid for the indicators. The initial value for all fields is None:
indicator_grid = [[None for column in range(4)] for row in range(8)]
Draw the indicators in nested loops:
while not done:
# [...]
for row, gridrow in enumerate(indicator_grid):
for column, status in enumerate(gridrow):
x = 100 + (MARGIN + WIDTH) * column + MARGIN
y = (MARGIN + HEIGHT) * row + MARGIN
color = "grey"
if status != None:
color = "red" if status else "orange"
pygame.draw.circle(screen, color, (x+WIDTH//2, y+WIDTH//2), WIDTH//2)
When you want to set the state in indicator_grid to True or False, the color of the corresponding circle changes.

Related

Pygame Mastermind game, Problems with getting the grid to work as intended

i am creating a mastermind game with python and pygame, I was beginning by trying to get the text box to take an input and then allow the user to make a guess
My code looks like this, sorry if it is a bit messy
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0 , 0, 255)
WIDTH = 20
HEIGHT = 20
WIDTH1 = 30
HEIGHT1 = 30
MARGIN = 5
MARGIN1 = 10
array_width = 4
array_height = 8
grid = []
for row in range(10):
grid.append([])
for column in range(10):
grid[row].append(0)
colors = [(0, 0, 0) for i in range(array_width * array_height)]
blocks = [False for i in range(array_width * array_height)]
pygame.init()
# Set the HEIGHT and WIDTH of the screen
WINDOW_SIZE = [300, 300]
screen = pygame.display.set_mode(WINDOW_SIZE)
# Set title of screen
pygame.display.set_caption("Array Backed Grid")
sair = True
done = False
coord =[]
clock = pygame.time.Clock()
grid[row][column] = 0
# -------- Main Program Loop -----------
grid[row][column] = 1
base_font = pygame.font.Font(None, 32)
user_text = ""
input_rect = pygame.Rect (10,250,100,50)
color_active = pygame.Color('lightskyblue3')
color_passive = pygame.Color('gray15')
color=color_passive
active = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
print (blocks)
pos = pygame.mouse.get_pos()
for i in range(array_width):
for j in range(array_height):
column = pos[0] // (WIDTH + MARGIN)
row = pos[1] // (HEIGHT + MARGIN)
print(row)
print(column)
blocks[row * array_height + column] = not blocks[row * array_height + column]
# toggle
for row in range(array_width):
for column in range(array_height):
# CHECK IF BLOCK SHOULD BE CHANGED
if blocks[column * array_width + row]:
if user_text == 'blue':
colors[column * array_height + row] = (0, 0, 255)
print("Click ", pos, "Grid coordinates: ", row, column)
# TEXT BOX CRETAION AND USAGE
if event.type == pygame.MOUSEBUTTONDOWN:
if input_rect.collidepoint(event.pos):
active = True
else:
active = False
if event.type == pygame.KEYDOWN:
if active == True:
if event.key == pygame.K_BACKSPACE:
user_text = user_text[0:-1]
else:
user_text += event.unicode
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
user_text = user_text
print(user_text)
if active:
color = color_active
else:
color=color_passive
pygame.draw.rect(screen,color,input_rect,2)
text_surface= base_font.render(user_text,True,(255,255,255))
screen.blit(text_surface, (input_rect.x +5, input_rect.y + 5))
for row in range(array_width):
for column in range(array_height):
pygame.draw.rect(screen,
# GET THE COLOR AT THAT INDEX
colors[column * array_width + row],
[(MARGIN + WIDTH) * column + MARGIN,
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
for row in range(8):
for column in range(4):
color = WHITE
if user_text == 'yellow':
print (grid)
grid[row][column] = 2
color = BLUE
pygame.draw.rect(screen,
color,
[(MARGIN + WIDTH) * column + MARGIN,
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
if user_text == 'green':
grid[row][column] = 1
color = GREEN
pygame.draw.rect(screen,
color,
[(MARGIN + WIDTH) * column + MARGIN,
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
clock.tick(60)
pygame.display.flip()
pygame.quit()
After running the code, if i click on any of the boxes, nothing seems to happen, which i somewhat expected as i need to write more.
When i click on the text box,
The gui looks like this
This error pops up when i click on the text box below the grid
blocks[row * array_height + column] = not blocks[row * array_height + column]
IndexError: list index out of range
I don't know why this is happening
Any help appreciated,
Thanks
You don't need the extra outer loops at all (for i in range(array_width): and for j in range(array_height):).
However, you have to evaluate whether column is less than array_height and row is smaller than array_width`:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
print (blocks)
pos = pygame.mouse.get_pos()
column = pos[0] // (WIDTH + MARGIN)
row = pos[1] // (HEIGHT + MARGIN)
print(row)
print(column)
# check if column and row are valid grid indices
if 0 <= column < array_height and 0 <= row < array_width:
blocks[row * array_height + column] = not blocks[row * array_height + column]
# toggle
for row in range(array_width):
for column in range(array_height):
# CHECK IF BLOCK SHOULD BE CHANGED
if blocks[column * array_width + row]:
if user_text == 'blue':
colors[column * array_height + row] = (0, 0, 255)
print("Click ", pos, "Grid coordinates: ", row, column)

Why will this loop not repeat itself in the order of the statements?

I am having trouble sorting out a loop in my program which does not behave a I would expect. This program lets you play "Connect Four". I included the full (runnable code) and the excerpt that troubles me at the end.
import numpy as np
import random
import pygame
import time
BOARD_SIZE = 6
BOARD_BOX_NUM = BOARD_SIZE ** 2
GIVEN_IDS = 0
# ------------------------------- setting up pygame --------------------------------------------
pygame.init()
display_height = 600
display_width = 600
game_display = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
# ------------------------------- colours ----------------------------------------------------
white = (255, 255, 255)
black = (0, 0, 0)
blue = (0,0,255)
light_blue = (30, 144, 255)
red = (200, 0, 0)
light_red = (255, 0, 0)
yellow = (200, 200, 0)
light_yellow = (255, 255, 0)
green = (34, 177, 76)
light_green = (0, 255, 0)
# ------------------------------- methods for the game algorythm ------------------------------
def rolling_window(a, size):
# This method is required for the algorythm that broadcasts the board for a win
shape = a.shape[:-1] + (a.shape[-1] - size + 1, size)
strides = a.strides + (a. strides[-1],)
return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
class Chip:
def __init__(self, colour):
if colour == "Blue":
self.colour = colour
if colour == "Red":
self.colour = colour
global GIVEN_IDS
self.iD = GIVEN_IDS
GIVEN_IDS += 1
def get_iD(self):
return self.iD
class Game:
def __init__(self, player_colour="Blue", comp_colour="Red"):
self.board = np.empty(BOARD_BOX_NUM, dtype=Chip)
self.board = self.board.reshape(BOARD_SIZE, BOARD_SIZE)
self.player_colour = player_colour
self.comp_colour = comp_colour
def get_comp_colour(self):
return self.comp_colour
def get_player_colour(self):
return self.player_colour
def give_str_board(self):
"""Returns a copy of the board array and replaces the Chip objects with the str with the colour of the chips."""
this_board = np.copy(self.board)
for x, y in np.ndindex(this_board.shape):
if this_board[x, y] is not None:
if this_board[x, y].colour == "Blue":
this_board[x, y] = "Blue"
else:
this_board[x, y] = "Red"
return this_board
def print_board_in_console(self):
"""This function holds the board which is a 8x8 matrix."""
this_board = self.give_str_board()
print(this_board)
print("-"*40)
def insert_chip(self, chip, col):
"""Method for making a new entry to the board. For the player and enemy.
The column has to be parametrised in the pythonic way. i.e. cols from 0-7."""
# slices the entries of the column into a new array
col_entries = self.board[:, col:col+1]
# checks for all unoccupied pos in this column(entries are None)
# double array of indexes with the form (array([row_i, ...]), array([column_i, ...]))
# checking the condition with "is" is here not possible, because "is" operator cannot be overloaded
none_indexes = np.where(col_entries == None)
# check whether the column cannot contain an extra chip and function has to be aborted
if len(none_indexes[0]) == 0:
print("This column is full. Chose again.")
return False
# the pos where the chip will fall is the one with the highest index
self.board[len(none_indexes[0]) - 1, col] = chip
return True
def get_chip(self, x, y):
"""This function can return the information about a chip in a pos of the board."""
chip = self.board[x, y]
return chip
def is_won(self):
"""This function can be used to check the board on whether the game has been decided.
The function differentiates between player and enemy and returns..."""
winning_chip = None
# get a copy of the board which only contains str and None
this_board = self.give_str_board()
flipped_board = np.fliplr(this_board)
# in order to check the entire board for 4 Chips in a formation individual rows and cols are examined
# use for loops to isolate rows and cols
for this_ax in range(0, 2):
for index in range(0, BOARD_SIZE):
# the stack will contain the row[index] when this_ax = 0 and the col[index] when this_ax = 1
stack = this_board.take(index, axis=this_ax)
# this will be the patterns, that are searched for
winning_formations = [['Blue', 'Blue', 'Blue', 'Blue'], ['Red', 'Red', 'Red', 'Red']]
for i in winning_formations:
bool_array = rolling_window(stack, 4) == i
if [True, True, True, True] in bool_array.tolist():
# the stack_index is the index of the first chip in the 4xChip formation in the row/col
stack_index_tuple, = np.where(np.all(bool_array == [True, True, True, True], axis=1))
stack_index = stack_index_tuple[0]
loop_index = index
# this_ax = 0 means loop_index is row and stack_index is col
if this_ax == 0:
winning_chip = self.get_chip(loop_index, stack_index)
break
else:
winning_chip = self.get_chip(stack_index, loop_index)
break
# This next part of the algorythm checks whether diagonal patterns of the array
# contain a winning formation
# if this bit is problematic: change the 0 in range()!!!
for index in range(0, BOARD_SIZE - 2):
for board in [this_board, flipped_board]:
diag_elements = board.diagonal(index)
for i in winning_formations:
bool_array = rolling_window(diag_elements, 4) == i
if [True, True, True, True] in bool_array.tolist():
# the stack_index is the index of the first chip in the 4xChip formation in the row/col
diag_el_index_tuple, = np.where(
np.all(bool_array == [True, True, True, True], axis=1))
diag_index = diag_el_index_tuple[0]
loop_index = index
# this_ax = 0 means loop_index is row and stack_index is col
if board == this_board:
winning_chip = self.get_chip(loop_index, diag_index)
break
else:
winning_chip = self.get_chip(diag_index, loop_index)
break
if winning_chip is not None:
return winning_chip.colour
return None
def get_comp_move(self):
"""This method generates the computer's move (the column) based on INTELLIGENCE!!!!
Returns the column of the move"""
c_colour = self.get_comp_colour()
p_colour = self.get_player_colour()
# check, if the comp can win in the next move
for i in range(0, BOARD_SIZE):
board = self.give_str_board()
chip = Chip(c_colour)
self.insert_chip(chip, i)
if self.is_won() == c_colour:
return i
# check, if the player can win in the next move and block that position
for i in range(0, BOARD_SIZE):
board = self.give_str_board()
chip = Chip(p_colour)
self.insert_chip(chip, i)
if self.is_won() == p_colour:
return i
# accumulate preferable positions for the next move
good_spots = []
board = self.give_str_board()
for axis in range(0, 2):
for index in range(0, BOARD_SIZE):
# the stack will contain the row[index] when this_ax = 0 and the col[index] when this_ax = 1
stack = board.take(index, axis=axis)
# this will be the patterns, that are searched for
for i in [c_colour, c_colour]:
bool_array = rolling_window(stack, 2) == i
if [True, True] in bool_array.tolist():
# the stack_index is the index of the first chip in the 4xChip formation in the row/col
stack_index_tuple, = np.where(np.all(bool_array == [True, True], axis=1))
stack_index = stack_index_tuple[0]
# this_ax = 0 means loop_index is row and stack_index is col
if axis == 0:
# "- 1" because this if-statement is called when broadcasting a row. i.e. column before
good_spots.append(stack_index - 1)
else:
good_spots.append(index)
# The pick is the x-coo of the first of a series of two chips (column) or the x before (row).
print(good_spots)
pick = random.randint(0, len(good_spots))
return pick
# make a move, "better than nothing"
flag = True
while flag is True:
rnd = random.randint(0, BOARD_SIZE)
if self.board[rnd, 0] is None:
return rnd
# ------------------------------- this part will take care of the visualisation in pygame ------------------------
# buttons = []
#
# def button(self, text, x, y, radius, inactive_colour, active_colour, action=None, size=" "):
# cur = pygame.mouse.get_pos()
# if x + radius > cur[0] > x - radius and y + radius > cur[1] > y - radius:
# pygame.draw.circle(game_display, active_colour, (x, y), radius)
#
# ix = None
# iy = None
# for event in pygame.event.get():
# if event.type == pygame.MOUSEBUTTONDOWN:
# ix, iy = event.pos
#
# if ix is not None and iy is not None:
# if x + radius > ix > x - radius and y + radius > iy > y - radius and action is not None:
# if action == "quit":
# pygame.quit()
# quit()
#
# if action == "move":
# col = int(x / 80 - 90)
# self.insert_chip(Chip(self.get_player_colour()), col)
# else:
# pygame.draw.circle(game_display, inactive_colour, (x, y), radius)
def draw_board(self):
board = self.give_str_board()
pygame.draw.rect(game_display, green, (60, 60, 80*BOARD_SIZE, 80*BOARD_SIZE))
for y in range(0, BOARD_SIZE):
for x in range(0, BOARD_SIZE):
dx = 90 + x * 80
dy = 90 + y * 80
if board[x, y] is None:
pygame.draw.circle(game_display, white, (dy, dx), 30)
elif board[x, y] == "Blue":
pygame.draw.circle(game_display, blue, (dy, dx), 30)
elif board[x, y] == "Red":
pygame.draw.circle(game_display, red, (dy, dx), 30)
# draw the selector square
pygame.draw.rect(game_display, yellow, (self.selector_pos * 80 + 80, 60, 20, 20))
selector_pos = 0
def move_selector(self, dir):
selector_pos = self.selector_pos
if dir == 'left' and selector_pos >= 0:
new_x = selector_pos * 80 - 80
pygame.draw.rect(game_display, yellow, (new_x, 60, 20, 20))
self.selector_pos -= 1
if dir == 'right' and selector_pos <= BOARD_SIZE - 1:
new_x = selector_pos * 80 + 80
pygame.draw.rect(game_display, yellow, (new_x, 60, 20, 20))
self.selector_pos += 1
def intro(self):
return
def game_loop(self, comp_goes_first=False):
game_over = False
while game_over is not True:
# here comes the computer's move
if comp_goes_first is True:
col = self.get_comp_move()
chip = Chip(self.get_comp_colour())
self.insert_chip(chip, col)
# This will be the player move
move_over = False
while move_over is not True:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.move_selector('right')
pygame.draw.rect(game_display, yellow, (50, 50, 50, 50))
if event.key == pygame.K_LEFT:
self.move_selector('left')
if event.key == pygame.K_RETURN:
# the selector position indicates the column which the player has chosen.
col = self.selector_pos
chip = Chip(self.get_player_colour())
move_over = self.insert_chip(chip, col)
game_display.fill(white)
self.draw_board()
pygame.display.update()
comp_goes_first = True
clock.tick(15)
game = Game()
game.game_loop()
Now to the part that particularly leaves me in doubt.
As the following loop runs, I can make the Player's move in the game as expected with the use of arrow keys and return, however then the program goes crazy. It will do multiple moves for the computer and sometimes the player as well. This is a picture of the GUI after the loop has run once (player's move and then the computer's move and now it would be the players move again).
At this point I am wondering whether I got something fundamentally wrong with the while loop construction here and I cannot figure it out. What is the issue?
game_over = False
while game_over is not True:
# here comes the computer's move
if comp_goes_first is True:
col = self.get_comp_move()
chip = Chip(self.get_comp_colour())
self.insert_chip(chip, col)
# This will be the player move
move_over = False
while move_over is not True:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.move_selector('right')
if event.key == pygame.K_LEFT:
self.move_selector('left')
if event.key == pygame.K_RETURN:
# the selector position indicates the column which the player has chosen.
col = self.selector_pos
chip = Chip(self.get_player_colour())
move_over = self.insert_chip(chip, col)
game_display.fill(white)
self.draw_board()
pygame.display.update()
comp_goes_first = True
clock.tick(15)
Your problem looks to me to be in your AI logic. You're making a copy of the board for the AI to experiment on, but then you're not using it, and instead inserting chips into the real board.
# check, if the comp can win in the next move
for i in range(0, BOARD_SIZE):
# Never used.
board = self.give_str_board()
chip = Chip(c_colour)
# inserting onto the real board.
self.insert_chip(chip, i)
print("insert check", board, self)
if self.is_won() == c_colour:
return i

Python program game of life

I am currently trying to make conways game of life in python, I am trying to figure out how to make the program read the black squares as on, however I am having no luck, could anyone help. The onoff print currently just prints everything as off (0's) and I want it to print 1's where there is black squares, in order.
import pygame
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
GREY = (0, 210, 230)
WIDTH = 20
HEIGHT = 20
MARGIN = 1
gridsize = 20
onoff = []
grid = []
for row in range(gridsize):
grid.append([])
for column in range(gridsize): # grid
grid[row].append([])
grid[row][column] = 0 # setting value of pixel to off
for x in range(gridsize*gridsize): #onoff update
onoff.append(grid[row][column])
print(onoff)
pygame.init()
WINDOW_SIZE = [21*gridsize, 21* gridsize]
screen = pygame.display.set_mode(WINDOW_SIZE) # screen size
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:# mosue click detection
pos = pygame.mouse.get_pos()
column = pos[0] // (WIDTH + MARGIN)
row = pos[1] // (HEIGHT + MARGIN)
grid[row][column] = 1
print(onoff)
print("Grid coordinates: ", row, column)
for row in range(gridsize):
for column in range(gridsize):
color = WHITE #grid creation
if grid[row][column] == 1:
color = BLACK
pygame.draw.rect(screen,
color,
[(MARGIN + WIDTH) * column + MARGIN, # black rect
(MARGIN + HEIGHT) * row + MARGIN,
WIDTH,
HEIGHT])
clock.tick(60)
pygame.display.flip()
pygame.quit()
onoff = []
grid = []
for row in range(gridsize):
grid.append([])
for column in range(gridsize): # grid
grid[row].append([])
grid[row][column] = 0 # setting value of pixel to off
onoff.append(grid[row][column])
for x in range(len(grid)):
print(grid[x])
its ok i solved it, thanks anyways

Pygame buttons functionality and correcting grid select mouse function

I've added two rectangles, red and green to the top of the following code, and for some reason my code, which otherwise worked, does not now. The grid cells should go RED when clicked, but the clicking is skewed. Can anyone advise on the problem? I have two issues:
An upvote to the first one to spot and point out the error, unless I get it first!
I also want to add text (user 1 and user 2) to the rectangles and make them clickable. On clicking, the user selects a random grid cell (which turns either red or green)
Code as follows:
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
size = (350, 350)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
done = False
clock = pygame.time.Clock()
width=22
height=22
margin=12
grid=[]
#Loop for each row in the list
for row in range(7):
#for each row, create a list that will represent an entire row
grid.append([])
#loop for each column
for column in range(7):
#add the number zero to the current row
grid[row].append(0)
#set row 1, column 5 to one
#grid[1][3]=1
#print(grid[1][3]) #this is the 2nd row and the 4th element along (0...1 row and 0...1...2....3 Column)
# -------- Main Program Loop -----------
while not done:
#ALL EVENT PROCESSING SHOULD GO BELOW THIS LINE
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#************CODE ADDED HERE**********************
elif event.type == pygame.MOUSEBUTTONDOWN:
#print("user clicked the screen")
pos=pygame.mouse.get_pos()
#x = grid[0]
#y= grid[1]
#print(pos)
#CHANGE THE X and Y screen coordinates as in the comments above to grid coordinates
column=pos[0]//(width+margin+50)
row=pos[1]//(height+margin+60)
#set the location to one (when selected by the mouse)
grid[row][column]=1
#print("User click ", pos, "Grid coordinates:", row+1, column+1)
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(BLACK)
# --- Drawing code should go here
#Drawing the red and Green rectangles
pygame.draw.rect(screen,RED, [0,0,120,50])
pygame.draw.rect(screen,GREEN, [240,0,120,50])
for row in range(7):
#the column number - this refers to the number of columns it will produce. 2, for example, will produce only 2 columns
for column in range(7):
color = WHITE
if grid[row][column] ==1:
color = RED
#****MOVING THE REST OF THE GRID DOWN*****
#the 60 is the margin from the top
#the 50 is the margin from the left
pygame.draw.rect(screen,color,[(margin + width) * column + margin+50, (margin + height) * row + margin+60,width,height])
#*******PRINTING TEXT TO THE SCREEN**********
# Select the font to use, size, bold, italics
#font = pygame.font.SysFont('Calibri', 25, True, False)
#text = font.render("a", True, BLACK)
# Put the image of the text on the screen at 250x250
#screen.blit(text, [25, 25])
# --- This bit updates the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
This is by no means an ideal way to achieve your goal, but I tried to keep the code as consistent with yours as possible. Let me know if you have any questions about how this works. I will do my best to answer quickly.
import pygame
from pygame.locals import *
pygame.init()
# first we define some constants
# doing this will reduce the amount of 'magic' numbers throughout the code
WINWIDTH = 350
WINHEIGHT = 350
WINSIZE = (WINWIDTH, WINHEIGHT)
CELLWIDTH = 22
CELLHEIGHT = 22
CELLSIZE = (CELLWIDTH, CELLHEIGHT)
CELLMARGINX = 12 # number of pixels to the left and right of each cell
CELLMARGINY = 12 # number of pixels to the top and bottom of each cell
SCREENPADX = 60 # number of pixels between the GRID and the left and right of the window
SCREENPADY = 70 # number of pixels between the GRID and the top and bottom of the window
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
DONE = False # is our program finished running?
# information about the two buttons (red and green)
REDBUTTON = (0, 0, 120, 50)
GREENBUTTON = (240, 0, 120, 50)
# create the WINDOW and CLOCK
WINDOW = pygame.display.set_mode(WINSIZE)
pygame.display.set_caption('My Game')
CLOCK = pygame.time.Clock()
CURRENTCOLOR = RED # which color is active
# setting up the GRID
# cells can be accessed by GRID[row][col] ie. GRID[3][4] is the 3rd row and 4th column
# each cell contains [x, y, color]
# where x is the x position on the screen
# y is the y position on the screen
# color is the current color of the cell
GRID = []
for y in range(7):
row = []
for x in range(7):
row.append([x * (CELLWIDTH + CELLMARGINX) + SCREENPADX, y * (CELLHEIGHT + CELLMARGINY) + SCREENPADY, WHITE])
GRID.append(row)
# main loop
while not DONE:
# process all events
for event in pygame.event.get():
if event.type == QUIT: # did the user click the 'x' to close the window
DONE = True
if event.type == MOUSEBUTTONDOWN:
# get the position of the mouse
mpos_x, mpos_y = event.pos
# check if REDBUTTON was clicked
button_x_min, button_y_min, button_width, button_height = REDBUTTON
button_x_max, button_y_max = button_x_min + button_width, button_y_min + button_height
if button_x_min <= mpos_x <= button_x_max and button_y_min <= mpos_y <= button_y_max:
CURRENTCOLOR = RED
# check if GREENBUTTON WAS CLICKED
button_x_min, button_y_min, button_width, button_height = GREENBUTTON
button_x_max, button_y_max = button_x_min + button_width, button_y_min + button_height
if button_x_min <= mpos_x <= button_x_max and button_y_min <= mpos_y <= button_y_max:
CURRENTCOLOR = GREEN
# calculations for clicking cells
mpos_x -= SCREENPADX # mouse position relative to the upper left cell
mpos_y -= SCREENPADY # ^ same
col = mpos_x // (CELLWIDTH + CELLMARGINX) # which cell is the mouse clicking
row = mpos_y // (CELLHEIGHT + CELLMARGINY) # ^ same
# make sure the user clicked on the GRID area
if row >= 0 and col >= 0:
try:
# calculate the boundaries of the cell
cell_x_min, cell_y_min = col * (CELLHEIGHT + CELLMARGINY), row * (CELLWIDTH + CELLMARGINX)
cell_x_max = cell_x_min + CELLWIDTH
cell_y_max = cell_y_min + CELLHEIGHT
# now we will see if the user clicked the cell or the margin
if cell_x_min <= mpos_x <= cell_x_max and cell_y_min <= mpos_y <= cell_y_max:
GRID[row][col][2] = CURRENTCOLOR if event.button == 1 else WHITE
else:
# the user has clicked the margin, so we do nothing
pass
except IndexError: # clicked outside of the GRID
pass # we will do nothing
# logic goes here
# drawing
WINDOW.fill(BLACK)
pygame.draw.rect(WINDOW, RED, REDBUTTON)
pygame.draw.rect(WINDOW, GREEN, GREENBUTTON)
for row in GRID:
for x, y, color in row:
pygame.draw.rect(WINDOW, color, (x, y, CELLWIDTH, CELLHEIGHT))
pygame.display.flip()
CLOCK.tick(60)
pygame.quit()

Python clicking game, updating score

import pygame
from pygame.locals import *
import random
import time
pygame.init()
randomNumber = random.randint(1,600)
randomNumber2 = random.randint(1,600)
x = 0
text = ""
squareCount = 0
beenHere = 0
# colours = (red, green, blue)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
LBLUE = (0, 123, 255)
colour = RED
# Make a window appear
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Square Chase | Score: 0")
screen.fill(LBLUE)
pygame.display.flip()
pygame.time.set_timer(USEREVENT + 1, 1500)
done = False
clock = pygame.time.Clock()
while done == False:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
done = True
if event.type == USEREVENT + 1:
screen.fill(LBLUE)
randomNumber = random.randint(1,625)
randomNumber2 = random.randint(1,420)
mySquare = pygame.draw.rect(screen,colour,(randomNumber,randomNumber2,50,50),5)
squareCount = squareCount + 1
if squareCount == 50:
done == true
pygame.display.flip()
if event.type == pygame.MOUSEBUTTONDOWN:
y, z = pygame.mouse.get_pos()
is_inside = mySquare.collidepoint(y, z)
if is_inside and colour == GREEN:
x = x+1
text = str(x)
pygame.display.set_caption("Square Chase | Score " + text)
colour = RED
elif is_inside:
x = x+1
text = str(x)
pygame.display.set_caption("Square Chase | Score " + text)
colour = GREEN
clock.tick(20)
pygame.quit()
I am aiming to create a game in which the user has to click on a square for their score to increase. They get 50 chances to do this. If they click in the square within the 1.5 seconds the colour of the square changes.
The above code works apart from each time a new square is drawn the user could click on it say 5 times and their score will go up by 5. Any suggestions as to how to get the score to increase by just one? Thanks in advance.
Wish I could just use a comment but I have lack of reputation.
I didn't look through all your code, but your description makes it sound like a simple flag would be able to help you.
Once you recognize it has been clicked, increment the score AND set a boolean.
So in essence you will want something along the lines of
if clicked == false
score = score+1
clicked = true
You will want to clear the flag back to false once another block has appeared.
Wouldn't it be better, if a new square would show up after a successful keypress? That way the game would be more dynamic.
It's easy to change this. Instead of using user events that are called every 1.5 sec, sum the value returned by clock.tick() and when their sum will be greater than 1500 ms, create a new rectangle. This is a better approach, because you can call the method that creates a new square and reset the timer right after a successful keypress.
Some code to get you started:
def new_rect(screen,colour):
screen.fill(LBLUE)
randomNumber = random.randint(1,625)
randomNumber2 = random.randint(1,420)
mySquare = pygame.draw.rect(screen,colour,(randomNumber,randomNumber2,50,50),5)
return mySquare
done = False
clock = pygame.time.Clock()
timer_var = 0
while done == False:
if(timer_var > 1500):
timer_var = 0
mySquare = new_rect(screen,color)
squareCount = squareCount + 1
if squareCount == 50:
done == true
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
y, z = pygame.mouse.get_pos()
is_inside = mySquare.collidepoint(y, z)
if is_inside:
x = x+1
text = str(x)
pygame.display.set_caption("Square Chase | Score " + text)
timer_var = 0
new_rect(screen,colour)
squareCount = squareCount + 1
if squareCount == 50:
done == true
if colour == GREEN:
colour = RED
else:
colour = GREEN
timer_var += clock.tick(20)
pygame.quit()

Categories

Resources