Reputation: 231
I am trying to make Chinese Checkers in C#. I'm having trouble moving a piece when it is clicked on. Right now I just want it to move where ever. What it is doing is creating a new instance of the piece object when it needs to just move. Any help would be great thank you. Here is the code.
namespace ChineseCheckers
{
public partial class mainForm : Form
{
private Board thisBoard = new Board();
public event PaintEventHandler paint;
public mainForm()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void mainForm_Paint(object sender, PaintEventArgs e)
{
int width = 15;
int del = 3;
int ystart = 50;
int xstart = ystart+4 * width;
SolidBrush whiteSB = new SolidBrush(Color.White);
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
if (Board.isSpace(i, j))
{
Space sp = thisBoard.getSpace(i, j);
int xPos = getXFromIndex(i, j, width, xstart, ystart);
int yPos = getYFromIndex(i, j, width, xstart, ystart);
pieceObject piece = new pieceObject(e, xPos - del, yPos - del, getColor(sp));
EventHandler myhandler = new EventHandler((a, b)=>myButton_Click(sender, e, piece));
piece.Click += myhandler;
piece.Size = new System.Drawing.Size(20, 20);
piece.Location = new System.Drawing.Point(xPos - del, yPos - del);
piece.BackColor = getColor(sp);
this.Controls.Add(piece);
}
}
}
}
private int getYFromIndex(int i, int j, int width, int xstart, int ystart)
{
return ystart + (2 * i) * width;
}
private int getIFromXY(int x, int y, int width, int xstart, int ystart)
{
return (y - ystart + width) / (2 * width);
}
private int getXFromIndex(int i, int j, int width, int xstart, int ystart)
{
return xstart + (2 * j - i) * width;
}
private int getJFromXY(int x, int y, int width, int xstart, int ystart)
{
int i = getIFromXY(x, y, width, xstart, ystart);
return (((x - xstart+ width/2) / width) + i) / 2;
}
private Color getColor(Space sp)
{
switch (sp)
{
case Space.Player1:
return Color.Orange;
case Space.Player2:
return Color.Yellow;
case Space.Player3:
return Color.Green;
case Space.Player4:
return Color.Blue;
case Space.Player5:
return Color.Purple;
case Space.Player6:
return Color.Red;
}
return Color.Gray;
}
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
{
Form currentForm = mainForm.ActiveForm;
currentForm.BackgroundImage = null;
currentForm.BackColor = Color.Black;
currentForm.Width = 600;
currentForm.Height = 650;
Button endTurn = new Button();
endTurn.Location = new Point(485, 575);
endTurn.Text = "End Turn";
endTurn.BackColor = Color.Wheat;
endTurn.Click += new EventHandler(endTurnEvent);
this.Controls.Add(endTurn);
}
public void endTurnEvent(object sender, EventArgs e)
{
System.Console.WriteLine("You have ended your turn!");
}
private void mainForm_MouseClick(object sender, MouseEventArgs e)
{
}
void myButton_Click(Object sender, System.EventArgs e, pieceObject piece)
{
System.Console.WriteLine("Position: " + piece.Location + "Color: " + piece.BackColor);
piece.Location = new Point(40, 40);
}
}
}
public class pieceObject : UserControl
{
// Draw the new button.
public pieceObject(PaintEventArgs e, int xPos, int yPos, Color color)
{
int width = 15;
SolidBrush whiteSB = new SolidBrush(color);
SolidBrush newPiece = new SolidBrush(color);
e.Graphics.FillEllipse(newPiece, xPos, yPos, width, width);
newPiece.Dispose();
}
}
Upvotes: 1
Views: 649
Reputation: 70671
Without a good, minimal, complete code example it is impossible to know for sure what the best advice would be. But given your problem statement:
What it is doing is creating a new instance of the piece object when it needs to just move
…it is at least possible to identify the specific bug that causes that and offer some suggestions.
The reason you are getting new instances of the pieceObject
class is that you are creating them every time the form's Paint
event is raised. It is important to understand that the Paint
event is raised every time that Windows decides that the window needs to be redrawn. It's not just a one-time thing.
Based on the direction you currently appear to be heading in terms of design, it seems likely you really do only want the code you've put in the Paint
event handler to be executed just once. If so, I'd recommend changing the code as follows:
First, fix the pieceObject
so that it draws itself as needed:
public class pieceObject : UserControl
{
private readonly Color _color;
public pieceObject(Color color) { _color = color; }
// Draw the new button.
protected override void OnPaint(PaintEventArgs e)
{
int width = 15;
using (SolidBrush newPiece = new SolidBrush(_color))
{
e.Graphics.FillEllipse(newPiece, 3, 3, width, width);
}
}
}
Then, instead of creating your pieceObject
instances every time the form's Paint
event is raised, just do it once, when the form is created:
public mainForm()
{
InitializeComponent();
InitializePieceControls();
}
private void InitializePieceControls()
{
int width = 15;
int del = 3;
int ystart = 50;
int xstart = ystart+4 * width;
for (int i = 0; i < 17; i++)
{
for (int j = 0; j < 17; j++)
{
if (Board.isSpace(i, j))
{
Space sp = thisBoard.getSpace(i, j);
int xPos = getXFromIndex(i, j, width, xstart, ystart);
int yPos = getYFromIndex(i, j, width, xstart, ystart);
pieceObject piece = new pieceObject(getColor(sp));
piece.Click += myButton_Click;
piece.Size = new System.Drawing.Size(20, 20);
piece.Location = new System.Drawing.Point(xPos - del, yPos - del);
// It's not clear why you are doing this, as it will just make
// it impossible to see the ellipse that is drawn by the piece
// itself
piece.BackColor = getColor(sp);
this.Controls.Add(piece);
}
}
}
}
void myButton_Click(object sender, EventArgs e)
{
pieceObject piece = (pieceObject)sender;
System.Console.WriteLine("Position: " + piece.Location + "Color: " + piece.BackColor);
piece.Location = new Point(40, 40);
}
Notes:
Click
event on the pieceObject
was wrong in a couple of ways: first, the lambda expression captured the sender and event args of the Paint
event, not the a
and b
actually sent with the event; second, there was no need to wrap the event handler in the lambda in the first place, because you can just cast the actual sender
of the Click
event to the pieceObject
that is in fact sending the event.Upvotes: 1