I'm trying to figure out how to set up my win condition (when the player lines up four chips as the same color horizontally, vertically, or diagonally). The win condition when met will display a win message, add 1 to a player win and player loss variable, add text to a list box, and clear the board.
I set up the board when the user presses the start button using the following code:
btnStartGame.Enabled = false;
btnStartGame.Visible = false;
btnExitGame.Enabled = true;
btnExitGame.Visible = true;
//This for loop creates the buttons used for the gameplay
for (int i = 0; i < gameButtons.Length; i++)
{
int index = i;
this.gameButtons[i] = new Button();
int x = 50 + (i % 7) * 50;
int y = 50 + (i / 7) * 50;
this.gameButtons[i].Location = new System.Drawing.Point(x, y);
this.gameButtons[i].Name = "btn" + (index + 1);
this.gameButtons[i].Size = new System.Drawing.Size(50, 50);
this.gameButtons[i].TabIndex = i;
this.gameButtons[i].UseVisualStyleBackColor = true;
this.gameButtons[i].Visible = true;
gameButtons[i].Click += (sender1, ex) => this.PlaceChip(sender1, index);
this.Controls.Add(gameButtons[i]);
From there main game play uses the following code for "dropping" chips into the columns:
private void PlaceChip(object sender, int index)
{
var pressedButton = (Button)sender;
if (pressedButton.BackColor == Color.BlanchedAlmond)
{
var newBackColor = black ? Color.Red : Color.Black;
var buttonToChangeIndex = index;
while (buttonToChangeIndex + 7 < gameButtons.Count() &&
gameButtons[buttonToChangeIndex + 7].BackColor == Color.BlanchedAlmond)
{
buttonToChangeIndex += 7;
}
gameButtons[buttonToChangeIndex].BackColor = newBackColor;
black = !black;
}
}
Currently my Win Condition code looks like the following, I just am not sure how I need to set this up correctly (assuming I am making a mistake somewhere) or how I call this and set up the arguments correctly when I call it.
private void WinCondition(int a, int b, int c, int d)
{
if (gameButtons[a].BackColor == gameButtons[b].BackColor && gameButtons[a].BackColor == gameButtons[c].BackColor && gameButtons[a].BackColor == gameButtons[d].BackColor)
{
gamesPlayed += 1;
do
{
if (gameButtons[a].BackColor == Color.Red)
{
MessageBox.Show("Player 1 Wins!");
player1wins += 1;
player2loss += 1;
lstScoreBoard.Items.Add("Player One");
//add to file
ResetBoard();
}
else
{
MessageBox.Show("Player 2 Wins!");
player2wins += 1;
player1loss += 1;
lstScoreBoard.Items.Add("Player Two");
ResetBoard();
}
if(gamesPlayed == 5)
{
MessageBox.Show("Maximum number of games have been played!\nWin board will now be reset!");
gamesPlayed = 0;
player1wins = 0;
player2wins = 0;
player1loss = 0;
player2loss = 0;
}
} while (gamesPlayed > 5);
}
}
If there is a better way to set up this win condition (In regards to the arguments etc) I am open for it! I'm at a loss for how to properly set it up!
If my description of what I need doesn't make sense feel free to ask and I will try to clarify!
Related
char SideA = 'A';
char SideB = 'B';
int CPUPlayer = 1;
Test.Text = x.ToString();
if (difficulty == 1)
{
if (CPUPlayer == 1)
{
string targetString = "";
for (int side = 1; side <= 1; side++)
{
targetString = SideA.ToString();
Test.Text = targetString.ToString();
for (int game = 1; game < 25; game++)
{
targetString = game.ToString();
for (int tile = 1; tile < 10; tile++)
{
targetString = tile.ToString();
PictureBox target = (PictureBox)(this.Controls.Find(targetString, true))[0];
if (target.BackgroundImage == null)
{
target.BackgroundImage = Properties.Resources.smallo;
Test.Text = targetString.ToString();
}
}
}
}
}
}
So I'm trying to loop through prenamed PictureBoxes (Ex: A11,A12,A13....etc) to have them change background Images by using the loop through string to connect to the pictureboxes but I keep getting Index is out of range from the PictureBox target = (PictureBox)(this.Controls.Find(targetString, true))[0];
I'm not sure what to do to fix it. I'm very new to c# and coding in general so would be nice to know what I'm missing!
To help you find the problem change
PictureBox target = (PictureBox)(this.Controls.Find(targetString, true))[0];
to
var found = this.Controls.Find(targetString, true);
if(found == null || found.Length < 1 ) {
throw new Exception("Picture not found")
}
After that, set a breakpoint in the throw line and find out why the picture was not found.
So turns out it was just my .ToString(); logic that was just flat out wrong and the string was coming out as a picturebox that didn't exist. This is the code that works:
if (difficulty == 1)
{
if (CPUPlayer == 1)
{
string targetString = "";
for (int side = 1; side <= 1; side++)
{
for (int game = 1; game < 25; game++)
{
for (int tile = 1; tile < 10; tile++)
{
targetString = SideA;
targetString += game.ToString();
targetString += tile.ToString();
Test.Text = targetString.ToString();
PictureBox target = (PictureBox)(this.Controls.Find(targetString, true))[0];
I'm creating a chessboard for my game. I have 64 buttons, for some reason I just can add 4 buttons into the panel. This is my code
for (int i = 0; i < 16; i++)
{
for (int t = 0; t < 4; t++)
{
if (t == 0)
{
Button RedSquare = tmpRedSquare;
square[t, i] = RedSquare;
}
else if (t == 1)
{
Button BlueSquare = tmpBlueSquare;
square[t, i] = BlueSquare;
}
else if (t == 2)
{
Button GreenSquare = tmpGreenSquare;
square[t, i] = GreenSquare;
}
else if (t == 3)
{
Button YellowSquare = tmpYellowSquare;
square[t, i] = YellowSquare;
}
pnlChessBoard.Controls.Add(square[t, i]);
}
tmpRedSquare.Location = new Point(tmpRedSquare.Location.X, tmpRedSquare.Location.Y + Constant.SquareMiddleSpace);
tmpBlueSquare.Location = new Point(tmpBlueSquare.Location.X + Constant.SquareMiddleSpace, tmpBlueSquare.Location.Y);
tmpGreenSquare.Location = new Point(tmpBlueSquare.Location.X, tmpBlueSquare.Location.Y - Constant.SquareMiddleSpace);
tmpYellowSquare.Location = new Point(tmpYellowSquare.Location.X - Constant.SquareMiddleSpace, tmpYellowSquare.Location.Y);
}
I expected the result should be 64 buttons on the form. The result is I just see 4 buttons (first 4 buttons when executing), I have debugged and realize that the panel just contains 4 controls after the program executed.
The code always go through the command, and it also the problem:
pnlChessBoard.Controls.Add(square[t, i]);
I didn't know how the panel didn't add other 62 buttons. So what is the main problem?
I can see that you already have an instance of tmpRedSquare, tmpBlueSquare, tmpGreenSquare and tmpYellowSquare, and it seems that you are expecting those instances to appear multiple times in your panel. Well, that's not how it works, you need to create each time a new instance of the expected Button to be added and provide that to the pnlChessBoard.Controls.Add() method.
I recommend you to create methods responsible for creating a new instance of those buttons (like CreateRedSquare(), CreateBlueSquare(), etc.) when they are called, and then use the returned instance instead:
if (t == 0)
{
Button RedSquare = CreateRedSquare();
square[t, i] = RedSquare;
}
...
Also, you will have to rethink your logic around the Location of the button when it's added to the panel.
You have just using 4 buttons. You need to create new Button().
Here is my sample code. You may need to calculate back X and Y according to your design. Hope it works.
public Button CreateBtnRedSqure()
{
Button b = new Button();
b.BackColor = Color.Red;
.....
.....
return b;
}
int Y = 0;
for (int i = 0; i < 16; i++)
{
int X = 0;
for (int t = 0; t < 4; t++)
{
if (t == 0)
{
Button RedSquare = CreateBtnRedSqure();
RedSquare.Location = new Point(X, Y + Constant.SquareMiddleSpace);
square[t, i] = RedSquare;
}
else if (t == 1)
{
Button BlueSquare = CreateBtnBlueSqure();
BlueSquare = new Point(X, Y + Constant.SquareMiddleSpace);
square[t, i] = BlueSquare;
}
else if (t == 2)
{
Button GreenSquare = CreateBtnGreenSqure();
GreenSquare = new Point(X, Y + Constant.SquareMiddleSpace);
square[t, i] = GreenSquare;
}
else if (t == 3)
{
Button YellowSquare = CreateBtnYellowSqure();
YellowSquare = new Point(X, Y + Constant.SquareMiddleSpace);
square[t, i] = YellowSquare;
}
pnlChessBoard.Controls.Add(square[t, i]);
X = X + (*width of your btn size)
}
Y = Y + (* height of your btn size );
}
I'm creating a new Picturebox via code, but now my TextBoxes don't give me any values. I think they went out of focus, or their controls aren't working anymore, here's the code so far:
private void button1_Click(object sender, EventArgs e)
{
int ErrorCode = 0;
string NewName = NewPointName.Text;
int X, Y;
Application.DoEvents();
if (NewPointName.Text == "")
ErrorCode = 1;
else
for (int i = 0; i < Names + 1; i++)
{
if (PointName[i] == NewName)
ErrorCode = 2;
}
if (ErrorCode > 0)
MessageBox.Show("Error " + ErrorCode);
else
{
if (Convert.ToInt32(NewPointXBox.Text) > 60)
X = 60;
else if (Convert.ToInt32(NewPointXBox.Text) < -60)
X = -60;
else if (NewPointXBox.Text == "")
X = 0;
else
X = Convert.ToInt32(NewPointXBox.Text);
if (Convert.ToInt32(NewPointYBox.Text) > 60)
Y = 60;
else if (Convert.ToInt32(NewPointYBox.Text) < -60)
Y = -60;
else if (NewPointYBox.Text == "")
Y = 0;
else
Y = Convert.ToInt32(NewPointYBox.Text);
Punkt.GiveName(NewName, Names);
Punkt.GiveCoordinates(X, Y, Names);
PointName[Names] = NewName;
NewPointName.Text = "";
NewPointXBox.Text = "";
NewPointYBox.Text = "";
Application.DoEvents();
UpdatePoint();
CreatePoint(X, Y, NewName, Names);
Names++;
ErrorCode = 0;
NewName = "";
}
}
public void CreatePoint(int X, int Y, string name, int i)
{
int StartPointX = 450, StartPointY = 450, Factor = 7;
if (RadioG6060.Checked)
{
StartPointX = 454;
StartPointY = 449;
Factor = 7;
}
Dot[i] = new PictureBox();
this.Controls.Add(Dot[i]);
Dot[i].Name = "PB_" + name;
Dot[i].Size = new Size(10, 10);
Dot[i].Image = Image.FromFile("../Dot.png");
Dot[i].Anchor = AnchorStyles.Left;
Dot[i].Location = new Point(StartPointX, StartPointY);
Dot[i].Visible = true;
InitializeComponent();
Dot[i].BringToFront();
Dot[i].Location = new Point(Dot[i].Location.X + (X * Factor), Dot[i].Location.Y - (Y * Factor));
Application.DoEvents();
}
I think it's the this.controls.Add(Dot[i]) that throws it off, because now I can't access the text in my NewPointName textbox.
How can I focus the program back on the form or do generally anything that could activate the boxes again?
I just solved the problem, I just had to leave out the InitializeComponent(), then it worked. Turns out that if you do that, the already existing components get blocked and can't be changed in any options of themselves anymore.
If you're from the USA, and you've ever been to a Cracker Barrel, then you've probably played the board game where you have to jump pegs until you only have one left. It's similar to Chinese checkers, with just a pyramid, or a triangle.
I have a form that makes the buttons and adds them to the form, and I have a "TheBoard" class that has all of the rules for how jumping works on the form. In my form, I also have a button clicker method that needs to run all of this.
I seem to have hit a brick wall. I can't figure out the logic behind getting it to accept a second click, in order to move through the whole if statements in the board class. My parameter for the move method in the board class takes an int x, which is the button you click on as a parameter. I feel like I'm missing the second half of the move. How do I get my move method to register two button clicks (the starting location of the peg and the end location of the peg)?
Code for form:
public partial class Form1 : Form
{
private Button[] btn = new Button[15];
private TheBoard myboard = new TheBoard();
public Form1()
{
InitializeComponent();
int buttonsPerRow = 1;
int index = 0;
while (index < btn.Length)
{
int increment = this.Width / (buttonsPerRow + 1);
for (int j = 1; j <= buttonsPerRow; j++)
{
btn[index] = new Button
{
//other style elements of the button
Name = "btn" + index
}
btn[index].Click += new EventHandler(this.My_Click);
Controls.Add(btn[index]);
index++;
}
buttonsPerRow++;
}
}
private void My_Click(object sender, EventArgs e) {
myboard.getValues();
Button b = (Button)sender;
string bName = b.Name;
// Now pull off the btn
string num = bName.Substring(3, bName.Length - 3);
// Parsing the number to an int
int x = Int32.Parse(num);
myboard.move(x);
int[] color = myboard.getValues();
for (int i = 0; i < 15; i++)
{
color = myboard.getValues();
if (color[i] == TheBoard.hasPeg)
{
btn[i].BackColor = System.Drawing.Color.Yellow;
}
else
btn[i].BackColor = System.Drawing.Color.Black;
}//for
}
}
Code for TheBoard class:
class TheBoard
{
static public int hasPeg = 100;
static public int noPeg = 50;
private int[] board;
private int firstMove; //1st click
public TheBoard()
{
board = new int[15];
board[0] = noPeg;
for(int i = 1; i < 15; i++)
{
board[i] = hasPeg;
}
firstMove = -1; //giving last move a location, starting it at the beginning
}
public int move(int x)
{
if(firstMove == -1)
{
firstMove = x;
return 0;
}
// blank at 0
// if you click a blank your 1st move
if (firstMove == noPeg)
{
Console.WriteLine("You cant move if there isn't a peg.");
return 666;
}
// first---------------------------------------middle-----------------------end
if (firstMove == 1 && board[0] == hasPeg && board[3] == hasPeg && board[6] == noPeg)
{
RemovePeg(board[0], board[3], board[6]);
return 0;
}
if (firstMove == 1 && board[0] == hasPeg && board[2] == hasPeg && board[4] == noPeg)
{
RemovePeg(board[0], board[2], board[4]);
return 0;
}
//etc for remaining firstMove possibilities
firstMove = -1;
return 5;
}
private int RemovePeg(int first, int second, int goal) {
board[goal] = hasPeg;
board[first] = noPeg;
board[second] = noPeg;
return 0;
}
public int[] getValues()
{
return board;
}
}
I looked over the code and I think I understand your problem; you can select the starting peg but you don't have a way to select where it should go. With minimal edit to your code, I would store the first button click in a global variable and then the second button click knows that it is the second and initiates the board move with the two pieces of information (and resets the global variable).
Here is my code for a CheckXWinner function, where I need to reference my Form in order to draw win lines:
public void CheckXWinner(Button[] buttonArray, Form1 frm)
{
int arrLength = buttonArray.Length;
int root = (int)Math.Sqrt(Convert.ToDouble(arrLength));
bool winner = false;//variable to keep the computer from going when Xwins
for (int i = 0; i < root; i++)
{
//Sets the counter for the winners back to zero
int d2Count = 0;
int d1Count = 0;
int hCount = 0;
int vCount = 0;
for(int j = 0; j < root; j++)
{
//increments the appropriate counter if the button contains an X
//Horizonal win
if (buttonArray[(i*root) + j].Text == "X")
{
hCount++;
if (hCount == root)
{
for (int z = (root - 1); z >= 0; z--)
{
buttonArray[(i*root) + z].BackColor = Color.IndianRed;
}
Xwins();
winner = true; //sets winner to true so computer does not take turn
}
}//end of Horizonal win
//Left to right diagonal
if (buttonArray[j + (j*root)].Text == "X")
{
d1Count++;
if (d1Count == root)
{
for (int z = (root - 1); z >= 0; z--)
{
buttonArray[z + (z * root)].BackColor = Color.IndianRed;
}
Xwins();
winner = true;
}
}//end of LTR win
//Right to left diagonal
if (buttonArray[(j*(root - 1)) + (root - 1)].Text == "X")
{
d2Count++;
if (d2Count == root)
{
for (int z = (root - 1); z >= 0; z--)
{
buttonArray[(z*(root - 1)) + (root - 1)].BackColor = Color.IndianRed;
}
Xwins();
winner = true;
}
}//end of RTL win
//Vertical win
if (buttonArray[i + (root*j)].Text == "X")
{
vCount++;
if (vCount == root)
{
for (int z = (root - 1); z >= 0; z--)
{
buttonArray[i + (root*z)].BackColor = Color.IndianRed;
}
Xwins();
winner = true;
}
}//end of vert win
}//end of for j loop
}//end of for loop
CheckDraw();
if (winner == false)
{
ComputerGoes(buttonArray);
};
}//end of CheckXWinner
In another part of this class I have the handler for all button clicks associated with the form:
//Handle any button clicks
private void button_click(object sender, EventArgs e)
{
Button b = (Button)sender;
b.Text = "X";
b.Enabled = false;
CheckXWinner(buttonArray, Form1 frm);
}
I have errors for the Form1 part of that call, how do I fix this???
Where you are passing Form1 frm you should actually pass a reference to an instance on Form1. Based on your comment to the suggestion of passing this it seems that the button handler is declared inside another form (not in Form1). If that's the case you should obtain/keep a reference to a Form1 instance and pass that in:
CheckXWinner(buttonArray, a_ref_to_form);
However, looking at your implementation of CheckXWinner it doesn't look like you are referencing frm anywhere anyway!
Rewrite the declaration of CheckXWinner as
public void CheckXWinner(Button[] buttonArray)
And call it like this:
CheckXWinner(buttonArray);
frm isn't declared anywhere when you pass it as a parameter.
pass "this" instead of Form1 frm.