I have problem to find the shortest path between two squares in the grid.
I would like to implement Lee's algorithm, but my struggle is to find the neighbors of specific coordinate in the table.
What I am not quite sure, where to move the cursor in the grid, when I label the neighbors with specific number. I have four movements in the grid, so I label everytime four neighbors of the current point, but where to move then?
Example:
My input:
Size of the grid: MxN
Characters which would be in the table. For example ABCDEF...(It is sort of Keyboard)
String which would be written by the table:
For example: BCD
Output of the program would be minimum of presses to write this specific string.
Start position of the cursor in the grid is in upper left corner. Presses are: up, down, left, right and ENTER - which will print the character
My starting aproach is: First find the position of the character of the string in the table. Then make a matrix with distances, which has in the beginning everywhere zeros. Then check if the character, which was found, is in upper left corner. If is, then number of presses is 1, find another character. Else label neighbors and get to the current letter. If you get to the current letter save number of presses and find next character from the position of the previous character.
See my button project below. Read comments. You can implement with a textboxes so you can put letters into the boxes, or a picture box where yo can added pictures to the cells.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Buttons
{
public partial class Form1 : Form
{
const int ROWS = 5;
const int COLS = 10;
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
public void Form1_Load(object sender, EventArgs e)
{
new MyButton(ROWS, COLS, this);
}
}
public class MyButton : Button
{
const int WIDTH = 50;
const int HEIGHT = 50;
const int SPACE = 5;
const int BORDER = 20;
public static List<List<MyButton>> buttons { get; set; }
public static List<MyButton> buttonList { get; set; }
public Form1 form1;
public int row { get; set; }
public int col { get; set; }
public Boolean[] neighbors { get; set; } //array 0 to 3, 0 top, 1 right, 2 bottom, 3 left with false is no wall true is wall
public MyButton()
{
}
public MyButton(int rows, int cols, Form1 form1)
{
buttons = new List<List<MyButton>>();
buttonList = new List<MyButton>();
this.form1 = form1;
for (int row = 0; row < rows; row++)
{
List<MyButton> newRow = new List<MyButton>();
buttons.Add(newRow);
for (int col = 0; col < cols; col++)
{
MyButton newButton = new MyButton();
newButton.Height = HEIGHT;
newButton.Width = WIDTH;
newButton.Top = row * (HEIGHT + SPACE) + BORDER;
newButton.Left = col * (WIDTH + SPACE) + BORDER;
newButton.row = row;
newButton.col = col;
newRow.Add(newButton);
buttonList.Add(newButton);
newButton.Click += new System.EventHandler(Button_Click);
form1.Controls.Add(newButton);
}
}
neighbors = new Boolean[4];
for (int i = 0; i < 0; i++)
{
neighbors[i] = true;
}
}
public void Button_Click(object sender, EventArgs e)
{
MyButton button = sender as MyButton;
MessageBox.Show(string.Format("Pressed Button Row {0} Column {1}", button.row, button.col));
}
}
}
Related
I have a class project to create a tic tac toe simulations (game is not played by people) where O's and X's automatically generate when the New Game button is clicked. I am having trouble with the code to get the labels to show the output.
Using a 2D array type INT to simulate the game board, it should store a 0 or 1 in each of the 9 elements and produce a O or X. There also needs to be a label to display if X or O wins.
Here is my code so far ( I know there isn't much, I'm completely lost):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void StartButton_Click(object sender, EventArgs e)
{
Random rand = new Random();
const int ROWS = 3;
const int COLS = 3;
int[,] gameBoard = new int[ROWS, COLS];
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{ gameBoard[row, col]= rand.Next(2); }
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Win Forms labels get populated unless the current event process finishes completely. If you want to update the labels with X and O while you may use the control property InvokeRequired (boolean) and after assigning the value to label call label.Refresh() function. I will suggest fork a thread on hitting start button and do the for loop -> random.next() inside the thread. Try with these changes. All the Best!!
Try following :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
const int ROWS = 3;
const int COLS = 3;
const int WIDTH = 100;
const int HEIGHT = 100;
const int SPACE = 20;
static TextBox[,] gameBoard;
public Form1()
{
InitializeComponent();
gameBoard = new TextBox[ROWS, COLS];
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
TextBox newTextBox = new TextBox();
newTextBox.Multiline = true;
this.Controls.Add(newTextBox);
newTextBox.Height = HEIGHT;
newTextBox.Width = WIDTH;
newTextBox.Top = SPACE + (row * (HEIGHT + SPACE));
newTextBox.Left = SPACE + (col * (WIDTH + SPACE));
gameBoard[row, col] = newTextBox;
}
}
}
}
}
I'm new to Unity and programming and I'm trying to make this game with moving cars on gameboard. My idea is to create an array and somehow store information about each element or tile in this array. I'd like these tiles to be able to be referenced to later, e.g. to detect if there is car GO on specific tile or not, etc. Unfortunately I¨m struggling how exactly should I save information to a tile so I can reference to it later, I mean later when I create a method which should be able to detect if that tile is occupied or not.
Thank you for all advices in advance!
The code below adds buttons to a panel control. You can replace the button with an image to use in your games.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const int ROWS = 10;
const int COLS = 15;
const int WIDTH = 20;
const int HEIGHT = 20;
const int SPACE = 10;
List<List<MyButton>> buttons = new List<List<MyButton>>();
public Form1()
{
InitializeComponent();
for (int row = 0; row < ROWS; row++)
{
List<MyButton> newRow = new List<MyButton>();
buttons.Add(newRow);
for (int col = 0; col < COLS; col++)
{
MyButton newButton = new MyButton();
newRow.Add(newButton);
newButton.Width = WIDTH;
newButton.Height = HEIGHT;
newButton.Left = col * (WIDTH + SPACE);
newButton.Top = row * (HEIGHT + SPACE);
newButton.row = row;
newButton.col = col;
panel1.Controls.Add(newButton);
}
}
}
}
public class MyButton : Button
{
public int row { get; set; }
public int col { get; set; }
}
}
I'm fairly new to OOP and am not sure how I would go about implementing something in my program. My program is pretty much similar to whack a mole and has an array of picture boxes with an image in and an image of a monster moves randomly between the picture boxes with a time interval applied or will move to a new random picture box whenever the user clicks on the monster in time. I have created an monster and a player sub class to try and add some OOP concepts to the program but am not sure how to implement what I want. Basically I have a label for score on my main form and a score variable in my animal class with a value. I want to be able to add the value of score from the label on my form when the user clicks on the picture box with the mole in and take away the value of score from the label when they don't click on it in time.
Here is my code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
PictureBox[] boxes;
int initialscore = 0;
int time = 0;
int randPos;
public Form1()
{
InitializeComponent();
}
private void boxes_MouseClick(object sender, MouseEventArgs e)
{
PictureBox pb2 = new PictureBox() { Image = Image.FromFile("sword2.png") };
this.Cursor = new Cursor(((Bitmap)pb2.Image).GetHicon());
for (int x = 0; x < 27; x++)
{
if (sender.Equals(boxes[x]))
{
Image grass = Image.FromFile("swamp.png");
PictureBox temp = (PictureBox)sender;
temp.Image = grass;
}
if (sender.Equals(boxes[x]))
{
PictureBox pb = (PictureBox)sender;
if (pb.Tag == "skeleton.png")
initialscore++;
}
}
label1.Text = " Score: " +initialscore.ToString();
}
public void timer1_Tick(object sender, EventArgs e)
{
boxes[randPos].Image = Image.FromFile("swamp.png");
boxes[randPos].Tag = "swamp.png";
Random r = new Random();
randPos=r.Next(0, 27);
boxes[randPos].Image = Image.FromFile("skeleton.png");
boxes[randPos].Tag = "skeleton.png";
}
private void Form1_Load(object sender, EventArgs e)
{
boxes = new PictureBox[27];
int top = 100;
int left = 100;
for (int x = 0; x < 27; x++)
{
boxes[x] = new PictureBox();
boxes[x].Image = Image.FromFile("swamp.png");
boxes[x].Height = 100;
boxes[x].Width = 100;
if (x % 9 == 0)
{
top += 120;
left = 120;
}
else
left += 120;
boxes[x].Top = top;
boxes[x].Left = (50 + left);
Controls.Add(boxes[x]);
this.boxes[x].MouseClick += new
System.Windows.Forms.MouseEventHandler(this.boxes_MouseClick);
label1.Text = " Score: " + initialscore.ToString();
label2.Text = " Time: " + time.ToString();
}
}
}
namespace WindowsFormsApplication1
{
class Monster
{
protected int score;
public Monster()
{
score = 10;
}
}
}
namespace WindowsFormsApplication1
{
class Player:Monster
{
}
}
Nothing has been added in the player class yet.
What do I need to add or change to be able to get the initial score to change by the value of the score in the monster class when clicking on the moving image?
To unify the updating/incrementing and visualization of the score you should extract that to a method:
public void incrementScore(int increment)
{
initialscore += increment;
label1.Text = " Score: " + initialscore.ToString();
}
in the Form1_Load you call this like:
incrementScore(0);
for the click on the monster you have different possibilities:
if all the monsters have the same points you can make it a static variable in the Monster class.
protected static int Score = 10;
which allows you to use it in the boxes_MouseClick event handler:
incrementScore(Monster.Score);
in case all monsters have another value you have to hold the score variable as an instance variable, identify somehow the instance of the monster class you clicked on and increment with this value
I'm having some issues with creating labels dynamically. I'm trying to create a 15x15 grid with an "X" label per cell, and the code is sort of working, it creates the first label but not the others, I've tried debugging the code with breakpoints and it's calling the Controls.Add the right amount of times but it's only creating one label. Here's the code:
class PlayingGrid
{
const int MAX_CELLS = 15;
Cell[,] grids = new Cell[MAX_CELLS, MAX_CELLS];
public PlayingGrid()
{
for (int y = 1; y < MAX_CELLS; y++)
{
int yPoint = y * 12;
for (int x = 1; x < MAX_CELLS; x++)
{
int xPoint = x * 12;
grids[y, x] = new Cell(new Point(xPoint, yPoint));
}
}
}
}
class Cell
{
#region Fields & Properties
public Letter Letter;
public Point Point;
public static GameForm refForm;
#endregion
//Default constructor will create an empty cell
public Cell(Point point)
{
Letter = new Letter(LatinAlphabet.Empty);
this.Point = point;
refForm.Invoke(new Action(()=> refForm.Controls.Add(new Label() { Text = "X", Location = point })));
}
}
Set label AutoSize property to true:
new Label() {AutoSize =true, Text = "X", Location = point }
Because with default size all label hided in below of last label.
Hi I have a small winforms program that will soon develop into something more. The program has 2 panels panel1 and panel2 these panels are populated dynamically with some form controls. the first panel is populated with combo-boxes and the second with a grid of buttons. What I want to achieve is to be able to disable the right button depending on what the user selects from the combobox. Each column of the grid represent a day of the week and the combobox will be used to disable the wanted day by selecting it from the list if you like.
To do this statically is straight forward, however my program will soon expand so that it can handle a large database so that's why I am doing this dynamically. Basically this is where I'm stuck at the moment I want to simply disable the right button.
Below is the interface that i have so far:
And this is my code if any help:
public Form1()
{
InitializeComponent();
}
Button[] btn = new Button[2];
ComboBox[] cmb = new ComboBox[1];
private void Form1_Load(object sender, EventArgs e)
{
placeRows();
}
public void createColumns(int s)
{
for (int i = 0; i < btn.Length; ++i)
{
btn[i] = new Button();
btn[i].SetBounds(40 * i, s, 35, 35);
btn[i].Text = Convert.ToString(i);
panel1.Controls.Add(btn[i]);
}
for (int i = 0; i < cmb.Length; ++i)
{
cmb[i] = new ComboBox();
cmb[i].SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged);
cmb[i].Text = "Disable";
cmb[i].Items.Add("Monday");
cmb[i].Items.Add("Tuesday");
cmb[i].SetBounds(40 * i, s, 70, 70);
panel2.Controls.Add(cmb[i]);
}
}
void cmb_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox senderCmb = (ComboBox)sender;
if (senderCmb.SelectedIndex == 1)
{
//MessageBox.Show("Tuesday");
btn[1].Enabled = false;
}
}
public void placeRows()
{
for (int i = 0; i < 80; i = i + 40)
{
createColumns(i);
}
}
}
Alternative 1
Every control has a Tag property.
You can set the Tag property of your buttons to represent the column they are in.
When a selection is made in the combo box, simply search through all buttons, and enable or disable the button based on whether each button's Tag property matches the selected text in the combo box.
Alternative 2
Create a
Dictionary<string, List<Button>> buttonMap;
where the key is the value representing the column ("Tuesday") and the value is a list of buttons with that tag. When creating the buttons initially, also populate that dictionary.
If you go with Alternative 2, you'll have to remember the previously selected value of the checkbox so you can re-enable buttons that are no longer disabled.
If you have lots of buttons, you may find that Alternative 2 is noticeably faster.
UPDATE
Here's a complete working sample of Alternative 1.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const int ROWS = 2;
const int COLS = 2;
Button[,] btn = new Button[ROWS,COLS];
ComboBox[] cmb = new ComboBox[ROWS];
private void Form1_Load(object sender, EventArgs e)
{
placeRows();
}
private readonly string[] cbTexts = new string[] { "Monday", "Tuesday" };
public void createColumns(int rowIndex)
{
int s = rowIndex * 40;
// Your original code kept overwriting btn[i] for each column. You need a 2-D array
// indexed by the row and column
for (int colIndex = 0; colIndex < COLS; colIndex++)
{
btn[rowIndex, colIndex] = new Button();
btn[rowIndex, colIndex].SetBounds(40 * colIndex, s, 35, 35);
btn[rowIndex, colIndex].Text = Convert.ToString(colIndex);
btn[rowIndex, colIndex].Tag = cbTexts[colIndex];
panel1.Controls.Add(btn[rowIndex, colIndex]);
}
cmb[rowIndex] = new ComboBox();
cmb[rowIndex].SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged);
cmb[rowIndex].Text = "Disable";
foreach (string cbText in cbTexts)
{
cmb[rowIndex].Items.Add(cbText);
}
cmb[rowIndex].SetBounds(40, s, 70, 70);
cmb[rowIndex].Tag = rowIndex; // Store the row index so we know which buttons to affect
panel2.Controls.Add(cmb[rowIndex]);
}
void cmb_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox senderCmb = (ComboBox)sender;
int row = (int)senderCmb.Tag;
for (int col = 0; col < COLS; col++)
{
Button b = btn[row, col];
// These three lines can be combined to one. I broke it out
// just to highlight what is happening.
string text = ((string)b.Tag);
bool match = text == senderCmb.SelectedItem.ToString();
b.Enabled = match;
}
}
public void placeRows()
{
for (int rowIndex = 0; rowIndex < 2; rowIndex++)
{
createColumns(rowIndex);
}
}
}