Create a Simon Says Style Game in Windows Forms and C# with Visual Studio
- Subject: C# Tutorials
- Learning Time: 2 hours
Hi, in this tutorial we will make a Simon Says style using windows form and C# programming. This game was a fun problem to solve as it required some out of the box thinking. In the beginning the idea was simple the game picks 3 blocks from the screen on 4×4 grid. We save the sequence and we need to blink those blocks to change colour in the same sequence so the user will know which box the game picked. First problem to solve was how to save the sequence information for the player and the game also we needed to figure out how to do the blink animation for the picture boxes. It was challenging but the solution turned out how to be more simple than the problem. We wanted to strictly use 1 timer in the game so this way we don’t need to keep starting and stopping multiple timers in the form so in this game we will use one timer but keep track of the blinking animation using a simple switch statement. Also we managed to make the game so when you score 3 it will level up by one so the game becomes more challenging the more you play it. We hope you find this tutorial useful and also you can make a lot more projects using the similar methods as this tutorial. Keep learning and keep making things.
Lesson Objectives:
- Create a Simon Says Style in Windows Form and C#
- Generate a 4×4 Grid of picture boxes through the code
- Add Click events to those picture boxes
- Assign a random colour each time the start button is clicked on those picture boxes
- Allow the game to randomly pick 3 picture boxes
- Animate those picture boxes by changing their colour to white in sequential animation
- Allow the player to follow that sequence and click on the picture boxes
- if the sequences match then show a message box of success
- If player score 3 then move up one level and add one more box to the sequence
Video Tutorial
Get Simon Says C# Game on GitHub
Simon Says Game Source Code Explained
Variables
int blocksX = 160; int blocksY = 80; int score = 0; int level = 3; List<PictureBox> pictureBoxes = new List<PictureBox>(); List<PictureBox> chosenBoxes = new List<PictureBox>(); Random rnd = new Random(); Color temp; int index = 0; int tries = 0; int timerLimit = 0; bool selectingColours = false; string correctOrder = string.Empty; string playerOrder = string.Empty;
In the context of a Simon Says style game developed in Windows Forms and C#, the provided variables serve fundamental roles in managing various aspects of gameplay.
The integer variables “blocksX” and “blocksY” denote the dimensions of the game blocks or tiles on the game board. These values determine the layout and positioning of the PictureBoxes representing the game elements within the game interface, ensuring a visually coherent and organized presentation of the game environment.
The “score” variable, also an integer, tracks the player’s progress by storing their current score throughout the game. As the player successfully completes tasks or levels, this variable is updated accordingly, providing feedback on the player’s performance and accomplishments.
Similarly, the “level” variable, another integer, indicates the current level of difficulty in the game. By adjusting factors such as the number of blocks to be memorized or the speed of gameplay, this variable influences the overall challenge presented to the player, ensuring an engaging and dynamic gameplay experience.
The lists “pictureBoxes” and “chosenBoxes” consist of PictureBox objects representing the game blocks on the game board and the blocks chosen by the player during gameplay, respectively. These lists facilitate the management and manipulation of game elements, enabling interactions between the player and the game environment.
The “rnd” variable, an instance of the Random class, is employed to generate random numbers within the game. It plays a crucial role in tasks such as selecting random blocks for the game sequence or generating random colors, enhancing the unpredictability and variability of the gameplay.
Additionally, the “temp” variable, of type Color, serves as temporary storage for colors during certain operations within the game logic, facilitating color manipulation and transitions between different game states.
The integer variables “index” and “tries” are utilized to track the current position in the game sequence and the number of attempts made by the player, respectively. These variables are essential for managing the game flow and determining the player’s progress and performance within the game environment.
Furthermore, the “timerLimit” and “selectingColours” variables control aspects of game timing and state, influencing game behavior and player interactions based on the current game mode or stage.
Lastly, the string variables “correctOrder” and “playerOrder” store the correct sequence of blocks chosen by the game and the sequence of blocks chosen by the player, respectively. These variables play a pivotal role in verifying the player’s input against the correct sequence and determining the outcome of the player’s actions within the game.
Form 1 Constructor
public Form1() { InitializeComponent(); SetUpBlock(); }
In the Form1 constructor of the Windows Forms application, two important tasks are performed sequentially. Firstly, the InitializeComponent() method is called to initialize the visual components of the form, including buttons, labels, and other controls, as defined in the form’s design.
Subsequently, the SetUpBlock() function is invoked. This function is responsible for setting up the game environment by creating PictureBoxes to represent the game blocks or tiles on the game board. The creation of these PictureBoxes is crucial for visualizing the game elements and enabling player interactions within the game interface.
By calling the SetUpBlock() function within the Form1 constructor, the program ensures that the necessary setup procedures for the game environment are executed automatically when the form is initialized or loaded. This structured approach enhances the efficiency and organization of the codebase, as it centralizes the setup logic within the constructor, simplifying maintenance and future modifications to the application.
Overall, the sequential execution of InitializeComponent() and SetUpBlock() in the Form1 constructor plays a pivotal role in preparing the game environment and initializing the visual elements of the form, facilitating the smooth operation of the game and providing players with an immersive gaming experience.
Set Up Blocks function
private void SetUpBlock() { for (int i = 1; i < 17; i++) { PictureBox newPic = new PictureBox(); newPic.Name = "pic_" + i; newPic.Height = 60; newPic.Width = 60; newPic.BackColor = Color.Black; newPic.Left = blocksX; newPic.Top = blocksY; newPic.Click += ClickOnPictureBox; if (i == 4 || i == 8 || i == 12) { blocksY += 65; blocksX = 160; } else { blocksX += 65; } this.Controls.Add(newPic); pictureBoxes.Add(newPic); } }
The SetUpBlock() function is responsible for creating and configuring PictureBoxes to represent game blocks or tiles on the game board. Let’s break down the function:
- For Loop: The function iterates through a loop 16 times, creating PictureBoxes for each block in the game. The loop starts from 1 and runs until 16.
- PictureBox Creation: Within each iteration, a new PictureBox object named “newPic” is created. It is initialized with specific properties such as Name, Height, Width, and BackgroundColor.
- Positioning: The position of the PictureBox is determined based on the variables “blocksX” and “blocksY”. Initially, these variables are set to 160 and 80, respectively. As PictureBoxes are created, their position is adjusted accordingly to form a grid-like layout.
- Click Event: A Click event handler named ClickOnPictureBox is attached to each PictureBox. This event handler will be triggered when the player clicks on a PictureBox during gameplay.
- Grid Layout: Conditional statements inside the loop adjust the values of “blocksX” and “blocksY” to ensure proper positioning of PictureBoxes in a grid layout. When PictureBoxes reach the end of a row, “blocksY” is incremented to move to the next row, while “blocksX” is reset to the initial position.
- Adding PictureBoxes to Controls: Each PictureBox created within the loop is added to the form’s Controls collection using the Controls.Add() method. Additionally, each PictureBox is added to the “pictureBoxes” list for further manipulation during gameplay.
The ClickOnPictureBox() function serves as the event handler for the Click event of PictureBoxes. It allows handling player interactions with the PictureBoxes during the game. When a PictureBox is clicked, its background color is changed to black, indicating player interaction. Additionally, the name of the clicked PictureBox is appended to the “playerOrder” string, and the “tries” counter is incremented.
Overall, the SetUpBlock() function is essential for initializing the game environment by creating and configuring PictureBoxes, while the ClickOnPictureBox() function enables player interactions with the PictureBoxes during gameplay.
Button Click Event
private void ButtonClickEvent(object sender, EventArgs e) { if (score == 3 && level < 7) { level++; score = 0; } correctOrder = string.Empty; playerOrder = string.Empty; chosenBoxes.Clear(); chosenBoxes = pictureBoxes.OrderBy(x => rand.Next()).Take(level).ToList(); for (int i = 0; i < chosenBoxes.Count; i++) { correctOrder += chosenBoxes[i].Name + " "; } foreach (PictureBox x in pictureBoxes) { x.BackColor = Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256)); } Debug.WriteLine(correctOrder); index = 0; timeLimit = 0; selectingColours = true; GameTimer.Start(); }
The button1_Click event handler is triggered when the player clicks on Button 1 within the Windows Forms application. Let’s analyze the function:
- Condition Check: The function begins with a conditional check to determine if the player’s score equals 3 and if the current level is less than 7. If both conditions are met, the level is incremented by 1, and the player’s score is reset to 0. This logic likely represents an advancement mechanism where the player progresses to the next level after achieving a certain score threshold.
- Initialization: The variables “correctOrder” and “playerOrder” are cleared, and the “chosenBoxes” list is cleared and then populated with a randomized selection of PictureBoxes from the “pictureBoxes” list. The number of PictureBoxes chosen is determined by the “level” variable. These PictureBoxes represent the blocks or tiles that the player needs to memorize and interact with during the game.
- Generating Correct Order: A loop iterates through the chosen PictureBoxes, appending their names to the “correctOrder” string. This string represents the correct sequence of blocks chosen for the current game round.
- Color Assignment: Each PictureBox in the “pictureBoxes” list has its background color set to a random RGB color using the Color.FromArgb() method. This step likely serves to visually indicate to the player the blocks they need to remember for the current game round.
- Debugging Output: The “correctOrder” string is written to the debug output window for debugging purposes, providing insight into the correct sequence of blocks chosen for the current round.
- Resetting Game State: The “index” and “timerLimit” variables are reset to 0, indicating the beginning of a new game round. The “selectingColours” variable is set to true, indicating that the player is currently in the mode of selecting colors. Lastly, the GameTimer is started, initiating the countdown for the player to memorize and interact with the blocks.
In summary, the button1_Click event handler plays a crucial role in initiating a new game round, advancing the player to the next level if certain conditions are met, and preparing the game environment for the player’s interaction by selecting and displaying the blocks for memorization.
Click on Picture Box Event –
private void ClickOnPictureBox(object? sender, EventArgs e) { if (!selectingColours && chosenBoxes.Count > 1) { PictureBox temp = sender as PictureBox; temp.BackColor = Color.Black; playerOrder += temp.Name + " "; Debug.WriteLine(playerOrder); tries++; } else { return; } }
The ClickOnPictureBox method serves as an event handler for the Click event associated with PictureBox controls in a Windows Forms application. Let’s break down the functionality in a formal manner:
- Conditional Check: The method begins with a conditional statement to verify whether the game is currently in the state of selecting colors (selectingColours variable is false) and if there are at least two PictureBoxes chosen for the game sequence (chosenBoxes.Count > 1).
- PictureBox Identification: If the conditions are met, the PictureBox control that triggered the event is identified and assigned to the “temp” variable using the “as” operator. This variable represents the PictureBox that the player has clicked on during gameplay.
- Updating Player Input: The background color of the clicked PictureBox is changed to black, indicating the player’s selection. Additionally, the name of the PictureBox, representing its position or identity in the game sequence, is appended to the “playerOrder” string. This string likely maintains the sequence of player-selected PictureBoxes for comparison with the correct sequence later in the game.
- Incrementing Tries: The “tries” counter is incremented to keep track of the number of attempts made by the player to replicate the correct sequence.
- Debugging Output: For debugging purposes, the current “playerOrder” string is written to the debug output window, providing insight into the sequence of PictureBoxes selected by the player during gameplay.
- Conditional Return: If the game is currently in the state of selecting colors or if there are fewer than two PictureBoxes chosen for the game sequence, the method exits early without executing further logic.
In summary, the ClickOnPictureBox method allows the player to interact with the game by selecting PictureBoxes during the gameplay phase where the player must replicate a sequence of colors. It handles the updating of player input, tracks the number of attempts, and provides debugging output for monitoring the player’s actions within the game.
Game Timer Event
private void GameTimerEvent(object sender, EventArgs e) { if (selectingColours) { timeLimit++; switch (timeLimit) { case 10: temp = chosenBoxes[index].BackColor; chosenBoxes[index].BackColor = Color.White; break; case 20: chosenBoxes[index].BackColor = temp; break; case 30: chosenBoxes[index].BackColor = Color.White; break; case 40: chosenBoxes[index].BackColor = temp; break; case 50: if (index < chosenBoxes.Count - 1) { index++; timeLimit = 0; } else { selectingColours = false; } break; } } if (tries >= level) { if (correctOrder == playerOrder) { tries = 0; GameTimer.Stop(); MessageBox.Show("Well done, you got them correctly.", "MOO Says: "); score++; } else { tries = 0; GameTimer.Stop(); MessageBox.Show("Your guesses did not match, try again.", "MOO Says: "); } } lblInfo.Text = "Click on " + level + " blocks in the same sequence."; }
The GameTimerEvent method is an event handler that responds to ticks from a timer control named GameTimer. It is a crucial part of the game logic in a Simon Says style game implemented in Windows Forms and C#. Let’s break down the code:
- Checking Selecting Colors State: The method starts by checking if the game is currently in the state of selecting colors. If the selectingColours variable is true, it proceeds with the logic for displaying colors.
- Incrementing Timer Limit: The timerLimit variable is incremented with each tick of the timer, effectively counting the time elapsed since the start of color display.
- Switch Statement: The switch statement is used to manage different stages of color display. At specific intervals of the timerLimit, the background color of the chosen PictureBox is modified to create a flashing effect, revealing the sequence of colors to the player. The chosen PictureBox is determined by the index variable.
- At timerLimit 10 and 30, the color of the chosen PictureBox is set to white, creating a brief pause in color display.
- At timerLimit 20 and 40, the original color of the chosen PictureBox is restored, simulating a flash effect.
- Progressing Through the Sequence: As the timerLimit reaches 50, the method checks if there are more PictureBoxes in the chosen sequence to display. If so, it moves to the next PictureBox in the sequence by incrementing the index variable and resetting the timerLimit. If all PictureBoxes have been displayed, the selectingColours variable is set to false, indicating that the player can now input their guesses.
- Checking Player Input: After the player has inputted their guesses, the method checks if the number of tries matches the level of difficulty. If the player has made the correct guesses according to the displayed sequence, a success message is displayed, and the player’s score is incremented. Otherwise, a failure message is shown, prompting the player to try again.
- Updating User Interface: The lblinfo label control is updated to provide instructions to the player, indicating how many blocks they need to click on and in what sequence.
In summary, the GameTimerEvent method controls the timing and progression of color display during the game, facilitates player input validation, and provides feedback to the player through visual cues and messages.