Click here to Skip to main content
15,939,736 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
Hello reader,

I'm trying to make a little puzzle game "Connect the dots".
And I have the following problem:
What I'm trying to do is to get a score value (property ScoreCounter(in class Grid.cs)) on my form (most likely showable with a label).
I tried to make scoreCounter public just to test it out, and I also tried to make a property which didn't work aswell.
I tried debugging and I saw that when the player is suppose to obtain a point when crossing a dot the value of scoreCounter actually increments within the condition.
But when I place a breakpoint at the top where I declared the score, it tells me it has no value.
Could someone please help me to obtain the score so I can display it in a label?
Many thanks in advance!
Debug example


This is how the code looks like:

At the top of the class Form
private Grid drawing;


Somewhere in the class Form
lblScore.Text = "Score: " + Convert.ToString(drawing.ScoreCounter);


Class Grid.cs
private int scoreCounter;
public int ScoreCounter
{
    get { return scoreCounter; }
    set { scoreCounter = value; }
}


protected override void OnMouseUp(MouseEventArgs e)
{
    base.OnMouseUp(e);  //On Panel
    var dotLocation = this.GetDotFromPoint(e.Location); //checks if graphic location is a dot

    // If the first holded dot is color green
    if (lastDot.DotColor == colorGreen)
    {
        firstGreen = true;
    }

    if (firstGreen)
    {
        // Checks if MouseUp is on a dot that isn't colored red
        // Checks if the user doesn't skip a dot
        // Checks if the user doesn't cross a dot diagonally (only allows horizontally)
        if (dotLocation != null && lastDot != null && dotLocation.DotColor != colorRed &&
       ((lastDot.Center.X + 40 == dotLocation.Center.X) || (lastDot.Center.X - 40 == dotLocation.Center.X)) &&
       (lastDot.Center.Y == dotLocation.Center.Y))
        {

            scoreCounter += 1;
            Line line = new Line();
            line.X1 = lastDot.Center.X;
            line.Y1 = lastDot.Center.Y;

            line.X2 = dotLocation.Center.X;
            line.Y2 = dotLocation.Center.Y;
            this.markers.Add(line);
            Invalidate();
        }

        // Checks if MouseUp is on a dot that isn't colored red
        // Checks if the user doesn't skip a dot
        // Checks if the user doesn't cross a dot diagonally (only allows vertically)
        else if (dotLocation != null && lastDot != null && dotLocation.DotColor != colorRed &&
            ((lastDot.Center.Y + 40 == dotLocation.Center.Y) || (lastDot.Center.Y - 40 == dotLocation.Center.Y)) &&
            (lastDot.Center.X == dotLocation.Center.X))
        {
            scoreCounter += 1;
            Line line = new Line();
            line.X1 = lastDot.Center.X;
            line.Y1 = lastDot.Center.Y;

            line.X2 = dotLocation.Center.X;
            line.Y2 = dotLocation.Center.Y;
            this.markers.Add(line);
            Invalidate();
        }
        else
        {
            MessageBox.Show("Invalid turn, try again.");
        }
    }
}


I also have the idea that whatever I'm trying to in the Form like for example calling a method in the class Grid it doesn't work.
I tested it by trying to clear the list markers by doing the following thing:

In Form calling the following method
drawing.ClearLines();


And in class Grid.cs
public void ClearLines()
{
    markers.Clear();
    scoreCounter = 0;
    Invalidate();
}


I also called the same method in the method OnMouseUp

else
{
    MessageBox.Show("Invalid turn, try again.");
    ClearLines() // or markers.Clear();
}


It all doesn't work.
Posted
Updated 13-May-11 4:24am
v9

Did you say you set a break point on the line where you declared the score property? If so, does your breakpoint get hit whenever that variable is changed? I would expect not if it is on the variable declaration. This would mean that it is hit once when it is first initialised - so that value would be seen as null until you have stepped over that line - i.e. until you have initialised it. Your code should probably be something like the following for this situation:

