Now, excuse if this is in the forum forum, even though I use a GUI, I don't beleive that's what's causing the problem.
The title makes this a little more confusing so let me explain.
I if do
This is how I do it:
Why does this happen?
Is it the way I use lambda or the way I detect if a button is clicked?
Thanks in advance,
Dream
the full script can be found here: https://pastebin.com/yh5jxHFU
Full code
The title makes this a little more confusing so let me explain.
I if do
a = lambda: some_function(16)then call 'a' (I do this when a button is clicked, but that's beside the point). And 'some_function' is:
def some_function(some_number): print(some_number)the output should be
Output:>12
Then when 'a' is called again, it should again print Output:>12
However, with my code, I call 'a' once, and like expected it prints '12'. I then call it again, but this time, instead of printing '12' once, it print it twice. Like this:Output:#called once for 1st time
>12
#called once for 2nd time
>12
>12
#called once for 3rd time
>12
>12
>12
.....
Even though the example is what happens, I will explain it with my real code, as it slightly different. When a button is pressed, a random number 1 through 6 is picked. When another button is pressed, it will call a function with parameters of either "P1" meaning player 1 or "P2" meaning player 2 and the random number. The player is changed every go (e.g. You press the button, a number is generated, you move your character. It becomes player 2's go. Player 2 does the same thing, it's now player 1's go). This is how I do it:
a = lambda: self.move_players("P1" if self.currPl == 1 else "P2", random_number) #self.currPl evaluates to either 1 or two.Now, on the first go, if player 1 rolles a 3, the function is called like
self.move_players("P1", 3)Fine - it works. Then it becomes player 2's go. Let's say player 2 roll a 5, the function is, again, called like
self.move_players("P2", 5)However, here lies the problem: if in the 'self.move_playersI(self, players, spaces)' function I do 'print(players, spaces)'. On player 1's first go it says
Output:>P1, 3
Then on player 2's go it says Output:>P2, 3
>P2, 5
Remember how player 1 rolled a 3. It calls the function once with player 1's value for player 2, then again this time with player 2's actuall value. In some cases, this means player 2 moves double the intended spaces.Why does this happen?
Is it the way I use lambda or the way I detect if a button is clicked?
Thanks in advance,
Dream
the full script can be found here: https://pastebin.com/yh5jxHFU
Full code
import sys from PyQt5 import QtWidgets from PyQt5 import QtCore from PyQt5 import QtGui from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * import time import random from guiLoop import guiLoop from functools import partial class Settings(): SCENE_SIZE_X = 1200 #Settings for everything SCENE_SIZE_Y = 900 GRID_COUNT_X = 4 GRID_COUNT_Y = 5 GRID_COUNT_TOTAL = GRID_COUNT_X * GRID_COUNT_Y GRID_BOX_WIDTH = 100 GRID_BOX_HEIGHT = 100 DEF_FONT_SIZE = 15 DEF_PLAYER_SIZE = 25 DEF_LEFT_PADDING = 5 P1_TOP_PADDING = 10 P2_TOP_PADDING = DEF_PLAYER_SIZE * 2 + 10 ROLL_TIME = 20 class Drawing(): p1 = QPen(QColor(66, 134, 244), 1, Qt.SolidLine) #p1 blue, #4286f4 brushP1 = QBrush(QColor(66, 134, 244), Qt.SolidPattern) p2 = QPen(QColor(244, 65, 65), 1, Qt.SolidLine) #p2 red, #f44141 brushP2 = QBrush(QColor(244, 65, 65), Qt.SolidPattern) transparent = QPen(QColor(255, 255, 255), 1, Qt.SolidLine) transparentB = QBrush(QColor(255, 255, 255), Qt.SolidPattern) class Grid(QtWidgets.QGraphicsScene): def __init__(self): super().__init__() self.scrolled = 0 self.ps = Players() self.texts = [] self.initUI() def initUI(self): self.draw_grid(Settings.GRID_COUNT_X, Settings.GRID_COUNT_Y, Settings.GRID_BOX_WIDTH, Settings.GRID_BOX_HEIGHT) #drawing grid first self.draw_text(Settings.GRID_COUNT_X, Settings.GRID_COUNT_Y, Settings.GRID_BOX_WIDTH, Settings.GRID_BOX_HEIGHT, Settings.DEF_FONT_SIZE) #drawing text next rect = self.ps.draw_players("P1", 0) self.addRect(rect[0], Drawing.p1, Drawing.brushP1) rect = self.ps.draw_players("P2", 0) self.addRect(rect[1], Drawing.p2, Drawing.brushP2) def draw_grid(self, x_count, y_count, x_size, y_size): width = x_count * x_size height = y_count * y_size self.setSceneRect(0, 0, width, height) self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex) pen = QPen(QColor(0,0,0), 1, Qt.SolidLine) for x in range(0,x_count+1): for y in range(0,y_count+1): #nested for loop for x and y (0,0) - (0,1) - (0,2) etc xc = x * x_size yc = y * y_size self.addLine(xc,0,xc,height,pen) self.addLine(0,yc,width,yc,pen) def draw_text(self, x_count, y_count, x_size, y_size, font_size): font = QFont("Courier New", font_size, QFont.Bold) total = Settings.GRID_COUNT_TOTAL row_count = Settings.GRID_COUNT_Y text_pos_ev = [] text_pos_od = [] for y in range(0,y_count): #another nested for loop with out the +1 to y and x count for x in range(0,x_count): xcTEXT = x * x_size ycTEXT = y * y_size if row_count % 2 == 0: #if the row is even text_pos_ev.append([xcTEXT, ycTEXT, total]) #add to even array else: text_pos_od.append([xcTEXT, ycTEXT, total]) #otherwise add to odd array total = total - 1 row_count = row_count - 1 for pos in text_pos_ev: #draws the even numbers text = self.addText(str(pos[2]), font) self.texts.append(text) text.setPos(pos[0], pos[1]) text.setOpacity(0.6) new_text_pos_od = reverse_section(text_pos_od, 4) #flips the odd numbers so they snake around the board for pos in new_text_pos_od: #draws new odd numbers text = self.addText(str(pos[2]), font) self.texts.append(text) text.setPos(pos[0], pos[1]) text.setOpacity(0.6) def move_players(self, player, spaces): rect = [] if(player == "P1"): self.remove_player("P1") rect = self.ps.draw_players("P1", spaces) self.addRect(rect[0], Drawing.p1, Drawing.brushP1) elif(player == "P2"): self.remove_player("P2") rect = self.ps.draw_players("P2", spaces) self.addRect(rect[1], Drawing.p2, Drawing.brushP2) def remove_player(self, player): rect = self.ps.clear_old_player(player) self.addRect(rect, Drawing.transparent, Drawing.transparentB) self.redraw_text() def redraw_text(self): for text in self.texts: self.removeItem(text) del self.texts[:] self.draw_text(Settings.GRID_COUNT_X, Settings.GRID_COUNT_Y, Settings.GRID_BOX_WIDTH, Settings.GRID_BOX_HEIGHT, Settings.DEF_FONT_SIZE) class Players(QRectF): def __init__(self): super().__init__() self.poses = [] self.row_count = 0 self.p1 = QRectF() self.p2 = QRectF() self.p1pos = 0 self.p2pos = 0 self.initUI() def initUI(self): self.gen_pos_arr() def draw_players(self, player, spaces): #space 1 is box 1, 2 is box 2, 3 is box 3.. if(player == "P1"): self.p1pos += spaces; elif(player == "P2"): self.p2pos += spaces; self.p1 = QRectF(self.poses[self.p1pos][0] + Settings.DEF_LEFT_PADDING, self.poses[self.p1pos][1] + Settings.P1_TOP_PADDING, Settings.DEF_PLAYER_SIZE, Settings.DEF_PLAYER_SIZE) self.p2 = QRectF(self.poses[self.p2pos][0] + Settings.DEF_LEFT_PADDING, self.poses[self.p2pos][1] + Settings.P2_TOP_PADDING, Settings.DEF_PLAYER_SIZE, Settings.DEF_PLAYER_SIZE) return [self.p1, self.p2] def clear_old_player(self, player): pos = [] if(player == "P1"): pos = self.poses[self.p1pos] pos[0] += Settings.DEF_LEFT_PADDING pos[1] += Settings.P1_TOP_PADDING elif(player == "P2"): pos = self.poses[self.p2pos] pos[0] += Settings.DEF_LEFT_PADDING pos[1] += Settings.P2_TOP_PADDING return QRectF(pos[0], pos[1], Settings.DEF_PLAYER_SIZE, Settings.DEF_PLAYER_SIZE) def gen_pos_arr(self): y = Settings.GRID_COUNT_Y-1 for i in range(1, Settings.GRID_COUNT_Y+1): if(y % 2 == 0): for x in range(0, Settings.GRID_COUNT_X): self.poses.append([x*Settings.GRID_BOX_WIDTH,y*Settings.GRID_BOX_HEIGHT]) else: for x in range(Settings.GRID_COUNT_X-1, -1, -1): self.poses.append([x*Settings.GRID_BOX_WIDTH,y*Settings.GRID_BOX_HEIGHT]) y = y - 1 class App(QtWidgets.QDialog): def __init__(self): super().__init__() self.images = ['1.png','2.png','3.png','4.png','5.png','6.png'] self.image = QLabel(self) self.currTurn = "<font color='#4286f4'>Player 1's turn</font>" self.turn = QLabel(self) self.roll = QPushButton("Roll!") self.move = QPushButton("Move player") self.currPl = 1 self.vbox1 = QVBoxLayout() self.vbox2 = QVBoxLayout() self.grid = Grid() self.initUI() def initUI(self): self.setGeometry(300, 100, Settings.SCENE_SIZE_X, Settings.SCENE_SIZE_Y) self.setWindowTitle("NEA Board Game") self.layout() @guiLoop def move_players(self, players, spaces): temp = 0 print(players, spaces) self.move.setEnabled(False) self.turn.setText(self.currTurn) #self.grid.move_players(players, spaces) if(self.currPl == 1): while(temp < spaces): self.grid.move_players("P1", 1) temp += 1 yield 0.5 else: while(temp < spaces): self.grid.move_players("P2", 1) temp += 1 yield 0.5 if(self.currPl == 1): self.currPl = 2 self.currTurn = "<font color='#f44141'>Player 2's turn</font>" self.turn.setText(self.currTurn) elif(self.currPl == 2): self.currPl = 1 self.currTurn = "<font color='#4286f4'>Player 1's turn</font>" self.turn.setText(self.currTurn) self.roll.setEnabled(True) spaces = 0 def layout(self): gridGview = QtWidgets.QGraphicsView(self.grid) d = self.dice() layout = QGridLayout(self) layout.addWidget(d[1], 2, 1) layout.addWidget(d[0], 1, 1) layout.addWidget(gridGview, 0, 1) def dice(self): rollBox = QGroupBox("") font = QtGui.QFont("Courier New", 23, QtGui.QFont.Bold) self.roll.clicked.connect(self.diceRoll) self.turn.setText(self.currTurn) self.turn.setFont(font) self.turn.setAlignment(QtCore.Qt.AlignCenter) self.vbox1.addWidget(self.turn) self.vbox1.addWidget(self.roll) rollBox.setLayout(self.vbox1) diceBox = QGroupBox("") self.vbox2.addWidget(self.move) self.move.setEnabled(False) diceBox.setLayout(self.vbox2) return [rollBox, diceBox] @guiLoop def diceRoll(self, argument): temp = 0 rollT = Settings.ROLL_TIME self.roll.setEnabled(False) while(temp <= rollT): yield ((temp * 0.02) + 0.05) img = random.choice(self.images) pixmap = QPixmap(img) self.image.setPixmap(pixmap) self.vbox2.addWidget(self.image) temp += 1 self.move.setEnabled(True) a = lambda: self.move_players("P1" if self.currPl == 1 else "P2", int(img[0:1])) self.move.clicked.connect(a) def reverse_section(arr, subsection): ml2 = [ (arr[i*subsection:(i+1)*subsection]) for i in range(int(len(arr)/subsection)) ] ml3 = [ sl[i][0:subsection-2] + [sl[len(sl)-i-1][2]] for sl in ml2 for i in range(len(sl)) ] return ml3 if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) app.setStyle("Fusion") ex = App() ex.show() sys.exit(app.exec_())