Button won't change visibility as intended - c#

I have a function that has a multidimentional array that holds n*n numbers, and a vector that holds my programs Buttons.
Right now, my program is able to shuffle the numbers in the array and assign each value to a button, "refreshing the values of each button" everytime I press the button.
I now have a problem when I've tried to hide a specific number (eg.0) each time I "refresh" the button, but it seems it doesn't make the previous button visible when I press the button, which leads to having all the buttons hidden eventually.
This is the code I have right now:
public void Refresh(int NumberToHide)
{
foreach (Button b in buttons)
b.Visibility = Visibility.Visible;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (buttons[(i * 4 + j)].Content.ToString() == NumberToHide.ToString())
{
buttons[(i * 4 + j)].Visibility = Visibility.Hidden;
}
else
{
buttons[(i * 4 + j)].Content = myArray[i, j].ToString();
}
}
}
}
Shouldn't the foreach at the start of the function make every button visible?
Why is it that the buttons that are not visible, don't become visible everytime I call the function?
Thanks for the help!

The problem seems to come from the fact that you either hide an element or assign a Content. Since your visibility check is based on that content, previously invisible elements don't change. I can't reproduce it since a lot of your code is missing, but based on your description I'd check for the new content instead of the current:
public void Refresh(int numberToHide)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
var button = buttons[i * 4 + j];
button.Content = myArray[i, j];
button.Visibility = myArray[i, j] == numberToHide ?
Visibility.Hidden : Visibility.Visible;
}
}
}

Related

Unsort a listbox in c# winform

I am very new programmer, the user is able to input vales into a ListBox, there is also a option button where the user can sort the numbers in ascending order. However I am also asked to create a option button to unsort back into its original form, however I am not sure how I would do this. I am trying to do this without the use of any containers/arrays. here is my code to sort:
private void sorted()
{
int a = lstHoldValue.Items.Count;
for (int i = 0; i < a - 1; i++)
{
var k = 0;
for (var j = 1; j < a - i; j++)
{
if (Convert.ToInt32(lstHoldValue.Items[j]) < Convert.ToInt32(lstHoldValue.Items[k]))
{
var temp = lstHoldValue.Items[j];
lstHoldValue.Items[j] = lstHoldValue.Items[k];
lstHoldValue.Items[k] = temp;
k = j;
}
else
{
k++;
}
}
}
}

tablelayoutpanel within a tablelayoutpanel disposal

I have a tableLayoutPanel called tlpMaster. It has 4 columns and 8 rows. in 3 of the columns and each row, it has another tableLayoutPanel. so thats 3 inner ones. Inside those I have checkboxes that I need to be able to dispose. Here is what I got so far but it seems to be disposing the tableLayoutPanels and not the checkboxes.
for (int i = 0; i < 8; i++)
{
for (int j = 1; j < 4; j++)
{
//loop throught the table layout panels and dispose
Control tlpTemp = tlpMaster.GetControlFromPosition(j, i);
while (tlpTemp.Controls.Count > 0)
{
tlpTemp.Controls[0].Dispose();
}
}
}
What am I doing wrong here?
Figured it out
for (int i = 0; i < 8; i++)
{
for (int j = 1; j < 4; j++)
{
//loop throught the table layout panels and dispose
Control tlpTemp = tlpMaster.GetControlFromPosition(j, i);
foreach(Control ctrl in tlpTemp.Controls)
{
while (ctrl.Controls.Count > 0)
{
ctrl.Controls[0].Dispose();
}
}
}
}

C# - How to access property of an array object?