C#
private int scoreCounter;
public int ScoreCounter
{
    get
    {
        //Do anything extra then:
        return scoreCounter;
    }
    set
    {
        //Do anything extra then:
        scoreCounter = value;
        //Then do anything else
    }
} 


Note: The 'do anything extras' should be anything directly related to the scoreCounter - do not put long code that should be in a method. This also avoids the risk of long code causing an infinite loop by say calling the ScoreCounter:get within another ScoreCounter:get call.

Also, ALL your should use the ScoreCounter property, not the provate, lower case scoreCounter property.

Hope this helps,

Ed :)
 
Share this answer
 
Comments
Makiguso 12-May-11 18:57pm    
Thank you for your time.
And I already tried making scoreCounter into a property but that didn't fix it.
I did declare the scoreCounter properly, and I also put a breakpoint at
private int scoreCounter;

It said the following thing:
The breakpoint will not currently be hit. No executable code is associated with this line. Possible causes include: conditional compilation or compilar optimization.

So that didn't help much..
Also the scoreCounter in the method MouseDown did increment scoreCounter everytime I created a line between two dots (checked with breakpoints).

Yet it doesn't pass the new value to my form.. Even when using a property
Ed Nutting 14-May-11 5:38am    
Sorry just seen your debug example - weird that this doesn't work. Could you put a link to ALL your code so I could try compiling it and looking at the problem?
Ed Nutting 14-May-11 5:44am    
Looking at your code, in Grid.cs you override OnMouseUp, but what did your Grid class inherit from??? Also, you seem to mix up using scoreCounter and ScoreCounter. I suggest sticking to using one - ScoreCounter, it is easier to debug. Try checking all references to scoreCounter and seeing if any set it to 0 where it should, or put a brwak point on every point where scoreCounter and ScoreCounter get set/incremented to check what values are set and see if any are 0.
Maybe you just misplaced this line:
C#
lblScore.Text = "Score: " + Convert.ToString(drawing.ScoreCounter);

Where did you put this line?

Whenever ScoreCounter value changes, you should update the Text property of your label as well. Make sure the text update statement is called after you update the score. I don't see any reason why it shouldn't work.

---------------------------------

So it means you have several instances of the class implementing the ScoreCounter:
I think you are updating one of the instances, but you are displaying another one.

Check carefully where you instanciate these objects and make sure the objects you update and display are the same.
 
Share this answer
 
v2
Comments
Makiguso 13-May-11 10:08am    
Thank you for your time Olivier,

Okay in my form I used a timer to count the seconds and convert them into hours minutes seconds etc. I also added the lblScore.Text in it.
Here is how it looks like.

///
/// Counts every second
///

/// <param name="sender"></param>
/// <param name="e"></param>
private void timer_Tick(object sender, EventArgs e)
{
totalSeconds++;
hours = (totalSeconds / 3600);
remaining = (totalSeconds - (hours * 3600));
minutes = remaining / 60;
seconds = remaining % 60;

lblTimer.Text = "Time elapsed: " +
Convert.ToString(hours) + "h " +
Convert.ToString(minutes) + "m " +
Convert.ToString(seconds) + "s ";

lblScore.Text = "Score: " + Convert.ToString(drawing.ScoreCounter);
}

Believe me you're not the only one who doesn't see any reason why it shouldn't work..
The funny part is when the seconds gets displayed into h,m,s properly how it should,
but value of drawing.ScoreCounter does not. It keeps showing value 0 ...
Its sorta funny to see how it doesn't work but also frustrating LOL
Regarding your breakpoint not being hit:

The others have touched on why your breakpoint wasn't being hit; adding my own take on the problem: I think what is happening is that you are assigning to scoreCounter (the backing variable) - which will not cause the code of the ScoreCounter (property) set accessor method to be executed.

Regarding the UI not being updated with the score:

