10
\$\begingroup\$

This is a game that is supposed to be based on strategy and guessing.

The letters need to match in a ABCD fashion on each button on buttons[0] - buttons[3] ... and buttons[n] - buttons[n] in each square, kind of like a matrix, although there is no matrix math involved.

This is how the game starts:

Initial state - showing 4 groups of 4 buttons, bottom-left group highlighted in green

Each time a user clicks the "A" button, the buttons' text changes for all the buttons[n] in the ABCD sequence, and to win you need to match each square of controls to the ABCD sequence.

Winning screen - showing identical pattern in all 4 button groups

Any help in how to improve this code is welcome. Most of it is just code for WinForms, but the implementation of checkForWins really feels like it can be done better.

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 Game
{
    public partial class Form1 : Form
    {
        Button[] buttons = new Button[16];

        public Form1()
        {
            InitializeComponent();
            grid();
            MessageBox.Show("Find the pattern");
        }

        public void grid() {
            for (int i = 0; i < buttons.Length; i++) {
                buttons[i] = new Button();
            }

            for (int i = 0; i < 4; i++) {
                buttons[i].MouseEnter += new EventHandler(HighLightm1);
                buttons[i].MouseLeave += new EventHandler(unhighlightm1);
            }

            for (int i = 4; i < 8; i++) {
                buttons[i].MouseEnter += new EventHandler(highlightm2);
                buttons[i].MouseLeave += new EventHandler(unhighlightm2);
            }


            for (int i = 8; i < 12; i++) {
                buttons[i].MouseEnter += new EventHandler(highlightm3);
                buttons[i].MouseLeave += new EventHandler(unhighlightm3);
            }


            for (int i = 12; i < 16; i++) {
                buttons[i].MouseEnter += new EventHandler(highlightm4);
                buttons[i].MouseLeave += new EventHandler(unhightlightm4);
            }


            buttons[0].Parent = this;
            buttons[0].Location = new Point(10, 10);
            buttons[0].Size = new Size(60, 60);
            buttons[0].Click += new EventHandler(button1click);
            buttons[1].Parent = this;
            buttons[1].Location = new Point(70, 10);
            buttons[1].Size = new Size(60, 60);
            buttons[1].Click += new EventHandler(button2click);
            buttons[2].Parent = this;
            buttons[2].Location = new Point(10, 70);
            buttons[2].Size = new Size(60, 60);
            buttons[2].Click += new EventHandler(button3click);
            buttons[3].Parent = this;
            buttons[3].Location = new Point(70, 70);
            buttons[3].Size = new Size(60, 60);
            buttons[3].Click += new EventHandler(button4click);


            buttons[4].Parent = this;
            buttons[4].Location = new Point(140, 10);
            buttons[4].Size = new Size(60, 60);
            buttons[4].Click += new EventHandler(button5click);
            buttons[5].Parent = this;
            buttons[5].Location = new Point(200, 10);
            buttons[5].Size = new Size(60, 60);
            buttons[5].Click += new EventHandler(button6click);
            buttons[6].Parent = this;
            buttons[6].Location = new Point(140, 70);
            buttons[6].Size = new Size(60, 60);
            buttons[6].Click += new EventHandler(button7click);
            buttons[7].Parent = this;
            buttons[7].Location = new Point(200,70);
            buttons[7].Size = new Size(60, 60);
            buttons[7].Click += new EventHandler(button8click);


            buttons[8].Parent = this;
            buttons[8].Location = new Point(10, 140);
            buttons[8].Size = new Size(60, 60);
            buttons[8].Click += new EventHandler(button9click);
            buttons[9].Parent = this;
            buttons[9].Location = new Point(70, 140);
            buttons[9].Size = new Size(60, 60);
            buttons[9].Click += new EventHandler(button10click);
            buttons[10].Parent = this;
            buttons[10].Location = new Point(10, 200);
            buttons[10].Size = new Size(60, 60);
            buttons[10].Click += new EventHandler(button11click);
            buttons[11].Parent = this;
            buttons[11].Location = new Point(70, 200);
            buttons[11].Size = new Size(60, 60);
            buttons[11].Click += new EventHandler(button12click);


            buttons[12].Parent = this;
            buttons[12].Location = new Point(140, 140);
            buttons[12].Size = new Size(60, 60);
            buttons[12].Click += new EventHandler(button13click);
            buttons[13].Parent = this;
            buttons[13].Location = new Point(200, 140);
            buttons[13].Size = new Size(60, 60);
            buttons[13].Click += new EventHandler(button14click);
            buttons[14].Parent = this;
            buttons[14].Location = new Point(140, 200);
            buttons[14].Size = new Size(60, 60);
            buttons[14].Click += new EventHandler(button15click);
            buttons[15].Parent = this;
            buttons[15].Location = new Point(200, 200);
            buttons[15].Size = new Size(60, 60);
            buttons[15].Click += new EventHandler(button16click);
        }

        public void button1click(object sender, EventArgs e) {
            buttons[0].Text = "D";
            buttons[1].Text = "A";
            buttons[2].Text = "B";
            buttons[3].Text = "C";
        }
        public void button2click(object sender, EventArgs e) {
            buttons[0].Text = "C";
            buttons[1].Text = "D";
            buttons[2].Text = "A";
            buttons[3].Text = "B";

        }
        public void button3click(object sender, EventArgs e) {
            buttons[0].Text = "B";
            buttons[1].Text = "C";
            buttons[2].Text = "D";
            buttons[3].Text = "A";
        }
        public void button4click(object sender, EventArgs e) {
            buttons[0].Text = "A";
            buttons[1].Text = "B";
            buttons[2].Text = "C";
            buttons[3].Text = "D";
            checkForWins();
        }

        public void button5click(object sender, EventArgs e) {
            buttons[4].Text = "C";
            buttons[5].Text = "D";
            buttons[6].Text = "A";
            buttons[7].Text = "B";
        }
        public void button6click(object sender, EventArgs e)
        {
            buttons[4].Text = "B";
            buttons[5].Text = "C";
            buttons[6].Text = "D";
            buttons[7].Text = "A";
        }
        public void button7click(object sender, EventArgs e)
        {
            buttons[4].Text = "A";
            buttons[5].Text = "B";
            buttons[6].Text = "C";
            buttons[7].Text = "D";
            checkForWins();

        }
        public void button8click(object sender, EventArgs e)
        {
            buttons[4].Text = "D";
            buttons[5].Text = "A";
            buttons[6].Text = "B";
            buttons[7].Text = "C";
        }

        public void button9click(object sender, EventArgs e) {
            buttons[8].Text = "B";
            buttons[9].Text = "C";
            buttons[10].Text = "D";
            buttons[11].Text = "A";
        }
        public void button10click(object sender, EventArgs e)
        {
            buttons[8].Text = "A";
            buttons[9].Text = "B";
            buttons[10].Text = "C";
            buttons[11].Text = "D";
            checkForWins();
        }
        public void button11click(object sender, EventArgs e)
        {
            buttons[8].Text = "D";
            buttons[9].Text = "A";
            buttons[10].Text = "B";
            buttons[11].Text = "C";
        }
        public void button12click(object sender, EventArgs e)
        {
            buttons[8].Text = "C";
            buttons[9].Text = "D";
            buttons[10].Text = "A";
            buttons[11].Text = "B";
        }
        public void button13click(object sender, EventArgs e)
        {
            buttons[12].Text = "A";
            buttons[13].Text = "B";
            buttons[14].Text = "C";
            buttons[15].Text = "D";
            checkForWins();
        }
        public void button14click(object sender, EventArgs e)
        {
            buttons[12].Text = "D";
            buttons[13].Text = "A";
            buttons[14].Text = "B";
            buttons[15].Text = "C";
        }
        public void button15click(object sender, EventArgs e)
        {
            buttons[12].Text = "C";
            buttons[13].Text = "D";
            buttons[14].Text = "A";
            buttons[15].Text = "B";
        }
        public void button16click(object sender, EventArgs e)
        {
            buttons[12].Text = "B";
            buttons[13].Text = "C";
            buttons[14].Text = "D";
            buttons[15].Text = "A";
        }

        public void checkForWins() {
            if (buttons[0].Text == "A" && buttons[1].Text == "B" && buttons[2].Text == "C" && buttons[3].Text == "D")
                if (buttons[4].Text == "A" && buttons[5].Text == "B" && buttons[6].Text == "C" && buttons[7].Text == "D")
                    if(buttons[8].Text == "A" && buttons[9].Text == "B" && buttons[10].Text == "C" && buttons[11].Text == "D")
                        if (buttons[12].Text == "A" && buttons[13].Text == "B" && buttons[14].Text == "C" && buttons[15].Text == "D") {
                            MessageBox.Show("You Won !");
                            for (int i = 0; i < buttons.Length; i++) {
                                buttons[i].Text = "";
                            }
                        }
        }
        public void HighLightm1(object sender, EventArgs e)
        {
            for (int i = 0; i < 4; i++) {
                buttons[i].BackColor = Color.RoyalBlue;
            }
        }
        public void unhighlightm1(object sender, EventArgs e) {
            for (int i = 0; i < 4; i++) {
                buttons[i].BackColor = Color.White;
            }
        }

        public void highlightm2(object sender, EventArgs e) {
            for (int i = 4; i < 8; i++) {
                buttons[i].BackColor = Color.Salmon;
            }
        }

        public void unhighlightm2(object sender, EventArgs e)
        {
            for (int i = 4; i < 8; i++) {
                buttons[i].BackColor = Color.White;
            }
        }

        public void highlightm3(object sender, EventArgs e) {
            for (int i = 8; i < 12; i++) { 
                buttons[i].BackColor = Color.ForestGreen;
            }
        }
        public void unhighlightm3(object sender, EventArgs e) {
            for (int i = 8; i < 12; i++) {
                buttons[i].BackColor = Color.White;
            }
        }

        public void highlightm4(object sender, EventArgs e) {
            for (int i = 12; i < 16; i++) {
                buttons[i].BackColor = Color.Orange;
            }
        }
        public void unhightlightm4(object sender, EventArgs e) {
            for (int i = 12; i < 16; i++) {
                buttons[i].BackColor = Color.White;
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
        }
    }
}
\$\endgroup\$
10
\$\begingroup\$

Naming.

    public partial class Form1 : Form

Make it a habit to name things. Even MainForm or GameForm would have been nice.

Naming is hard though.

There are only two hard things in Computer Science: cache invalidation and naming things.

-- Phil Karlton

But really, it's worth even just trying to get right. Readable code loves good naming.


public void grid()

Per Method Naming Guidelines, method names in C# should be PascalCase, and should start with a verb.


Partial.

    public partial class Form1 : Form

The Form1 class is partial: its definition is split between multiple files - in this case I'd wager the rest of the class is defined in the auto-generated Form1.Designer.cs.

That's where InitializeComponent is defined:

public Form1()
{
    InitializeComponent();
    //...
}

If you navigate to that .Designer.cs generated code, you'll see this:

/// <summary> 
/// Required method for Designer support - do not modify 
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()

The entire grid() method is the kind of code typically seen there. There's a reason a missing parameterless constructor and/or a call to InitializeComponent() in that constructor, breaks the designer: Visual Studio not only generates, but also runs this code.

By defining your buttons in the InitializeComponent() method, you effectively remove this UI boilerplate from the interesting code, and as a bonus the form designer starts looking very much like the runtime one.

I would have used the designer, and let that code be generated.


Layout.

Your layout doesn't scale. If you didn't use the designer at all, and haven't manually modified the Form1.Designer.cs file, then the user can resize the form and... totally wreck your UI.

Use the Container controls WinForms has to offer - in this case a TableLayoutPanel with fully anchored buttons would have greatly simplified the layout - here a 4x4 grid; the form's MinSize is set to 200x200:

200x200 grid same grid, stretched horizontally. buttons resize to maintain the margins


Implementation.

This leaves us with the click handlers for the buttons, the checkForWins() method, and this:

private void Form1_Load(object sender, EventArgs e)
{
}

I don't see that handler registered anywhere. This tells me that you created the form, and then double-clicked the designer to bring up the code; that registered the Load event and added a handler stub, and now the code won't build if you remove it. Right? Use the events view in the property window to locate the form's Load event - and remove it from there. Then you can remove the handler and build.

Don't keep empty methods around. Dead code is confusing.


What's missing is an abstraction level here: your code has 16 buttons, but the problem has 4 groups of 4 buttons.

You could create a UserControl to represent a group of 4 buttons, the TableLayoutPanel can now be a 2x2 grid instead of 4x4. And it would be easier to get the proper margins, and each control would handle its own buttons.

The one can implement some model to centralize the state, and have each control (/group of 4 buttons) delegate their click handler logic to the actual form; that would be a good start IMO.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.