Create Buttons and it's signals dynamically in Ruby GTK - ruby

i'm trying to make a Nurikabe puzzle with Ruby GTK and i'm having trouble creating button signals dynamically.
Basically, i have a matrix, some boxes have a number ( clicking them won't do anything), others can have one of 3 states (white, black or unplayed). The matrix can have different sizes so i did this :
def construction
# we get the width and height of the matrix
taille_hauteur = ##partie.grilleEnCours.hauteur
taille_largeur = ##partie.grilleEnCours.largeur
#boutons = {}
#We create a table which will include all of our buttons (one for each box of our matrix)
table = Table.new(taille_hauteur,taille_largeur,false)
# we go through our matrix
for i in 0..taille_largeur-1
for j in 0..taille_hauteur-1
# if the box has a number, we create a button with that number as a label
if ##partie.grilleEnCours.matriceCases[i][j].is_a?(CaseNombre)
# we add this button to a hash
#boutons[[i,j]] = Button.new(:label=> ##partie.grilleEnCours.matriceCases[i][j].to_s)
table.attach(#boutons[[i,j]], i, i+1, j, j+1)
else
# otherwise,we create and add a button to the hash without a label
#boutons[[i,j]] = Button.new()
# we create a signal, changing the state of the box of the matrix at the same coordinates as the button
#boutons[[i,j]].signal_connect('clicked'){
puts "#{i} #{j}"
# we change the box's state of the matrix
##partie.clicSurCase(i,j)
puts ##partie.grilleEnCours
# here we are just changing the label corresponding to the box's state
if(##partie.grilleEnCours.matriceCases[i][j].etat==0)
lab = ""
elsif (##partie.grilleEnCours.matriceCases[i][j].etat==1)
lab = "Noir"
else
lab = "Point"
end
#boutons[[i,j]].set_label(lab)
}
table.attach(#boutons[[i,j]], i, i+1, j, j+1)
end
end
end
#object.add(table)
end
The problem is, doing this, when we click any button, it will change the last box of the matrix and the last button's label (bottom right). I believe this is because Integers are objects in Ruby so clicking a button will change the box's state and button's state at the coordinates (i,j) (which are matrix height-1, matrix width-1) and not the values i and j had when we created the signal.
I have no idea how to link a button to a specific box of the matrix (knowing matrixes can have multiple sizes), could you help me on this one ?

It is quite hard to read such a large block of code - maybe start by chopping it into logic-based functions?
It will clear the code up.
you don't need to set "lab =" in each branch of if - just:
lab = if (i==1)
1
else
2
end
in additions - use "case" in this case. Once you split the code up - you will(probably) find the issue you have.
it will be easier to debbug.

Related

How can I make a GUI that shows how many bricks i have collected?

Each brick in my game has a value, and it gets added to leaderstats. But, I want a GUI to show how many BRICKS they have collected. For example, 2 bricks in my game are worth 32 points to be stored in leaderstats. Instead of showing the total, 64, i want it to show the amount of bricks i collected: 2.
Here is the code that collects the bricks and stores them in leaderstats:
script.Parent.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") ~= nil then
if db == true then
db = false
script.Parent.Transparency = 1
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
player.leaderstats.ElectoralVotes.Value = player.leaderstats.ElectoralVotes.Value + 37.5
script.Sound:Play()
wait(1)
script.Parent:Remove()
end
end
end)
I want to keep the leaderstats in the top right, but on the screen i also want it to show the amount of bricks collected. Does anyone know how i could implement this into my game?
make a Main GUi and insert an TextLabel inside it insert Int value and a script and put the MainGUI in The Starter Gui Pack
next type the below code in the script if TextLabel:
local my_text_gui = script.Parent.TextLabel
local brick_count = my_gui.IntValue
local function change_value()
my_text_gui.Text = brick_count.Value
brick_count:GetPropertyChangedSignal("Value"):Connect(change_value())
Then change the touch detection script and add a value adding code given bellow(works only when the touch detection script is not a local script)
script.Parent.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") ~= nil then
if db == true then
db = false
script.Parent.Transparency = 1
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
player.leaderstats.ElectoralVotes.Value = player.leaderstats.ElectoralVotes.Value + 37.5
hit.Parent.PlayerGui.Your_Brick_Counter_GUI.IntValue = hit.Parent.PlayerGui.Your_Brick_Counter_GUI.IntValue + 1
script.Sound:Play()
wait(1)
script.Parent:Remove()
end
end
end)
Thanks!

Trouble building tree for possible chess piece movements

I'm building a chess game that takes a start coordinate and end coordinate and builds a tree using BFS. I have two methods to find possible moves.
The #find_possible_positions_from_origin method logs every single possible square that chess piece can end up (for example a rook can end up either, north up to 7 spaces, south up to 7 spaces, left up to 7 spaces, and right up to 7 spaces. If the end coordinate ends up BEING one of these coordinates from #find_possible_positions_from_origin, it then runs another method directly under it #find_possible_incremental_moves that traverses every single one of these spaces by only 1 space at a time - the reason being so that it can check if each space is empty, and not just hop over another piece. It creates a "cell" on each of these spaces so that it can log the path to destination. Each cell remembers the path to it from the starting coordinate.
I'm having trouble getting the second variable #find_possible_incremental_moves run smoothly under the #find_possible_positions_from_origin method. A "cell" is supposed to be created at the destination coordinate of the board, so that I can have the path to it, and check if the path is occupied by any other pieces. But when I call the destination coordinate, I get nil.
Someone corrected me on a previous question that I shouldn't post my entire production code which makes sense, so I included the single #build_tree that I'm having trouble with I hope that's enough.
Here is my code that have for this section.
def build_tree
#start_coor = convert_input_to_coor(#start)
#destination_coor = convert_input_to_coor(#destination)
#selected_piece = #gameboard[#start_coor[0]][#start_coor[1]]
starting_cell = Cell.new(#start_coor[0], #start_coor[1])
queue = []
queue.unshift(starting_cell)
until queue.empty?
current = queue.shift
possible_positions = find_possible_positions_from_origin([current.x, current.y])
next if possible_positions.nil?
if possible_positions.include?(#destination_coor)
#selected_piece.possible_positions = find_possible_incremental_moves(([current.x, current.y]))
#selected_piece.possible_positions.each do |move|
next unless !#dummyboard.board[move[0]][move[1]].instance_of? Cell
linked_cell = Cell.new(move[0], move[1])
current.edges << linked_cell
linked_cell.path = current.path + linked_cell.path
#dummyboard.board[move[0]][move[1]] = linked_cell
queue.push(linked_cell)
end
end
end
starting_cell
end

Excel - More efficient way to remove specific borders

How can I make the below code more efficient, at the moment it takes roughly 30 seconds to complete
The code will clear all cells within a selection which have a white background & then clear all diagonal borders within a selection.
With only the clear cells with white background code it finishes instantly but as soon as I added the remove borders code it became slow.
Sub ADULTClearOnly()
Set sh2 = ThisWorkbook.Worksheets("ADULT Sign On Sheet")
sh2.Select
Cells.Range("B1:F756").Select
For Each Cell In Selection
If Cell.Interior.Color = Excel.XlRgbColor.rgbWhite Then
Cell.Value = ""
End If
Next
Cells.Range("G1:AO757").Select
For Each Cell In Selection
If Cell.Borders(xlDiagonalUp).LineStyle = xlDiagonalUp Then
Cell.Borders(xlDiagonalUp).LineStyle = xlNone
End If
Next
End Sub
There are several issues in your code:
You don't need to, and should not Select to do these actions
Your logic is flawed: xlDiagonalUp is not a LineStyle
Because you are setting any Diagonal Up borders to none, you don't need to iterate the range, do it in one step
So, replace
Cells.Range("G1:AO757").Select
For Each Cell In Selection
If Cell.Borders(xlDiagonalUp).LineStyle = xlDiagonalUp Then
Cell.Borders(xlDiagonalUp).LineStyle = xlNone
End If
Next
with
sh2.Range("G1:AO757").Borders(xlDiagonalUp).LineStyle = xlNone
Similarly,
sh2.Select
Cells.Range("B1:F756").Select
For Each Cell In Selection
If Cell.Interior.Color = Excel.XlRgbColor.rgbWhite Then
Cell.Value = ""
End If
Next
can be reduced to
For Each Cell In sh2.Range("B1:F756")
If Cell.Interior.Color = Excel.XlRgbColor.rgbWhite Then
Cell.ClearContents
End If
Next

How to keep panning only if id exists?

I'm trying to pan through a list of elements to confirm that the set minimum number of elements is there on the screen. The problem I'm running into is that 'pan' will keep going and the test will pass even if I set the minimum to a high number (greater than what's actually there on the page).
When /^I swipe through my list of chat suggestion cards I should see the minimum$/ do
i = 0
while i < 12
i += 1
wait_for_element_exists("* id:'itemContainer'")
pan("* id:'itemContainer'", :left)
end
end
Is there anyway to check if the number of id: 'itemContainer' is actually there, to make it fail if the minimum number doesn't exist?
Query will only return the elements that are currently on the screen, so you will have to swipe across to make all of the cards visible to calabash and check for them. Assuming that query("* id:'itemContainer'") would only find one at a time, i.e. the cards are a whole screen in size,
12.times do
card_before_panning = query("* id:'itemContainer'")
pan("* id:'itemContainer'", :left)
card_after_panning = query("* id:'itemContainer'")
assert_not_equal card_before_panning, card_after_panning
end
If more than one of the cards can be visible on the screen at a time then you will have to do an additional check. Assuming that there could be two visible at the time
11.times do
card_before_panning = query("* id:'itemContainer' index:0")
pan("* id:'itemContainer'", :left)
card_after_panning = query("* id:'itemContainer' index:0")
assert_not_equal card_before_panning, card_after_panning
end
# Then check that there are two visible on the final screen.
assert_equal 2, query("* id:'itemContainer'").size
Note that this will only work if the cards appear differently in your app, i.e. they have different content. If query("* id:'itemContainer'") has identical results for each of the cards then calabash will not be able to tell them apart to see if anything has changed.

Change cell background color without changing focus

On a form I have 4 MSFlexGrids.
The top grid contains dynamic data, which updates once in a while.
The user can enter data in the cells of the 3 other grids.
The data which is used to fill the top grid is received via a Winsock control, processed, and then the results are written into the appropriate cells using .TextMatrix(intRow, intCol) = strData
This works fine. The data is updated flawlessly, and the user can enter his data into the other 3 grids without any problems.
The problem occurs when I want to change the background color of some cells in the top grid.
On rare occasions the received data is very important, and the background color of the corresponding cells should change color.
I change the color of the cells with the following code:
With grd
For lngRow = 1 To .Rows - 1
'default background color
lngBack = vbWhite
'check for important values
If Val(.TextMatrix(lngRow, 1)) >= lngMax Then
'important color
lngBack = &H3040FF
End If
'select whole row
.Row = lngRow
.Col = 0
.RowSel = lngRow
.ColSel = .Cols - 1
'set the background color of the selected row
.CellBackColor = lngBack
Next lngRow
End With 'grd
The problem with this is that when the user is entering data in the other 3 grids, and the background color of a row in the top grid is changed, then the focus moves to the top grid, and the user has to enter his data anew in the grid where he was working.
Is it possible to change the background color of a cell or whole row in a MSFlexGrid without moving the focus to that grid?
So far I could not find a solution to the problem itself.
I created a work around though :
I created an enum containing a value for each grid:
Public Enum ActiveGrid
enuSystem = 0
enuTel = 1
enuRLN = 2
enuRood = 3
enuData = 4
enuCircuit = 5
End Enum
Whenever a grid gets the focus I save the corresponding enum value in a form level variable.
After coloring the required cells in the first grid I return the focus to the grid which last had it.
The user is not editing in the grid itself, but in a textbox which is laid over the cell, so there is no real problem with the grid losing the focus.
When you look closely though you see the focus leave and return quickly.
For now I will accept this work around, and its minor glitches.
Maybe in the future I can come up with a better solution, or anyone else has a better suggestion?

Resources