I dont know how to show clearly, so:
Example - I create an array of button like this:
Button[,] _button = new Button[3, 3];
public MainPage()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
_button[i, j] = new Button();
_button[i, j].Name = "btn" + i.ToString() + j.ToString();
_button[i, j].Tag = 0;
//Add Click event Handler for each created button
_button[i, j].Click += _button_Click;
boardGrid.Children.Add(_button[i, j]);
Grid.SetRow(_button[i, j], i);
Grid.SetColumn(_button[i, j], j);
}
} // end MainPage()
private void _button_Click(object sender, RoutedEventArgs e)
{
Button b = (Button)sender;
if (...)
b.Tag = 1;
else
b.Tag = 2;
}// end Click Event
Now how can I compare the Tag of 2 buttons in that array like:
b[1,1].Tag == b[1,2].Tag ? ...<do st>... : ....<do st>...
If you need to find position of control in array consider to set Control.Tag to that position instead of search:
_button[i, j].Tag = new System.Drawing.Point{ X = j, Y = i};
And instead of searching just
Point position = (Point)((Button)sender).Tag;
Or if you need more information (like Position + 0/x/empty choice you have) - have custom class to hold all information you need:
enum CellState { Empty, Player1, Player2 };
class TicTacToeCell
{
public Point Position {get;set;}
public CellState State {get;set;}
}
Now when you have position and state - use _buttons array to index access other ones:
Check same row:
Point position = (Point)((Button)sender).Tag;
int player1CountInThisRow = 0;
for (var col = 0; col < 3; col++)
{
if (((TicTacToeCell)(_button[position.Y, col].Tag).State == CellState.Player1)
{
player1CountInThisRow ++;
}
}
This is more of a long-winded clarification than a definite answer, but it may uncover what you're really trying to do:
In the code that you show b is (presumably) a single Button, not an array of buttons. Do you mean:
_button[1,1].Tag == _button[1,2].Tag ? ...<do st>... : ....<do st>...
Or are you trying to compare b (the event sender) to a button relative to it in the array?

c#: Creating a 10x10 field (and array) of CheckBoxes

I have a problem, and i don't know why but i can't figure out what it actually is.
All I want to do is create a 10 x 10 field of checkboxes as a board for a game basically.
The thing I came up with should use an Array of these boxes to easily identify them from box[0,0] to box[9,9] according to theirt coordinates in the field.
This is the code i am struggling with:
private void Form1_Load(object sender, EventArgs e)
{
// == OPTIONS ========================================
int xpos = 60; // Position of the first Checkbox (x)
int ypos = 60; // Position of the first Checkbox (y)
int size = 10; // Number of Rows and Columns
int spc = 30; // Space between boxes (Default:20)
// ====================================================
//other Variables
int x, y;
//Creating the Game Field
CheckBox[,] box = new CheckBox[size,size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
box[i, j] = new CheckBox();
//For Debugging Purpuses: Showing i and j next to checkBox
box[i, j].Text = i + "" + j;
//Set Position
y = i * spc + xpos;
x = j * spc + ypos;
box[i, j].Location = new Point(x,y);
this.Controls.Add(box[i, j]);
}
}
}
All I get from this is one single column of checkboxes marked [0,0] to [0,9].
And even if i switch around x and y or i and j, that never changes. So i.E. i will never get a row of checkboxes, just always a single column. Where am I going wrong with this?
i just get those 10 checkboxes, nothing more. they do not seem to be placed over each other either.
Hope you can help me out here :) thanks.
timo.
The check-boxes are too wide by default.
Try it with (for example):
int spc = 50;
And also add this in the loop:
box[i, j].Width = 40;

Prevent Stack Overflow in a Minesweeper Clone

I'm creating a Minesweeper clone. Thus far, I've gotten to revealing adjacent tiles when the tile clicked has zero adjacent mines, below is my method for revealing mines.
struct data
{
public Button tile;
public bool mine, flag, clicked;
public int adjMines;
}
data[,] dat;
//Defaults
Size gridSize = new Size(16, 16);
Size tileSize = new Size(16, 16);
int mines = 40, flags = 0;
bool valid(int x, int y)
{
return (x >= 0 && y >= 0 && y < gridSize.Height && x < gridSize.Width);
}
void reveal(Button btn)
{
btn.BackColor = Color.DimGray;
start = true;
btn.Enabled = false;
//find button clicked, forget everything you ever learned about efficiency.
for (int i = 0; i < gridSize.Width; i++)
for (int j = 0; j < gridSize.Height; j++)
if (dat[i, j].tile == btn)
{
if (dat[i, j].adjMines == 0)
{
for (int ii = -1; ii <= 1; ii++)
for (int jj = -1; jj <= 1; jj++)
if (valid(i + ii, j + jj))
reveal(dat[i + ii, j + jj].tile);
}
else
btn.Text = dat[i, j].adjMines.ToString();
}
}
I keep getting a StackOverflowException when I run it, which doesn't come as much of a surprise, but I don't know how to fix it without doing away with the struct, which is a requirement. Any ideas?
The problem is that when you "reveal", you reveal all the neighbors. When the neighbor is revealed, it reveals all of its neighbours, including the first one, and now you have an infinite recursion.
The trick is: before you reveal the very first one, make a hash set of "in progress reveals". Before you recurse, add the current button to the "in progress" set. In the reveal method return immediately if the button is already in the in-progress set. You know that all its neighbours are already in the process of being revealed, so there's no work to do.
It would probably help if you didn't recursively try to reveal the same tile:
for (int ii = -1; ii <= 1; ii++)
for (int jj = -1; jj <= 1; jj++)
if (valid(i + ii, j + jj) && !(ii == 0 && jj == 0))
reveal(dat[i + ii, j + jj].tile);
Note the !(ii == 0 && jj == 0) test added - that will stop one of the stack overflow reasons. Apart from that, you also need to mark the node as 'enabled' before going recursive, it'll keep bouncing back and forth otherwise.
It's not a really efficient method you've chosen to implement, but it should work with this fix.
It looks like you are calling reveal from inside reveal. Reveal goes through each tile. You are calling it for all adjacent tiles which then goes through each tile and then calls all adjacent tiles. I would suggest looking through your use of recursion.

Categories