Drag one picturebox to picturebox, it drags them all - c#

When i drag one picturebox, it drags both of mine. Because in the pbxMap_DragDrop method i have to call both of the methods that should fire when i drag one.
private void pbxMap_DragDrop(object sender, DragEventArgs e)
{
myDetectMouse.setMinotaur(e, myMap.myCells);
myDetectMouse.setTheseus(e, myMap.myCells);
}
SetTheseus:
public void setTheseus(DragEventArgs e, List<Cell> cells)
{
for (int i = 0; i < cells.Count; i++)
{
int[] mapData = myMapController.getMapData(i, cells);
int column = mapData[0];
int row = mapData[1];
int right = mapData[2];
int bottom = mapData[3];
Point RelativeMouseLoc = myMapController.myMap.myForm.pbxMap.PointToClient(Cursor.Position);
if (RelativeMouseLoc.X > column &&
RelativeMouseLoc.X < column + myMapController.myMap.myCellSize
&& RelativeMouseLoc.Y > row && RelativeMouseLoc.Y <
row + myMapController.myMap.myCellSize)
{
myMapController.myMap.myCells[i].hasTheseus = true;
}
else
{
myMapController.myMap.myCells[i].hasTheseus = false;
}
}
}
SetMinotaur is much the same but replace hasTheseus with hasMinotaur. As soon as a cell "hasTheseus" or "hasMinotaur" it will be drawn to the cell.
So it draws them both when i drag one because they both get set in pbxMap_DragDrop.
I thought i could have multiple event handlers for pbxMap_DragDrop depending on which picturebox was dragged.

You can check the sender parameter to determine whether you want to move the minotaur or Theseus. It would look something like this:
var pic = (PictureBox)sender;
if (pic.Name == "minotaur")
{
myDetectMouse.setMinotaur(e, myMap.myCells);
}
else
{
myDetectMouse.setTheseus(e, myMap.myCells);
}
If you don't want to use the Name property, you can use something else like the Tag property - just make sure you set it for each of the PictureBox objects.

Related

c# Windows Forms adding pictureBoxes to an Array

