I am working on a game where a user moves around a 10x10 grid of buttons. The buttons are added to a 2d array and are displayed as shown below. Currently I have the starting position (black player tile) set to index 1 when the form loads. What I am trying to figure out is how I can introduce a button event method that I can use to navigate the tiles.
Here is what the grid looks like:
And here is the code:
private readonly int _xAxis = 10;
private readonly int _yAxis = 10;
private int _count = 1;
private void DrawButtonArray()
{
Button[] buttons = new Button[_xAxis * _yAxis];
int index = 0;
for (int i = 0; i < _xAxis; i++)
{
for (int j = 0; j < _yAxis; j++)
{
Button gridBtn = new Button
{
Size = new Size(60, 55),
Location = new Point(175 + j * 60, 55 + i * 55),
Text = _count.ToString()
};
gridBtn.ForeColor = Color.FromArgb(64, 64, 64);
buttons[index++] = gridBtn;
_count++;
Controls.Add(gridBtn);
if (index == 1)
{
gridBtn.BackColor = Color.Black;
}
}
}
}
What Id hope to achieve is a mouse click event (or possibly WASD key press) that moves the "player" from one button to another. The current idea I have is to set the next button that is clicked to the colour of the current position, then set the current positions colour to the default grey. I just need to know how I could add these event args to the method that doesn't contain them. How might I add them?
I created a method that works, but it might not be the best:
private void DrawButtonArray()
{
Button[] buttons = new Button[_xAxis * _yAxis];
int currentIndex = 0;
for (int i = 0; i < _xAxis; i++)
{
for (int j = 0; j < _yAxis; j++)
{
Button gridBtn = new Button
{
Size = new Size(60, 55),
Location = new Point(175 + j * 60, 55 + i * 55),
Text = _count.ToString()
};
gridBtn.ForeColor = Color.FromArgb(64, 64, 64);
if (currentIndex == 0)
{
gridBtn.BackColor = Color.FromArgb(0, 0, 0);
}
buttons[currentIndex++] = gridBtn;
_count++;
Controls.Add(gridBtn);
}
}
currentIndex = 1;
foreach (Button nextIndex in buttons)
{
nextIndex.Click += (s, e) =>
{
if (nextIndex.Text == (currentIndex + 1).ToString()
|| nextIndex.Text == currentIndex.ToString()
|| nextIndex.Text == (currentIndex - 1).ToString()
|| nextIndex.Text == (currentIndex + 10).ToString()
|| nextIndex.Text == (currentIndex - 10).ToString())
{
buttons[currentIndex - 1].BackColor = Color.FromArgb(64, 64, 64);
currentIndex = int.Parse(nextIndex.Text);
nextIndex.BackColor = Color.Black;
}
else
{
MessageBox.Show("Invalid Move");
}
};
}
}
Related
I am working on a game. For this game i create around 200 images in a box 20x10.
My problem is that pressing 1 button creates them a lot of times which garbages the Memory, which i want to avoid. So i created a little if/else function which is supposed to check wether the images were created or not. In case they weren't, code creates them, but if they were, the code should delete them, and i have no idea how to delete code generated images or how to interract with them at all.
public void GameStart(bool load = false)
{
Random rnd = new Random();
Pause.IsEnabled = true;
Save.IsEnabled = true;
Shuffle.IsEnabled = true;
byte datasave = 0;
int[,] TileID = new int[20,10];
for(int i = 0; i < 20; i++)
{
for(int j = 0; j < 10; j++)
{
if(TileID[i,j] != 0)
{
datasave = 1;
}
TileID[i, j] = rnd.Next(1,9);
CreateImage(i, j, TileID[i,j], datasave);
}
}
}
public void CreateImage(int a, int b, int TileID, byte datainfo)
{
if(datainfo != 0)
{
Image image = new Image();
image.Width = 40;
image.Height = 40;
image.Name = $"Tile{a}{b}";
image.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
image.Margin = new Thickness(-1000 + 80 * a, -200 + 80 * b, 0, 0);
string way = #"C:\Users\ignat\Desktop\Игра\Images\";
image.Source = new BitmapImage(new Uri(way + $"icon{TileID}.jpg", UriKind.Absolute));
Grid.Children.Add(image);
}
else
{
CreateImage(a, b, TileID, datainfo);
}
Basically, I need to match to match the Picture and the color, so that result will be that whenever I press the burger it becomes blue, and when I click something else it becomes green.
NOW it just randomly goes green or blue whenever I click the button with no reliance on the clicked picture.
Again, I need to match to match the picture and the color, so that result will be that whenever I press the burger it becomes blue, and when I click something else it becomes green.
I will now add screenshots of the form when it starts and what happens, and the entire code.
Thanks in advance.
Start : https://prnt.sc/jnad9j
When Clicked : https://prnt.sc/jnadie
CODE:
for (int i = 0; i < arr.GetLength(0); i++)
{
cx = x;
for (int j = 0; j<arr.GetLength(1); j++)
{
value = rnd.Next(0, 2);
t = new Button();
t.Tag = new Place(i, j);
if (value == 0)
rndmimg = rnd.Next(1, 2);
else rndmimg = rnd.Next(2, 6);
t.BackColor = Color.Red;
t.BackgroundImageLayout = ImageLayout.Stretch;
t.BackgroundImage = Image.FromFile("..\\..\\Pictures\\"+rndmimg+".png");
t.Bounds = new Rectangle(cx, y, w, h);
t.Click += new System.EventHandler(this.qqq_Click);
this.Controls.Add(t);
arr [i, j] = t;
cx += w;
}
y += h;
}
public Form1() => InitializeComponent();
private void Form1_Load(object sender, EventArgs e) => rnd = new Random();
private void qqq_Click(object sender, EventArgs e)
{
int px;
int py;
Place pl = (Place)(((Button)sender).Tag);
px = pl.GetR();
py = pl.C;
rndmcus = rnd.Next(0, 2); // Rndmcus determines color when button is clicked
if (rndmcus == 0)
{
mishvalue = 0;
arr[px, py].BackColor = Color.Green;
arr[px, py].Enabled = false;
}
if (rndmcus == 1)
{
mishvalue = 1;
arr[px, py].BackColor = Color.Blue;
arr[px, py].Enabled = false;
}
((Button)sender).Text = " ";
scanner();
}
public void scanner()
{
int counter = 0;
for (int i = 0; i < arr.GetLength(0); i++)
for (int j = 0; j < arr.GetLength(0); j++)
if (arr[i, j].Text == " ")
counter++;
if (counter == boardsize * boardsize)
this.Close();
}
class Place
{
private int r;
private int c;
public Place(int r, int c)
{
this.r = r;
this.c = c;
}
public int GetR() => r;
public int C => c;
public void SetR(int r) => this.r = r;
public void SetC(int c) => this.c = c;
}
Assign all your button an id then access it in the event
for (int j = 0; j < arr.GetLength(1); j++)
{
value = rnd.Next(0, 2);
t = new Button();
t.ID = j.ToString();
Button button = (Button)sender;
string buttonId = button.ID;
Associate color with the id in like a Dictionary.
I have a standard panel which I add controls too, when the number of controls exceeds the panels size I want to clear the panel ready for the "next page" of controls which just is a clear and location reset of the buttons. Problem is when ever I clear the controls new ones will not add. Here is what I have:
// MDButList is the collection of controls
ButPosX = 2; // x position of button on panel
ButPosY = 2; // y position of button on panel
PageCount = 1; // page number
for (int i = 0; i <= MDButList.Count - 1; i++)
{
NewPOBut = MDButList[i]; // as cant ref a collection for some reason..
if (i % 14 == 0) // panel can only hold 14
{
if (i < 13) // for first item (0)
SetPOButPos(ref ButPosX, ref ButPosY, ref NewPOBut);
//sets the buttons point value and increments x & y
else
{
panMDItems.Controls.Clear();
ButPosX = 2;
ButPosY = 2;
PageCount++;
SetPOButPos(ref ButPosX, ref ButPosY, ref NewPOBut);
btnPrevPage.Visible = true;
btnNextPage.Visible = true;
labPageNum.Visible = true;
labPageNum.Text = PageCount.ToString() + " / " + PageCount.ToString();
}
}
else
{
SetPOButPos(ref ButPosX, ref ButPosY, ref NewPOBut);
}
}
Controls are being added to the collection and the code steps through as expected but after 14 controls I just get a blank panel nothing above a 14 control count will add? Ask if you need more info, thanks!
I was kind of bored, so i've made a sample of how i would do what you are asking for. This is my code, see if it fits you.
public partial class Form1 : Form
{
private int page = 1;
private int pageCount = 0;
List<Button> MDButList = new List<Button>();
public Form1()
{
InitializeComponent();
GenerateButtons(60);
SetButtons(page);
}
private void GenerateButtons(decimal number)
{
for (int i = 0; i < number; i++)
{
Button a = new Button();
a.Text = "But" + i;
MDButList.Add(a);
}
pageCount = Convert.ToInt32(Math.Ceiling(number / 14));
}
private void SetButtons(int page)
{
labPageNum.Text = page.ToString() + " / " + pageCount.ToString();
int ButPosX = 2;
int ButPosY = 2;
for (int i = panMDItems.Controls.Count - 1; i >= 0; --i)
panMDItems.Controls[i].Dispose();
int upperlimit=(page * 14) - 1;
if (upperlimit>MDButList.Count-1) upperlimit=MDButList.Count-1;
for (int i = (page-1) * 14; i <=upperlimit ; i++)
{
Button NewPOBut = MDButList[i];
SetPOButPos(ref ButPosX, ref ButPosY, ref NewPOBut);
if (i % 2 != 0)
{
ButPosX = 2;
ButPosY += NewPOBut.Height + 10;
}
else
{
ButPosX += NewPOBut.Width + 10;
}
}
}
private void SetPOButPos(ref int ButPosX, ref int ButPosY, ref Button NewPOBut)
{
NewPOBut.Location = new Point(ButPosX, ButPosY);
panMDItems.Controls.Add(NewPOBut);
}
private void btnPrevPage_Click(object sender, EventArgs e)
{
if (page > 1) page--;
SetButtons(page);
}
private void btnNextPage_Click(object sender, EventArgs e)
{
if (page < pageCount) page++;
SetButtons(page);
}
}
I am currently trying to develop a form of battleships on c# windows form.
Here is the code I am trying to use.. the trouble I have been having is how to create a second set of buttons (another 10x10) behind the other, with two sets of controls so I can switch between the two.
I have everything like AI and automated setups, I just need to have 2 button controls. I hope someone can help me out with this! Many thanks!
private List<List<Button>> grid = new List<List<Button>>();
public UserForm()
{
InitializeComponent();
byte numRows = 10;
byte numCols = 10;
for (byte i = 0; i < numRows; i++)
{
grid.Add(ButtonRowCreator(numCols, 25, (i+1) * 50));
}
}
public List<Button> ButtonRowCreator(byte numOfBtnsNeeded, int x, int y)
{
List<Button> btns = new List<Button>();
for (int i = 0; i < numOfBtnsNeeded; i++)
{
Button btn = new Button();
btn.Size = new Size(50, 50);
btn.Location = new Point(x + (i * btn.Width), y);
btns.Add(btn);
btn.Font = new Font("Georiga", 10);
this.Controls.Add(btn);
btn.Click += new EventHandler(btn_Click);
}
return btns;
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
int curRow = -1, curCol = -1;
for(int i = 0; i < grid.Count; i++)
{
int index = grid[i].IndexOf(btn);
if (index != -1)
{
curRow = i;
curCol = index;
Console.WriteLine("curRow = " + curRow.ToString() + ", curCol = " + curCol.ToString());
}
}
// ... now you can use "curRow", "curCol" and "grid" to do something ...
foreach (List<Button> row in grid)
{
foreach (Button col in row)
{
col.ForeColor = Color.Gray;
}
}
if (board[curRow, curCol] == 1)
{
if (btn.Text == "Hit")
{
}
else
{
btn.Text = "Hit";
btn.BackColor = Color.Red;
hit++;
}
if (hit == 17)
{
MessageBox.Show("Congratulations, You Sunk Their Battleships!");
MessageBox.Show("Thanks For Playing!");
MessageBox.Show("Goodbye!");
}
}
else
{
btn.Text = "Miss!";
btn.BackColor = Color.Blue;
}
I think this is what you're after?
It looks like a lot of your code is used to figure out what button is clicked on. This information can be stored on the button object itself in the Tag property and greatly simplifies the code.
private Button[,] _grid1;
private Button[,] _grid2;
public UserForm()
{
InitializeComponent();
_grid1 = new Button[10, 10];
_grid2 = new Button[10, 10];
CreateGrid(_grid1, 10, 10, 25, 0, 20, true);
CreateGrid(_grid2, 10, 10, 25, 250, 20, false);
}
public void CreateGrid(Button[,] grid, int numOfRows, int numOfCols, int offsetX, int offsetY, int buttonSize, bool enabled)
{
for (byte i = 0; i < numOfRows; i++)
{
for (byte j = 0; j < numOfCols; j++)
{
grid[i,j] = ButtonCreator(i, j, offsetX, offsetY, buttonSize, enabled);
}
}
}
public Button ButtonCreator(int row, int col, int x, int y, int buttonSize, bool enabled)
{
Button btn = new Button();
btn.Size = new Size(buttonSize, buttonSize);
btn.Location = new Point(x + (col * buttonSize), y + (row * buttonSize));
btn.Font = new Font("Georiga", 10);
this.Controls.Add(btn);
btn.Click += new EventHandler(btn_Click);
btn.Tag = row + "," + col;
btn.Enabled = enabled;
return btn;
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string[] coord = btn.Tag.ToString().Split(',');
int curRow = Convert.ToInt32(coord[0]);
int curCol = Convert.ToInt32(coord[1]);
Console.WriteLine(curRow = " + curRow + ", curCol = " + curCol);
// ... now you can use "curRow", "curCol" to do something ...
_grid1[curRow, curCol].BackColor = Color.Red;
}
What do I want to achieve?
My goal is to create a sudoku field programmatically, so I want to add 9x9 EditText-views to my existing TableLayout.
What is my problem?
Easy said: The EditText-views are not showing up.
What have I tried?
Well.. my google attempts could be recognized as a DDOS-Attack.. ;)
But seriously, I googled a lot, read some documentations etc. but could not find appropriate information solving my problem.
My Sudoku activiy code:
public class Sudoku : Activity
{
private EditText[,] tbs;
private TableLayout grid;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
//set view
SetContentView(Resource.Layout.Sudoku);
//initializations
tbs = new EditText[9,9];
grid = FindViewById<TableLayout> (Resource.Id.grid);
//preparation
prepareControls ();
}
private void prepareControls()
{
int size = Conversion.PixelsToDp(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.Density) / 15;
int x_default = 10;
int x = x_default;
int y = x_default;
int margin = 4;
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams (size, size);
for (int row = 0; row < 9; row++)
{
TableRow trow = new TableRow (this);
for (int col = 0; col < 9; col++)
{
//lparams.LeftMargin = x;
//lparams.TopMargin = y;
EditText tb = new EditText (this);
tb.SetHeight (size);
tb.SetWidth (size);
tb.Gravity = GravityFlags.Center;
tb.SetTextColor (Color.Argb (1, 75, 75, 75));
tb.SetBackgroundColor (Color.White);
tb.LayoutParameters = lparams;
tbs[col, row] = tb;
//layout.AddView (tb, lparams);
trow.AddView (tb);
x += size;
if ((col + 1) % 3 == 0)
{
x += margin;
}
if ((col + 1) % 9 == 0)
{
y += size;
x = x_default;
}
}
if ((row + 1) % 3 == 0)
{
y += margin;
}
grid.AddView (trow);
}
}
}
Additional information
Environment: Xamarin
Language: C#
API Level: API 15
I appreciate any help!