I would take the following steps to diagnose why the score is not being displayed:

  1. Delete the backing store for ScoreCounter and make ScoreCounter an 'auto-property' (i.e. one where the compiler creates the backing variable for the property). This will prevent any confusion beween assigning to the backing store vs. to the property.
    This step is not crucial (and you can only do it because you're not doing work in either of the accessors), but it makes the code cleaner so it helps.
  2. Search for all references to the ScoreCounter property.

    • Look at all places where the property is assigned: are there any places where it is getting assigned zero?
    • Put breakpoints on all assignments and see what is happening.
  3. Extend your search for all places where the word 'ScoreCounter' is found. Perhaps you have properties of that name in multiple different classes, and you're referencing the wrong one by accident?
  4. Search for all places where lblScore.Text is assigned and put breakpoints on each of them. (To make debugging easier, and if lblScore.Text is updated in places other than the timer code, I might drop the timer tick interval to 30 seconds, so that you don't continually get hit with timer ticks when you want to see what else is happening.)

Hope that helps.
Chris
 
Share this answer
 
v3
Comments
Makiguso 13-May-11 12:53pm    
Hello Chris, and thank you for your time.

1. I'm not really sure what you mean with "Backing store".
I used the Refactor - Encapsulate Field function in Visual Studio to create the property of "private int scoreCounter;.
And it looks like this:

///
/// Property gets and sets the scoreCounter
///

public int ScoreCounter
{
get { return scoreCounter; }
set { scoreCounter = value; }
}

2 When I checked for all references there were only 2 results.
"Form1.cs - (118, 66) : lblScore.Text = "Score: " + Convert.ToString(drawing.ScoreCounter);"

And
"Grid.cs - (244, 20) : public int ScoreCounter"

My 2 other classes Dot.cs and Line.cs don't contain any scores so theres no need for a property of scoreCounter in those 2 classes.

3. Not much to extend my search for if there's only 2 references.
4. Used the search through the whole project and only Form contains lblScore.Text

I have absolutely no clue what to do next...
Chris Trelawny-Ross 13-May-11 14:34pm    
'backing store' is the name given to the private field that is used to actually store the value that a property represents. So, for your ScoreCounter property, the backing store is the 'scoreCounter' variable. The naming comes from the fact that the variable is real storage, that 'backs' the property (i.e. does the real work of the property!) - since the property itself is not truly storage although it is used as if it is a variable of some kind.

Have you tried putting a breakpoint in the timer event handler? If you also put a breakpoint in the mouse move, and set the timer period to, say, 10 seconds, you can (a) force a value into the ScoreCounter (when the mouseMove breakpoint is hit) then (b) when the timer breakpoint is hit look to see if the value is still there.

Am I right in thinking that the mouse move handler is the only place that the score is modified? If not, you should put breakpoints on all the other places that the score is modified. If one of those breakpoints is hit you may have discovered the cause of the problem.

Let me know what you discover.
Chris Trelawny-Ross 13-May-11 14:38pm    
Also (re properties and backing store)...

An 'auto property' is one that is declared like this:

public int ScoreCounter { get; set; }

There is an implicit private field 'scoreCounter' created by the compiler for a property declared like this.

I don't think that Visual Studio has a refactoring that converts a property with backing store to an auto-property. You might download the trial version of Resharper (from JetBrains). It has some awesome refactorings, including the one I mentioned. It also has some really good code inspections - and a handy right margin that if it comes up green you know your code is as 'clean'.
Makiguso 15-May-11 10:13am    
I'm using Visual Studio 2010, and just used the refactor option in order to make a property. It automatically created the following:
public int ScoreCounter
{
get { return scoreCounter; }
set { scoreCounter = value; }
}

And I don't see any reason why I should put a breakpoint in the time event handler if that part works (Its counting the seconds as it should). Altho I did try it out and it showed me that the value of ScoreCounter still was 0. I also tried your approach of using a auto property:
public int ScoreCounter { get; set; }

right after the scoreCounter was incremented I did:
ScoreCounter = scoreCounter;

And you're right about the mouse move (on click-drag-release).
The MouseUp is the only mouse event where the score is incremented.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900