I need to add PictureBox's (pictureBox11 to pictureBox30) to an array.
So instead of adding PictureBox's like this:
PictureBox[] Coins = new PictureBox[20];
Coins[0] = pictureBox11;
...
Coins[19] = pictureBox30;
I wrote a for cycle like this (DOESN'T WORK) :
for (int i = 11; i < 31; i++)
{
for (int j = 0; j < Coins.Length; j++)
{
Coins[j] = (PictureBox)Controls.Find(
"pictureBox" + i.ToString(), true)[0];
}
}
There might be a small stupid mistake somewhere because I use the same cycle for another thing and it works, idk, maybe I'm just blind and cant see the mistake.
Maybe it is relevant, so I will include the code I am assigning for the array elements:
for (int i = 0; i < Coins.Length; i++)
{
if (player.Bounds.IntersectsWith(Coins[i].Bounds))
{
Coins[i].Visible = false;
}
}
EVERYTHING works fine if I add them as shown in first code, but it is not very practical.
Why isn't the second code (the for cycle) I wrote working for me?
Is there a better way to add multiple pictureboxes to an array?
I am guessing you are making this more complicated than it has to be. To try and understand better, I assume that when you say I need to add pictureboxes (pictureBox11 to pictureBox30) to an array. that you mean there are 30+ PictureBoxs on your form and each PictureBox uses a naming convention such that each is named “pictureBoxX” where “X” is 1,2,3…30,31. Then you want to get a (consecutive?) group of “PictureBoxes” on the form to make invisible. I hope this is correct.
To simply make the picture boxes invisible, I do not think an array is needed. Simply loop through the picture boxes and make it invisible if the name matches a string of the form “pictureBoxX “. I used IndexsAreValid method to validate the start and end indexes. It is also used in the code for an array implementation below this code.
Make PictureBoxes invisible without an array
private void SetPictureBoxesInvisible(int start, int end) {
int size = -1;
string targetString = "";
if (IndexsAreValid(start, end, out size)) {
for (int i = start; i < end + 1; i++) {
try {
targetString = "pictureBox" + i;
PictureBox target = (PictureBox)Controls.Find(targetString, true)[0];
if (target != null) {
target.Visible = false;
}
}
catch (IndexOutOfRangeException e) {
return;
}
}
}
}
If you must have a PictureBox array returned, then the code below should work.
First, to get an array of PictureBoxs as you want you need an array to store them. But first you need to know how big to make it. From your posted code it appears that you want to get picture boxes 11-30 and put them in an array. So we can get the size from these numbers… i.e. 30-11=19 +1 = 20. That’s about all you need. Simply create the array and loop through all the picture boxes and grab pictureBox11-pictureBox30. When done we can use this array to make these `PictureBoxes” invisible.
I created a method IsValidPic similar to a tryParse to validate if the given index (1,2,3..30) is valid. If it is out of range, I simply ignore that value. This gives you the ability to grab an individual picture box in case the desired picture boxes are not contiguous. I used a few buttons to test the methods.
Hope this helps.
private PictureBox[] GetPictureBoxes(int start, int end) {
int size = - 1;
if (IndexsAreValid(start, end, out size)) {
PictureBox curPic = null;
PictureBox[] allPics = new PictureBox[size];
int index = 0;
for (int i = start; i <= end; i++) {
if (IsValidPic(i, out curPic)) {
allPics[index] = curPic;
index++;
}
}
return allPics;
}
else {
return new PictureBox[0];
}
}
private Boolean IndexsAreValid(int start, int end, out int size) {
if (start < 1 || end < 1) {
size = -1;
return false;
}
if (start > end) {
size = -1;
return false;
}
size = end - start + 1;
return true;
}
private Boolean IsValidPic(int index, out PictureBox picture) {
string targetName = "pictureBox" + index;
try {
PictureBox target = (PictureBox)Controls.Find(targetName, true)[0];
if (target != null) {
picture = target;
return true;
}
picture = null;
return false;
}
catch (IndexOutOfRangeException e) {
picture = null;
return false;
}
}
private void ResetAll() {
foreach (PictureBox pb in this.Controls.OfType<PictureBox>()) {
pb.Visible = true;
}
}
private void button1_Click(object sender, EventArgs e) {
TurnInvisible(2, 3);
}
private void button3_Click(object sender, EventArgs e) {
TurnInvisible(11, 30);
}
private void button4_Click(object sender, EventArgs e) {
TurnInvisible(1,7);
}
private void TurnInvisible(int start, int end) {
PictureBox[] pictureBoxesToChange = GetPictureBoxes(start, end);
foreach (PictureBox pb in pictureBoxesToChange) {
if (pb != null)
pb.Visible = false;
}
}
private void button2_Click(object sender, EventArgs e) {
ResetAll();
}

C# objectlistview undefined offset in cell editor

I use TreeListView component from ObjectListView library. I make cell values editable and when i double click on them TextBox will appear with odd offset.
I want to remove this offset, but how?
before start editing
after start editing
As you can see first row, second column ("My new device"), TextBox is appeared with offset.
P.S. Editing work as expected. Only offset is annoying me
P.P.S. As you can see the offset depends of first column offset. How i can change it to zero?
After long searches i found solution!
Source code of OLV, ObjectListView.cs
public virtual void StartCellEdit(OLVListItem item, int subItemIndex) {
OLVColumn column = this.GetColumn(subItemIndex);
Control c = this.GetCellEditor(item, subItemIndex);
Rectangle cellBounds = this.CalculateCellBounds(item, subItemIndex);
c.Bounds = this.CalculateCellEditorBounds(item, subItemIndex, c.PreferredSize);
// Try to align the control as the column is aligned. Not all controls support this property
Munger.PutProperty(c, "TextAlign", column.TextAlign);
// Give the control the value from the model
this.SetControlValue(c, column.GetValue(item.RowObject), column.GetStringValue(item.RowObject));
// Give the outside world the chance to munge with the process
this.CellEditEventArgs = new CellEditEventArgs(column, c, cellBounds, item, subItemIndex);
this.OnCellEditStarting(this.CellEditEventArgs);
if (this.CellEditEventArgs.Cancel)
return;
// The event handler may have completely changed the control, so we need to remember it
this.cellEditor = this.CellEditEventArgs.Control;
this.Invalidate();
this.Controls.Add(this.cellEditor);
this.ConfigureControl();
this.PauseAnimations(true);
}
I saw CellEditEventArgs contains Control, that drawed in area named Bounds.
This function in the source file append offset to control's bounds:
protected Rectangle CalculateCellEditorBoundsStandard(OLVListItem item, int subItemIndex, Rectangle cellBounds, Size preferredSize) {
if (this.View == View.Tile)
return cellBounds;
// Center the editor vertically
if (cellBounds.Height != preferredSize.Height)
cellBounds.Y += (cellBounds.Height - preferredSize.Height) / 2;
// Only Details view needs more processing
if (this.View != View.Details)
return cellBounds;
// Allow for image (if there is one).
int offset = 0;
object imageSelector = null;
if (subItemIndex == 0)
imageSelector = item.ImageSelector;
else {
// We only check for subitem images if we are owner drawn or showing subitem images
if (this.OwnerDraw || this.ShowImagesOnSubItems)
imageSelector = item.GetSubItem(subItemIndex).ImageSelector;
}
if (this.GetActualImageIndex(imageSelector) != -1) {
offset += this.SmallImageSize.Width + 2;
}
// Allow for checkbox
if (this.CheckBoxes && this.StateImageList != null && subItemIndex == 0) {
offset += this.StateImageList.ImageSize.Width + 2;
}
// Allow for indent (first column only)
if (subItemIndex == 0 && item.IndentCount > 0) {
offset += (this.SmallImageSize.Width * item.IndentCount);
}
// Do the adjustment
if (offset > 0) {
cellBounds.X += offset;
cellBounds.Width -= offset;
}
return cellBounds;
}
We can see, that offset appending to every cell (not only first). Also we can se, that CellEditEventArgs contains CellBounds.
So we can just reset Control.Bounds to CellBounds value:
//...
dataTreeView.CellEditStarting += DisableInputValueForCollections;
//...
private static void DisableInputValueForCollections(object sender, CellEditEventArgs e)
{
RemoveExtraOffsetForNotFirstColumnInputControl(e);
var node = e.RowObject as DataTreeNode;
if (node != null && e.Column.AspectName == "Value")
{
if (node.IsContainer()) e.Cancel = true;
}
}
//...
private static void RemoveExtraOffsetForNotFirstColumnInputControl(CellEditEventArgs e)
{
if (e.Column.AspectName != "Name")
{
e.Control.Bounds = e.CellBounds;
}
}
//...
The issue still exists in OLV v2.9.1. I worked around it slightly different than muzagursiy did.
olv.CellEditStarting += (sender, args) =>
{
// Left align the edit control
args.Control.Location = args.CellBounds.Location;
// Readjust the size of the control to fill the whole cell if CellEditUseWholeCellEffective is enabled
if (args.Column.CellEditUseWholeCellEffective)
{
args.Control.Size = args.CellBounds.Size;
}
};

How can I instantiate large number of buttons in Windows Forms?

I'm developing a theatre reservation software. I'm using Windows Forms, the seats is represented by a 2-dimensioned array. And I draw the buttons as following:
public void DrawSeats()
{
// pnl_seats is a Panel
pnl_seats.Controls.Clear();
// Here I store all Buttons instance, to later add all buttons in one call (AddRange) to the Panel
var btns = new List<Control>();
// Suspend layout to avoid undesired Redraw/Refresh
this.SuspendLayout();
for (int y = 0; y < _seatZone.VerticalSize; y++)
{
for (int x = 0; x < _seatZone.HorizontalSize; x++)
{
// Check if this seat exists
if (IsException(x, y))
continue;
// Construct the button with desired properties. SeatSize is a common value for every button
var btn = new Button
{
Width = SeatSize,
Height = SeatSize,
Left = (x * SeatSize),
Top = (y * SeatSize),
Text = y + "" + x,
Tag = y + ";" + x, // When the button clicks, the purpose of this is to remember which seat this button is.
Font = new Font(new FontFamily("Microsoft Sans Serif"), 6.5f)
};
// Check if it is already reserved
if (ExistsReservation(x, y))
btn.Enabled = false;
else
btn.Click += btn_seat_Click; // Add click event
btns.Add(btn);
}
}
// As said before, add all buttons in one call
pnl_seats.Controls.AddRange(btns.ToArray());
// Resume the layout
this.ResumeLayout();
}
But already with a seat zone of 20 by 20 (400 buttons), it spent almost 1 minute to draw it, and in debug I checked that the lack of performance, is the instantiation of the buttons.
There is a way to make it faster? Perhaps disable all events during the instatiation or another lightweight Control that has the Click event too?
UPDATE:
lbl was a test, the correct is btn, sorry.
UPDATE 2:
Here is the IsException and ExistsReservations methods:
private bool IsException(int x, int y)
{
for (var k = 0; k < _seatsExceptions.GetLength(0); k++)
if (_seatsExceptions[k, 0] == x && _seatsExceptions[k, 1] == y)
return true;
return false;
}
private bool ExistsReservation(int x, int y)
{
for (var k = 0; k < _seatsReservations.GetLength(0); k++)
if (_seatsReservations[k, 0] == x && _seatsReservations[k, 1] == y)
return true;
return false;
}
Suppose that you change your arrays for reservations and exclusions to
public List<string> _seatsExceptions = new List<string>();
public List<string> _seatsReservations = new List<string>();
you add your exclusions and reservations in the list with something like
_seatsExceptions.Add("1;10");
_seatsExceptions.Add("4;19");
_seatsReservations.Add("2;5");
_seatsReservations.Add("5;5");
your checks for exclusions and reservations could be changed to
bool IsException(int x, int y)
{
string key = x.ToString() + ";" + y.ToString();
return _seatsExceptions.Contains(key);
}
bool ExistsReservation(int x, int y)
{
string key = x.ToString() + ";" + y.ToString();
return _seatsReservations.Contains(key);
}
of course I don't know if you are able to make this change or not in your program. However consider to change the search on your array sooner or later.
EDIT I have made some tests, and while a virtual grid of 20x20 buttons works acceptably well (31 millisecs 0.775ms on average), a bigger one slows down noticeably. At 200x50 the timing jumps to 10 seconds (1,0675 on average). So perhaps a different approach is needed. A bound DataGridView could be a simpler solution and will be relatively easy to handle.
I also won't use such a myriad of controls to implement such a thing. Instead you should maybe create your own UserControl, which will paint all the seats as images and reacts on a click event.
To make it a little easier for you i created such a simple UserControl, that will draw all the seats and reacts on a mouse click for changing of the state. Here it is:
public enum SeatState
{
Empty,
Selected,
Full
}
public partial class Seats : UserControl
{
private int _Columns;
private int _Rows;
private List<List<SeatState>> _SeatStates;
public Seats()
{
InitializeComponent();
this.DoubleBuffered = true;
_SeatStates = new List<List<SeatState>>();
_Rows = 40;
_Columns = 40;
ReDimSeatStates();
MouseUp += OnMouseUp;
Paint += OnPaint;
Resize += OnResize;
}
public int Columns
{
get { return _Columns; }
set
{
_Columns = Math.Min(1, value);
ReDimSeatStates();
}
}
public int Rows
{
get { return _Rows; }
set
{
_Rows = Math.Min(1, value);
ReDimSeatStates();
}
}
private Image GetPictureForSeat(int row, int column)
{
var seatState = _SeatStates[row][column];
switch (seatState)
{
case SeatState.Empty:
return Properties.Resources.emptySeat;
case SeatState.Selected:
return Properties.Resources.choosenSeat;
default:
case SeatState.Full:
return Properties.Resources.fullSeat;
}
}
private void OnMouseUp(object sender, MouseEventArgs e)
{
var heightPerSeat = Height / (float)Rows;
var widthPerSeat = Width / (float)Columns;
var row = (int)(e.X / widthPerSeat);
var column = (int)(e.Y / heightPerSeat);
var seatState = _SeatStates[row][column];
switch (seatState)
{
case SeatState.Empty:
_SeatStates[row][column] = SeatState.Selected;
break;
case SeatState.Selected:
_SeatStates[row][column] = SeatState.Empty;
break;
}
Invalidate();
}
private void OnPaint(object sender, PaintEventArgs e)
{
var heightPerSeat = Height / (float)Rows;
var widthPerSeat = Width / (float)Columns;
e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
for (int row = 0; row < Rows; row++)
{
for (int column = 0; column < Columns; column++)
{
var seatImage = GetPictureForSeat(row, column);
e.Graphics.DrawImage(seatImage, row * widthPerSeat, column * heightPerSeat, widthPerSeat, heightPerSeat);
}
}
}
private void OnResize(object sender, System.EventArgs e)
{
Invalidate();
}
private void ReDimSeatStates()
{
while (_SeatStates.Count < Rows)
_SeatStates.Add(new List<SeatState>());
if (_SeatStates.First().Count < Columns)
foreach (var columnList in _SeatStates)
while (columnList.Count < Columns)
columnList.Add(SeatState.Empty);
while (_SeatStates.Count > Rows)
_SeatStates.RemoveAt(_SeatStates.Count - 1);
if (_SeatStates.First().Count > Columns)
foreach (var columnList in _SeatStates)
while (columnList.Count > Columns)
columnList.RemoveAt(columnList.Count - 1);
}
}
This will currently draw forty rows and columns (so there are 800 seats) and you can click on each seat to change its state.
Here are the images i used:
EmtpySeat:
ChoosenSeat:
FullSeat:
If you anchor this control and resize it or you click on a seat to change its state there can be some minor lacking for the repainting if you further increase the number of rows or columns, but that is still somewhere far below one second. If this still hurts you, you have to improve the paint method and maybe check the ClipRectangle property of the paint event and only paint the really needed parts, but that's another story.
Rather than using actual button controls, just draw the image of the seats then when the user clicks on a seat translate the mouse X,Y coordinates to determine which seat was clicked. This will be more efficient. Of course, the drawback is that you have to write the method to translate x,y coordinates to a seat, but that really isn't that difficult.
EDIT; it has been pointed out to me this will not work in Windows Forms!
Well, you are Sequentially working through it.
if one iteration costs 1 sec, the full process will take 400*1 in time.
Perhaps you should try and make a collection of your objects, and process it 'parallel'.
try the .Net framework (4 and above) 'parallel foreach' method:
http://msdn.microsoft.com/en-s/library/system.threading.tasks.parallel.foreach(v=vs.110).aspx
edit: so, if you have a list buttonnames, you can say
buttonNames.ForEach(x=>CreateButton(x));
while your CreateButton() method is as following:
private Button CreateButton(string nameOfButton) { Button b = new
Button(); b.Text = nameOfButton; //do whatever you want...
return b; }

Moving in 2-d array of rectangle cells with arrows

i need help on a maze game that i'm trying to build. I know there is a lot written on that topic, but i can't get it right. So, on the problem - i want the user to escape from the maze with arrow keys. I build the maze from 2-d array of rectangle cells from the tutorial here.
And that is the method.
public static Grid DFS(Grid grid)
{
Stack<Cell> cellStack = new Stack<Cell>();
int totalCells = grid.Cells.GetLength(0) * grid.Cells.GetLength(1);
Cell currentCell = grid.Cells[0, 0];
currentCell.IsVisited = true;
grid.VisitedCells = 1;
while (grid.VisitedCells < totalCells)
{
List<Cell> neighbours = GetNeighbours(grid, currentCell);
if (neighbours.Count > 0)
{
Cell newCell = GetRandomNeighbour(neighbours);
CrushWall(currentCell, newCell);
newCell.IsVisited = true;
cellStack.Push(currentCell);
currentCell = newCell;
grid.VisitedCells++;
}
else
{
currentCell = cellStack.Pop();
}
}
return grid;
}
Then i add it on a panel in the main form:
private void mediumToolStripMenuItem_Click(object sender, EventArgs e)
{
panel1.Controls.Clear();
Grid grid = new Grid(30, 30);
panel1.Size = grid.Size;
grid.BorderStyle = BorderStyle.FixedSingle;
panel1.Controls.Add(grid);
maze = Maze.DFS(grid);
}
So far so good. Now i want to escape from the maze. Start point is Cell[0,0] and the goal is at the last Cell, let's say Cell[30,30]. Here is my attempt for that. It's not finished yet and covers just when we go right and down. What it happens is that i go just one cell right or down and that's it. Noting more! Please tell me where i'm wrong!
void frmMain_KeyDown(object sender, KeyEventArgs e)
{
for (int i = 0; i < maze.Rows; i++)
{
for (int j = 0; j < maze.Columns; j++)
{
maze.Cells[i, j].IsVisited = false;
}
}
Cell currentCell = maze.Cells[0, 0];
if (currentCell == maze.Cells[maze.Rows - 1, maze.Columns - 1])
{
MessageBox.Show("Well Done! You made it!");
}
else
{
switch (e.KeyCode)
{
case Keys.Right:
currentCell = Maze.GoRight(maze, currentCell);
currentCell.IsOnPath = true;
maze.Invalidate();
break;
case Keys.Down:
currentCell = Maze.GoDown(maze, currentCell);
currentCell.IsOnPath = true;
maze.Invalidate();
break;
}
}
}
And here is the going right for example:
public static Cell GoRight(Grid maze, Cell currentCell)
{
List<Cell> neighbours = GetMazeNeighbours(maze, currentCell);
Cell rightNeighbour = new Cell();
if (neighbours.Any())
{
foreach (var item in neighbours)
{
if (item.LeftWall == 1)
{
rightNeighbour = item;
}
}
}
return rightNeighbour;
}
Two potential problems I can see straight away. Firstly, most seriously, you're initialising currentCell to the cell at [0,0] every time you press a key. So, every time a key is pressed currentCell goes back to [0,0]! That can't be right.
Secondly, you need to break out or return from your foreach as soon as you assign rightNeighbour, or any other cells in the list of neighbours that are subsequently found matching the item.LeftWall == 1 criteria will overwrite the assignment.(Plus it's inefficient to iterate through a list when you've already found what you're looking for).
e.g.
foreach (var item in neighbours)
{
if (item.LeftWall == 1)
{
rightNeighbour = item;
break;
}
}
Finally i was able to locate the problem and fix it. Here it is on the image:
The black cell is the current cell that we`re on. The yellow ones are the neighbours. The problem is that the two neighbours have the same properties. For example:
neighbour1.TopWall = 1;
neighbour2.TopWall = 1;
This means that the top wall of both neighbours is crushed.
Let`s say i want to go down. In the KeyDown event the condition for going down is true for both of the neighbours, so it is pure luck that the correct neighbour is the first met here:
foreach (var item in neighbours)
{
if (item.TopWall == 1)
{
rightNeighbour = item;
break;
}
}
And i solved it like this:
if current cell has neighbours
check if bottom cell is not null
if false, check if its top wall is crushed
if true, make bottom cell the current cell
I hope this will help to someone! Cheers!

checking a color of a button and changing it using a 2D array

I'm creating a small game just like the game Reversi/Othello I have managed to created a 2x3 board with buttons.
The buttons change colour ones you click on them but I'm having trouble to detect if there is a white colour in between 2 black colours and if so change that white colour into black.. I hope this make sense. the buttons are in a 2D array. Any suggestions that could help me do this would be much appreciated.
The image:
Here is my code:
![namespace reversitest
{
public partial class Form1 : Form
{
private Button\[,\] squares;
public Form1()
{
InitializeComponent();
squares = new Button\[3, 2\];
squares = new Button\[,\] {{button1, button2, button3},
{button4, button5, button6,}};
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (Button sqrr in squares)
{
sqrr.Click += new System.EventHandler(this.DrawCharacter);
}
}
int _turn = 0;
private void DrawCharacter(object sender, EventArgs e)
{
Button sqrr = (Button)sender;
int col = 0;
if (sqrr.BackColor.Equals(Color.Black) || sqrr.BackColor.Equals(Color.White))
{
MessageBox.Show("Move Not Allowed!");
}
else
{
for ( int i = 0; i < squares.GetLongLength(1); ++i)
{
// check othere squares and change color
if (i < 2)
{
for (int f = 0; f < 3; ++f)
{
var ss = squares\[i, f\];
if (ss.BackColor.Equals(Color.Black))
{
MessageBox.Show("we have a black");
//ss = squares\[i, f+1\];
ss.BackColor = Color.Black;
}
else
{
MessageBox.Show("no black");
}
}
}
if (_turn == 0)
{
_turn = 1;
sqrr.BackColor = Color.Black;
}
else
{
_turn = 0;
sqrr.BackColor = Color.White;
}
}
}
}
}
}
First name your buttons with the array index. It will help you to find the button.
For example according to you picture button1 name would be btn_1_1.
Then inside your button click event first get the button name and then identify the button positioned.
Button b = sender as Button;
string[] btnData = b.Name.Split('_');
int x = int.Parse(btnData[1]);
int y = int.Parse(btnData[2]);
//check for possible combinations
int top = y - 2;
int botton = y + 2;
int left = x - 2;
int right = x + 2;
if (top >= 0 && squares[top, y].Background == Color.Black)
{
squares[top+1, y].Background = Color.Black;
}
...
...
Continue like that. If you need more detail please free to ask.
Final Answer
//check for possible combinations
int top = x - 2;
int botton = x + 2;
int left = y - 2;
int right = y + 2;
if (top >= 0 && squares[top, y].BackColor == Color.Black)
{
squares[top + 1, y].BackColor = Color.Black;
}
else if (left >= 0 && squares[x, left].BackColor == Color.Black)
{
squares[x, left + 1].BackColor = Color.Black;
}
else if (left >= 0 && squares[x, left].BackColor == Color.Black)
{
squares[x, left + 1].BackColor = Color.Black;
}
Will be extended for a 8x8 board later on
Do you need it to be elegant? A kind of brute force method: You could check for pieces in the 8 different directions it is possible for them to be aligned. So for example, you start with a black piece. Check the next piece over in one direction. If it's white, keep going and take a note of the position that was white so you can change it to black later. When you finally hit a black piece, change all the stored positions to black and move on to the next direction and repeat the process until you've done all 8 directions.

Categories