I want to alternate between X's and O's in my tic-tac-toe game. The only problem is that after the initial click which places an O it freezes. It doesn't continue further. I expected that the while loop 'continue' from off the if statement but it's like it doesn't register any more events. Also, I used an alternator which seems to be fine, I'm reasoning that the collation of events restarts but that should just register it??
import matplotlib.pyplot as plt
import pygame
import sys
import pygame
import os
from PIL import Image
pygame.font.init()
size = 320, 240
black = 0, 0, 0
white = 255,255,255
red = 255, 0, 0
x1y1 = [(100, 0), (100, 300)]
x2y2 = [(200, 0), (200, 300)]
x3y3 = [(0, 100), (300, 100)]
x4y4 = [(0, 200), (300, 200)]
ser = []
for a in range(0,3):
for b in range(0,3):
ser.append((a,b))
def centroid(coord1, coord2):
xx = 50
yy = 50
coords = []
for a in range(0,3):
for b in range(0,3):
if a == int(coord1) and b == int(coord2):
coords += tuple([xx + a*100, yy + b*100])
return tuple(coords)
def fourCorners(a,b,length,width):
center = (a, b)
corner3 = (int(a + length/2), int(b + width/2))
corner2 = (int(a + length/2), int(b - width/2))
corner4 = (int(a - length/2), int(b + width/2))
corner1 = (int(a - length/2), int(b - width/2))
return [corner1 ,corner2 ,corner3 ,corner4]
def withinRect(a,b,corners):
if len(corners) != 4:
print('Pass a list parameter of length 4.')
elif int(corners[0][0]) >= int(a) >= int(corners[1][0]) and int(corners[0][1]) >= int(b) >= int(corners[1][1]):
return True
screen = pygame.display.set_mode((300,300))
screen.fill(white)
pygame.draw.line(screen, (0, 0, 128), x1y1[0], x1y1[1], 3)
pygame.draw.line(screen, (0, 0, 128), x2y2[0], x2y2[1], 3)
pygame.draw.line(screen, (0, 0, 128), x3y3[0], x3y3[1], 3)
pygame.draw.line(screen, (0, 0, 128), x4y4[0], x4y4[1], 3)
os.chdir('C:\\Users\\DELL\\Documents\\E-books\\Coding\\Projects')
os.path.abspath("X.png")
ximg = pygame.image.load("X.png")
ximg = pygame.transform.scale(ximg, (80,80))
os.path.abspath("O.png")
oimg = pygame.image.load("O.png")
oimg = pygame.transform.scale(oimg, (80,80))
def insert_x():
global result
result = ()
def alternate():
while True:
yield 0
yield 1
alternator = alternate()
next(alternator)
button = pygame.Rect(0,0,300,300)
while True:
ev = pygame.event.get()
for event in ev:
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
x, y = event.pos
evb = pygame.Rect(x,y,10,10)
for val in ser:
va = tuple([100*x + 10 for x in val])
if (va[0] + 100 >= x >= va[0] and va[1] + 100 >= y >= va[1]):
result += va
if (button.colliderect(evb)):
if next(alternator) == 1:
screen.blit(oimg,[result[0], result[1]])
next(alternator)
pygame.display.flip()
result = ()
continue
elif next(alternator) == 0:
screen.blit(ximg,[result[0], result[1]])
next(alternator)
pygame.display.flip()
result = ()
continue
pygame.display.update()
pygame.display.flip()
continue
insert_x()
The issue is the construct
if next(alternator) == 1:
# [...]
elif next(alternator) == 0:
# [...]
alternator is evaluated in the if statement the 1st time. If it doesn't yield 1 but yield 0, then the condition is not fulfilled and the elif statement is evaluated. But in the elif statement alternator is evaluate a second time and now it yield 1 in any case.
This cause that the elif condition is never fulfilled. The application seems to hang, because in this state neither the if condition nor the elif condition will be fulfilled at any time.
Evaluate alternate once, before the if-elif statement, to solve the issue:
a = next(alternator)
if a == 1:
screen.blit(oimg,[result[0], result[1]])
result = ()
elif a == 0:
screen.blit(ximg,[result[0], result[1]])
result = ()
By the way, the continue statement and the pygame.display.flip() calls in the event loop are superfluous. The event loop will terminate when the message queue is empty and the single pygame.display.flip() call at the end of the main llop is sufficient.
Related
I'm trying to create a Sudoku game in python with a solver included. First of all, for some reason, it doesn't show me the procedure of resolving, the window opens only when the board is solved and secondly when i close the window it returns me that python fatal error :Fatal Python error: pygame_parachute: (pygame parachute) Segmentation Fault
Python runtime state: initialized
That is my code :
import time
import pygame
from random import *
import numpy as np
pygame.init()
pygame.font.init()
LARGEUR, HAUTEUR = 550, 550
WIN = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption('Sudoku Game')
Font1 = pygame.font.SysFont(None, 35)
clock = pygame.time.Clock()
BLANC = (255, 255, 255)
NOIR = (0, 0, 0)
BLEU = (0,0,255)
def gen_grille():
grille = [
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]
]
val_debut = 17
for n in range(val_debut):
lgn = randint(1, 8)
cl = randint(1, 8)
num = randint(1, 9)
while(not is_possible(grille,lgn,cl,num) or grille[lgn][cl] != 0):
lgn = randint(1, 8)
cl = randint(1, 8)
num = randint(1, 9)
grille[lgn][cl]= num;
return list(grille)
def is_possible(grille,lgn,cl,num):
statut = True
for a in range(9):
if (grille[a][cl] == num):
statut = False
for b in range(9):
if (grille[lgn][b] == num):
statut = False
zone_lgn = lgn // 3
zone_cl = cl // 3
for a in range(3):
for b in range(3):
if(grille[zone_lgn*3 + a][zone_cl*3 + b] == num):
statut = False
return statut
gen_grille()
grille = gen_grille()
grid_original = [[grille[x][y] for y in range(len(grille[0]))] for x in range(len(grille))]
def draw_new_vals(WIN, position):
x,y = position[0], position[1]
myfont = pygame.font.SysFont('Comic Sans MS', 35)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if(grid_original[x-1][y-1] != 0):
return
if(event.key == 48):
grille[x-1][y-1] = event.key - 48
pygame.draw.rect(WIN, BLANC, (position[0]*50 + 5, position[0]*50+ 5, 40, 40))
pygame.display.update()
return
if(0 < event.key - 48 <10):
pygame.draw.rect(WIN, BLANC, (position[0]*50 + 5, position[1]*50+ 5, 40, 40))
value = myfont.render(str(event.key-48), True, (0,0,0))
WIN.blit(value, (position[0]*50 +15, position[1]*50))
grille[x-1][y-1] = event.key - 48
pygame.display.update()
return
return
def draw_strt_vals():
for x in range(9):
for y in range(9):
if(0 < grille[x][y] < 10):
num = Font1.render(str(grille[x][y]), True, BLEU)
WIN.blit(num, ((x+1)*50 + 15, (y+1)*50 + 15))
def draw_all():
WIN.fill(BLANC)
draw_grille()
draw_strt_vals()
pygame.display.update()
def draw_grille():
for x in range(10):
pygame.draw.line(WIN, (NOIR), (50 + 50*x, 50), (50 + 50*x, 500), 2)
pygame.draw.line(WIN, (NOIR), (50, 50 + 50*x), (500, 50 + 50*x), 2)
for x in range(10):
if x % 3 == 0:
pygame.draw.line(WIN, (NOIR), (50 + 50*x, 50), (50 + 50*x, 500), 4)
pygame.draw.line(WIN, (NOIR), (50, 50 + 50*x), (500, 50 + 50*x), 4)
solved = 0
def solver(grille):
Font1 = pygame.font.SysFont(None, 35)
for lgn in range(9):
for cl in range(9):
if grille[lgn][cl] == 0:
for num in range(1,10):
if is_possible(grille, lgn, cl, num):
grille[lgn][cl] = num
pygame.draw.rect(WIN, BLANC, ((cl+1)*50 + 5, (lgn+1)*50+ 5,40 ,40))
value = Font1.render(str(num), True, (0,0,0))
WIN.blit(value, ((cl+1)*50 +15,(lgn+1)*50))
pygame.display.update()
solver(grille)
global solved
if(solved == 1):
return
grille[lgn][cl] = 0
pygame.draw.rect(WIN, BLANC, ((lgn+1)*50 + 5, (cl+1)*50+ 5,40 ,40))
pygame.display.update()
return
solved = 1
def main():
pygame.init()
clock.tick(60)
marche = True
for i in range(0, len(grille[0])):
for j in range(0, len(grille[0])):
if(0<grille[i][j]<10):
value = Font1.render(str(grille[i][j]), True, BLEU)
WIN.blit(value, ((j+1)*50 + 15, (i+1)*50 ))
pygame.display.update()
solver(grille)
while marche:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
m_pos = pygame.mouse.get_pos()
draw_new_vals(WIN, (m_pos[0]//50, m_pos[1]//50))
if event.type == pygame.QUIT:
pygame.quit()
return
draw_all()
main()
if __name__ == "__main__":
main()
main()
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
The cells don't behave like they're supposed to, meaning they don't follow the rules. I've tried everything I could think of, but it doesn't work.
The variable "state" is used to store the current states of all the cells (1 if active 0 if not) in the format state[x][y], similarly, "cells" also follow the same format but instead of 1s and 0s, it stores all the sprites, aka cells. The "new_state" is exactly like the state but it stores the states for the next generation. (The next generation is calculated from "state" and stored in "new_state".)
Heres an example of what "state" might look like:
state = [[0,0,0,0,0,0,0,0,0],[0,1,1,1,0,0,0], . . . ]
To calculate how many active neighbors there are next to a cell, I just did a nested for loop, both with range(-1, 2). If i, j are the variables of the for loops, then that would look something like this:
for i in range(-1, 2):
for j in range(-1, 2):
sum += state[x + i][y + j]
sum -= state[x][y]
Anyways, heres the code:
import pygame as pg
pg.init()
ticking = False
# colours
white = (255, 255, 255)
grey = (100, 100, 100)
blue = (0, 0, 255)
black = (0, 0, 0)
drk_blue = (0, 0, 100)
red = (255, 0, 0)
# now the screen
width = 750
height = 500
main_screen = pg.display.set_mode([width, height])
main_screen_rect = main_screen.get_rect()
game_width = width - width // 5
main_screen.fill(black)
game_screen = pg.Surface([game_width, height])
game_screen_rect = game_screen.get_rect()
game_screen.fill(black)
WH_cells = [0, 42]
for x in range(0, game_width, 12):
WH_cells[0] += 1
a = False # This is for toggling the eraser for the cells
# The state says which cells are active and inactive and cells is just a list containing the sprites
state = []
cells = []
new_state = []
# New state is for updating, i.e., it contains the states of the next generation
# imp functions
def logic():
sum_calc()
drawer()
global state, new_state
state = new_state
new_state = blank
def sum_calc():
global new_state
state_len = len(state)
state_len_part = len(state[0])
for x_c in range(1, state_len - 1):
for y_c in range(1, state_len_part - 1):
neigh_sum = 0
for i in range(-1, 2):
for j in range(-1, 2):
if x_c + i < state_len and y_c + j < len(state[x_c + i]):
neigh_sum += state[x_c + i][y_c + j]
neigh_sum -= state[x_c][y_c]
if neigh_sum < 2 or neigh_sum > 3:
new_state[x_c][y_c] = 0
elif neigh_sum == 3:
new_state[x_c][y_c] = 1
def drawer():
state_len = len(new_state)
state_len_part = len(new_state[0])
for x in range(state_len):
for y in range(state_len_part):
if new_state[x][y] != 1:
cells[x][y].Activate(False)
else:
cells[x][y].Activate(True)
# sprites
class Cell(pg.sprite.Sprite):
def __init__(self):
super(Cell, self).__init__()
self.surf = pg.Surface((10, 10))
self.surf.fill(grey)
self.rect = self.surf.get_rect()
self.index = None
def update(self, mouse_pos, eraser):
if self.rect.collidepoint(mouse_pos[0], mouse_pos[1]):
cell_x = self.index[0]
cell_y = self.index[1]
global state
if not eraser:
self.surf.fill(white)
state[cell_x][cell_y] = 1
else: # if eraser
self.surf.fill(grey)
state[cell_x][cell_y] = 0
def Activate(self, yesno):
global new_state
cell_x = self.index[0]
cell_y = self.index[1]
if yesno:
self.surf.fill(white)
new_state[cell_x][cell_y] = 1
else:
self.surf.fill(grey)
new_state[cell_x][cell_y] = 0
all_sprites = pg.sprite.Group()
running = True
# generating the cells and lists
for x in range(0, game_width, 12):
state.append([])
cells.append([])
for y in range(0, height, 12):
x_coord = int(x / 12)
state[x_coord].append(0)
new_cell = Cell()
new_cell.rect.x = x
new_cell.rect.y = y
new_cell.index = (x_coord, int(y / 12))
cells[x_coord].append(new_cell)
all_sprites.add(new_cell)
game_screen.blit(new_cell.surf, (x, y))
sprite_list = all_sprites.sprites()
sprite_list_len = len(sprite_list)
new_state = state
blank = state
while running:
if ticking:
logic()
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_a:
a = not a
if event.key == pg.K_SPACE:
if ticking:
ticking = not ticking
else:
ticking = True
print("ticking toggled to: ", ticking)
if event.type == pg.MOUSEMOTION or pg.mouse.get_pressed()[0]:
if pg.mouse.get_pressed()[0]:
for sprites in all_sprites:
sprites.update(pg.mouse.get_pos(), a)
for sprites in sprite_list:
game_screen.blit(sprites.surf, (sprites.rect.x, sprites.rect.y))
main_screen.blit(game_screen, (0, 0))
pg.display.update(main_screen_rect)
fps = pg.time.Clock()
fps.tick(60)
An assignment operation like new_state = state doesn't generate a new object. After this expression, you have 2 variables that refer to the same object.
Actually you have just 1 grid of states. The variables state, new_state and blank refer to the same object. You must create a new and empty state grid in each frame:
def logic():
global state, new_state
new_state = [[0 for _ in row] for row in state]
sum_calc()
drawer()
state = new_state
Furthermore, your algorithm is not correct. See Conway's Game of Life. Change the lgoic:
def sum_calc():
global new_state
state_len = len(state)
state_len_part = len(state[0])
for x_c in range(1, state_len - 1):
for y_c in range(1, state_len_part - 1):
neigh_sum = 0
for i in range(-1, 2):
for j in range(-1, 2):
if x_c + i < state_len and y_c + j < len(state[x_c + i]):
neigh_sum += state[x_c + i][y_c + j]
neigh_sum -= state[x_c][y_c]
#if neigh_sum < 2 or neigh_sum > 3:
# new_state[x_c][y_c] = 0
#elif neigh_sum == 3:
# new_state[x_c][y_c] = 1
if state[x_c][y_c] == 1 and (neigh_sum == 2 or neigh_sum == 3):
new_state[x_c][y_c] = 1
elif state[x_c][y_c] == 0 and neigh_sum == 3:
new_state[x_c][y_c] = 1
else:
new_state[x_c][y_c] = 0
I want to change different variables in my code while it's running, for example changing the variable speed = 1 to speed = 2 using the CMD. The variable I want to change is decided on the person running the code through an input(). They type in speed, and the variable speed changes to another number, also chosen by the person running the code through another input().
To change the values, you should need to-
.
Press Enter, to pause the game
Select the CMD window
Type 'setvar', then Enter
Type 'speed', then Enter
Type '5', then Enter
.
I want this to change speed = 1 to speed = 5, but I also want to be able to do this with every variable, being able to change the score variable, or anything else. So far, I have made it so you input the variable you want to change, and what you want to change it to. The code is slightly messy, but readable.
So far I have tried
exec("%s = %s" % (var,setTo))
and
exec(f"{var} = '{setTo}'")
But it hasn't worked, although speed = 5 does.
The code I want help with is near the bottom. The whole code is...
def RUN():
import pygame
import time
import random
import msvcrt as m
pygame.init()
dis_width = 800
dis_height = 600
score = 0
x = 375
y = 275
foodx = -100
foody = -100
speed = 1
stanima = 0
gotox = 200
gotoy = 200
gotoSet = []
goto = []
gotoSet.append(gotox)
gotoSet.append(gotoy)
goto.append(gotoSet)
people = []
numOfPeople = 1 # Number of people
foodEaten = True
foodRun = True
speedRunPlus = True
speedRunMinus = True
runningRun = True
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
dis = pygame.display.set_mode((dis_width, dis_height)) #screen stuff
pygame.display.set_caption('Game')
game_over = False
running = True
lightBlue = (50, 153, 213) #colors
red = (255, 100, 0)
yellow = (255, 255, 102)
blue = (70, 70, 255)
green1 = (0, 255, 0)
green2 = (0, 255, 25)
green3 = (0, 255, 50)
green4 = (0, 255, 75)
green5 = (0, 255, 100)
green6 = (0, 255, 125)
green7 = (0, 255, 150)
green8 = (0, 255, 175)
green9 = (0, 255, 200)
green10 = (0, 255, 225)
dis.fill(blue) #Backround
pygame.draw.rect(dis, lightBlue, [50, 50, 700, 500]) #Inner rectangle
def update_fps():
fps = str(int(clock.get_fps()))
fps = str("FPS: "+fps)
fps_text = font.render(fps, 1, pygame.Color("coral"))
return fps_text
def speedRender():
speed_str = str(speed)
speed_sentance = str("Average Speed: "+speed_str)
speed_text = font.render(speed_sentance, 1, pygame.Color("coral"))
return speed_text
def player(x, y, color, stamina): #Rectangle player
player = pygame.draw.rect(dis, color, [x, y, 25, 25])
if stanima == 1:
pygame.draw.rect(dis, red, [x+11, y+11, 3, 3])
elif stanima == 2:
pygame.draw.rect(dis, red, [x+10, y+10, 5, 5])
elif stanima == 3:
pygame.draw.rect(dis, red, [x+9, y+9, 7, 7])
elif stanima == 4:
pygame.draw.rect(dis, red, [x+8, y+8, 9, 9])
elif stanima == 5:
pygame.draw.rect(dis, red, [x+7, y+7, 11, 11])
elif stanima == 6:
pygame.draw.rect(dis, red, [x+6, y+6, 13, 13])
elif stanima == 7:
pygame.draw.rect(dis, red, [x+5, y+5, 15, 15])
elif stanima == 8:
pygame.draw.rect(dis, red, [x+4, y+4, 17, 17])
elif stanima == 9:
pygame.draw.rect(dis, red, [x+3, y+3, 19, 19])
def food(foodx, foody): #Rectangle food
food = pygame.draw.rect(dis, yellow, [foodx, foody, 10, 10])
for num1 in range(numOfPeople):
x = random.randint(300,400)
y = random.randint(300,400)
person = []
person.append(x)
person.append(y)
person.append(1)
person.append(goto)
person.append(score)
people.append(person)
while not game_over:
while running:
dis.fill(blue)
pygame.draw.rect(dis, lightBlue, [50, 50, 700, 500])
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
game_over = True
for num2 in range(numOfPeople):
x = people[0][0]
y = people[0][1]
#speed = people[0][2]
goto = people[0][3]
score = people[0][4]
del people[0]
if x+12 > foodx+5: # "AI"
x -= speed
elif x+12 < foodx+5:
x += speed
if y+12 > foody+5: # "AI"
y -= speed
elif y+12 < foody+5:
y += speed
if x > 725: #Creates Borders
x = 725
game_over = True
elif x < 50:
x = 50
game_over = True
if y > 525:
y = 525
game_over = True
elif y < 50:
y = 50
game_over = True
if x >= foodx-24 and x <= foodx+10:
if y >= foody-24 and y <= foody+10:
score += 1
foodEaten = True
#print("Score:", score)
person = []
person.append(x)
person.append(y)
person.append(1)
person.append(goto)
person.append(score)
people.append(person)
playerColor = green1
player(x, y, playerColor, stanima) #Creating Player
if foodEaten == True:
foodx = random.randint(90, 700)
foody = random.randint(90, 500)
stanima += 1
foodEaten = False
food(foodx, foody) #Creating Food
pressed = pygame.key.get_pressed() #Key Movement
if pressed[pygame.K_RCTRL]:
dis.blit(update_fps(), (10,0))
dis.blit(speedRender(), (100,0))
if pressed[pygame.K_SPACE]:
RUN()
if pressed[pygame.K_ESCAPE]:
running = False
game_over = True
if pressed[pygame.K_RSHIFT]:
if foodRun == True:
foodx = random.randint(90, 700)
foody = random.randint(90, 500)
stanima += 1
foodEaten = False
foodRun = False
else:
foodRun = True
if pressed[pygame.K_RETURN]:
if runningRun == True:
running = False
runningRun = False
print(" ")
else:
runningRun = True
if pressed[pygame.K_MINUS]:
if speedRunMinus == True:
speed -= 0.1
speedRunMinus = False
else:
speedRunMinus = True
if pressed[pygame.K_EQUALS]:
if speedRunPlus == True:
speed += 0.1
speedRunPlus = False
else:
speedRunPlus = True
pygame.display.flip() #updating screen
clock.tick()
if not game_over:
command = input(" :")
commandSplit = command.split(".")
#try:
if commandSplit[0] == "return":
var = input(" :")
if var in dir():
print(" :", eval(var), sep='')
else:
print(" :Variable Not Found")
elif commandSplit[0] == "run":
if commandSplit[1] == "exit":
running = False
game_over = True
elif commandSplit[0] == "setvar":
var = input(" :")
print("Var value now:", eval(var), sep='')
if var in locals():
setTo = input("Change variable to:") #Code I need help with -----------------------
print("Var value after:", eval(var), sep='')
else:
print(" :Invalid Syntax Error")
'''
except Exception:
print(" :Invalid Syntax Error")
pass
'''#to implement later
RUN()
I want to alternate between X's and O's in pygame. I have made a while loop that should restart if the image has been blitted. It's just that it keeps returning the same image instead of alternating to X or O. I can't seem to find what's wrong. I have involved the use of next(alternator) to split the decision between X and O.
import matplotlib.pyplot as plt
import pygame
import sys
import pygame
import os
from PIL import Image
pygame.font.init()
size = 320, 240
black = 0, 0, 0
white = 255,255,255
red = 255, 0, 0
x1y1 = [(100, 0), (100, 300)]
x2y2 = [(200, 0), (200, 300)]
x3y3 = [(0, 100), (300, 100)]
x4y4 = [(0, 200), (300, 200)]
ser = []
for a in range(0,3):
for b in range(0,3):
ser.append((a,b))
def centroid(coord1, coord2):
xx = 50
yy = 50
coords = []
for a in range(0,3):
for b in range(0,3):
if a == int(coord1) and b == int(coord2):
coords += tuple([xx + a*100, yy + b*100])
return tuple(coords)
def fourCorners(a,b,length,width):
center = (a, b)
corner3 = (int(a + length/2), int(b + width/2))
corner2 = (int(a + length/2), int(b - width/2))
corner4 = (int(a - length/2), int(b + width/2))
corner1 = (int(a - length/2), int(b - width/2))
return [corner1 ,corner2 ,corner3 ,corner4]
def withinRect(a,b,corners):
if len(corners) != 4:
print('Pass a list parameter of length 4.')
elif int(corners[0][0]) >= int(a) >= int(corners[1][0]) and int(corners[0][1]) >= int(b) >= int(corners[1][1]):
return True
screen = pygame.display.set_mode((300,300))
screen.fill(white)
pygame.draw.line(screen, (0, 0, 128), x1y1[0], x1y1[1], 3)
pygame.draw.line(screen, (0, 0, 128), x2y2[0], x2y2[1], 3)
pygame.draw.line(screen, (0, 0, 128), x3y3[0], x3y3[1], 3)
pygame.draw.line(screen, (0, 0, 128), x4y4[0], x4y4[1], 3)
os.chdir('C:\\Users\\DELL\\Documents\\E-books\\Coding\\Projects')
os.path.abspath("X.png")
ximg = pygame.image.load("X.png")
ximg = pygame.transform.scale(ximg, (80,80))
os.path.abspath("O.png")
oimg = pygame.image.load("O.png")
oimg = pygame.transform.scale(oimg, (80,80))
def insert_x():
global result
result = ()
def alternate():
while True:
yield 0
yield 1
alternator = alternate()
next(alternator)
button = pygame.Rect(0,0,300,300)
while True:
ev = pygame.event.get()
for event in ev:
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
x, y = event.pos
evb = pygame.Rect(x,y,10,10)
for val in ser:
va = tuple([100*x + 10 for x in val])
if (va[0] + 100 >= x >= va[0] and va[1] + 100 >= y >= va[1]):
result += va
if (button.colliderect(evb)):
if next(alternator) == 1:
screen.blit(oimg,[result[0], result[1]])
next(alternator)
pygame.display.flip()
result = ()
continue
elif next(alternator) == 0:
screen.blit(ximg,[result[0], result[1]])
next(alternator)
pygame.display.flip()
result = ()
continue
pygame.display.update()
pygame.display.flip()
continue
insert_x()
The problem is syncronised calling of next(alternator).
Given it yields 0/1/0/1/... forever, calling it twice resets is back to the same value - that is, it causes it to skip the second value.
Consider the code:
def alternate():
while True:
yield 0
yield 1
alternator = alternate()
next(alternator)
for i in range( 10 ):
if ( next(alternator) == 1 ):
print("O ", end='')
next(alternator)
elif ( next(alternator) == 0 ):
print("X ", end='')
next(alternator)
print("")
Which outputs:
OOOOOOOOOO
And then consider this alternative:
for i in range( 10 ):
alt = next(alternator)
if ( alt == 1 ):
print("o", end='')
elif ( alt == 0 ):
print("x", end='')
print("")
Which outputs:
oxoxoxoxox
The alternator is a pretty interesting way of handling this flip-flopping value though, I like it.
I want that when I click on one of the possible squares an X is printed.
I have made a list of all the coordinates of the tic-tac-toe grid. I've also added the centre points of each of the rectangles coordinates. I'm trying to make that if I click within the area of one of the squares that the an X button shows up. The eventual aim is to make that a double-click results in a lodged result.
import matplotlib.pyplot as plt
import pygame
import sys
import pygame
pygame.font.init()
size = 320, 240
black = 0, 0, 0
white = 255,255,255
red = 255, 0, 0
x1y1 = [(100, 0), (100, 300)]
x2y2 = [(200, 0), (200, 300)]
x3y3 = [(0, 100), (300, 100)]
x4y4 = [(0, 200), (300, 200)]
def centroid(coord1, coord2):
xx = 50
yy = 50
coords = []
for a in range(0,3):
for b in range(0,3):
if a + 1 == int(coord1) and b + 1 == int(coord2):
coords += tuple([xx + a*100, yy + b*100])
return tuple(coords)
def fourCorners(a,b,length,width):
center = (a, b)
corner3 = (int(a + length/2), int(b + width/2))
corner2 = (int(a + length/2), int(b - width/2))
corner4 = (int(a - length/2), int(b + width/2))
corner1 = (int(a - length/2), int(b - width/2))
return [corner1 ,corner2 ,corner3 ,corner4]
def withinRect(a,b,corners):
if len(corners) != 4:
print('Pass a list parameter of length 4.')
elif int(corners[0][0]) >= int(a) >= int(corners[1][0]) and int(corners[0][1]) >= int(b) >= int(corners[1][1]):
return True
screen = pygame.display.set_mode((300,300))
screen.fill(white)
pygame.draw.line(screen, (0, 0, 255), x1y1[0], x1y1[1], 3)
pygame.draw.line(screen, (0, 0, 255), x2y2[0], x2y2[1], 3)
pygame.draw.line(screen, (0, 0, 255), x3y3[0], x3y3[1], 3)
pygame.draw.line(screen, (0, 0, 255), x4y4[0], x4y4[1], 3)
while True:
ev = pygame.event.get()
for event in ev:
# handle get_pressed
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
x, y = event.pos
v = fourCorners(centroid(1,1)[0],centroid(1,1)[1],100,100)
button = pygame.Rect(v[1][0], v[1][1] ,100,100)
if (withinRect(x,y,v) == True and button.collidepoint(event.pos)):
print('X')
pygame.display.flip()
else:
break
pygame.display.flip()
Traverse all the 9 fields by 2 nested loos and define a pygame.Rect for the corresponding field:
for a in range(3):
for b in range(3):
button = pygame.Rect(a*100, b*100, 100, 100)
If you want you can define a margin, to limit the area to the center of a field:
margin = 4
button = pygame.Rect(a*100+margin, b*100+margin, 100-2*margin, 100-2*margin)
Use colliderect() to check if the click was inside the area:
if button.collidepoint(pos):
# [...]
Draw a line from the .bottomleft to the .topright and a line from the .topleft to the .bottomright, to form a cross:
pygame.draw.line(screen, (0, 0, 255), button.bottomleft, button.topright, 3)
pygame.draw.line(screen, (0, 0, 255), button.topleft, button.bottomright, 3)
ev = pygame.event.get()
for event in ev:
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
margin = 4
for a in range(3):
for b in range(3):
button = pygame.Rect(a*100+margin, b*100+margin, 100-2*margin, 100-2*margin)
if button.collidepoint(pos):
pygame.draw.line(screen, (0, 0, 255), button.bottomleft, button.topright, 3)
pygame.draw.line(screen, (0, 0, 255), button.topleft, button.bottomright, 3)