views:

60

answers:

2

Hello All,
I'm a fairly inexperienced programmer, and i'm currently working on a Console Application project. It's basically a little 'mathematics game'; the application generates two random numbers, that have either been added, subtracted, multiplied or divided against each other randomly. The answer is shown on screen and the user has to pick from the menu which is the right mathematical operator, once the correct answer is picked the application then displays on screen how long it took for the user in milliseconds to input the correct answer.

Now I want to save the times of the players in an array that can be called up later with all the scores. I need to include a method in this programme and I figured a method to save the times into an array would be suitable. I seem to have stumbled across a little problem though.

I'm not quite sure what's wrong:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mathgame
{
    class Program
    {
    }

    class arrayclass
    {
        public static void saveInArray(int duration)
        {
            int[] TopTenScores = {000,1000,2000,3000,4000,5000,6000,7000,8000,9000};

            if (duration < 1000)
            {
                duration = TopTenScores[000];
            }
            else if ((duration >= 1000) && (duration <= 1999))
            {
                duration = TopTenScores[1000];
            }
            else if ((duration >= 2000) && (duration <= 2999))
            {
                duration = TopTenScores[2000];
            }
            else if ((duration >= 3000) && (duration <= 3999))
            {
                duration = TopTenScores[3000];
            }
            else if ((duration >= 4000) && (duration <= 4999))
            {
                duration = TopTenScores[4000];
            }
            else if ((duration >= 5000) && (duration <= 5999))
            {
                duration = TopTenScores[5000];
            }
            else if ((duration >= 6000) && (duration <= 6999))
            {
                duration = TopTenScores[6000];
            }
            else if ((duration >= 7000) && (duration <= 7999))
            {
                duration = TopTenScores[7000];
            }
            else if ((duration >= 8000) && (duration <= 8999))
            {
                duration = TopTenScores[8000];
            }
            else if ((duration >= 9000) && (duration <= 9999))
            {
                duration = TopTenScores[9000];
            }

            Console.WriteLine(TopTenScores);
        }

    static void Main(string[] args)
    {
        int intInput, num1, num2, incorrect, array1;
        float answer;
        string input;

        System.Random randNum = new System.Random();
        Console.WriteLine("Welcome to the Maths game!");
        Console.WriteLine("(Apologies for the glitchiness!)");
        Console.WriteLine();
        Console.WriteLine("Please choose from the following options:");
        Console.WriteLine();
    retry:
        Console.WriteLine("1 - Test your Maths against the clock!");
        Console.WriteLine("2 - Exit the application.");
        Console.WriteLine("3 - Top scores");
        Console.WriteLine();
        input = Console.ReadLine();
        intInput = int.Parse(input);

        if (intInput == 1)
        {
            goto start;
        }
        else if (intInput == 2)
        {
            goto fin;
        }
        else if (intInput == 3)
        {

            array1 = array1.saveInArray;

          goto retry;
        }

Now, in the last 'else if' statement in the code, you can see my variable array1 trying to call the method, but no matter what I do I keep getting errors.

This is the only error I have at the moment, but I have a feeling soon as I resolve that error, another will come up. For now i'm just determined to get past this error:

'int' does not contain a definition for 'saveInArray' and no extension method 'saveInArray' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?).

Any help would be kindly appreciated, apologies in advanced for my ugly written code! And thank you to any help that I receive!

Regards, Omar.

+4  A: 

Okay,

There's quite a bit in this code that needs fixing TBH.

I'll start with your error first:

You are declaring the variable array1 as an integer. In C# integers are primitive types. This means that they have no methods and no class members. So, when you call array1.saveInArray the compiler is basically saying "the type integer doesn't have any methods... I can't find an appropriate method to match your call".

Instead of calling array1.saveInArray I think what you meant to call was arrayclass.saveInArray(x).

Notice the x in that call above. I'm passing a variable called x which is of type int into the function saveInArray().

This brings us to the second error. If saveInArray was a property, then you could just go arrayclass.saveInArray. However, it is a function which requires an argument... namely an integer.

When you call arrayclass.saveInArray(someInteger) you are passing someInteger as an argument into a method. The method is then free to use this argument to do its calculations.

That should fix your most basic errors and hopefully you can compile.

Moving on to some other errors that will cause you problems at runtime:

In the method saveInArray you are declaring an integer array called TopTenScores.

You are declaring this fine... however later on when you are indexing into TopTenScores, you are using an index that is way out of range of TopTenScores.

Here is your declaration of TopTenScores:

int[] TopTenScores = {000,1000,2000,3000,4000,5000,6000,7000,8000,9000};

Notice that there are 10 numbers in this declaration. This means that the max index you can have is 9. Why? Because arrays start indexing at 0 in C#.

I think you might be thinking that this array is associative... however this is not the case. When you do TopTenScores[1000] you are saying "give me the value at index 1000". This value does not exists and you will get a runtime error.

Instead, you would want to call TopTenScores[1] if you wanted to access the value 1000.

Also, you are not overwriting the default value with the new top score, rather you are overwriting the new top score with the default value. I don't think this is intended. Instead, switch your calls from this: duration = TopTenScores[1000];

to this: TopTenScores[1] = duration;

Edit: Lastly, as the commenter pointed out, using goto is bad practice and greatly discouraged. You will understand why later on as you start to understand program flow and organization better. For now, it is best to try and avoid the habit of using goto. goto maps to a low level system construct, which we should avoid when using a higher level language like C#. Your code can get confusing and error prone quickly with using goto.

Anyways, feel free to ask more questions/comment etc if you have questions or you need to clarify something. Welcome to StackOverflow!

Polaris878
Another problem worth mentioning: you describe yourself as "a fairly inexperienced programmer" and yet you use labels and goto statements in your C# code. Please don't do this. goto is occasionally useful but in the way inexperienced programmers use it it is a bad idea. Use a looping construct like while in this case, not goto.
avpx
Thank you polaris for your response,I understand what you are saying about your second point, however I didn't reveal the rest of my code. I am passing an integer value through. I also know about the goto statements, they do make the programme very glitchy however I was in a bit of a hurry to construct this programme.
O.Lodhi
I also took your advice Polaris, I changed array1 = array1.saveInArray; to array1 = arrayClass.saveInArray; and my problem seems to have reduced. It simply says cannot implicitly convert type void to int. I know taking away void doesn't help, is there anything I should change it to?
O.Lodhi
Because you are printing the top scores array to the console in your method saveInArray, I don't think you want to be returning anything. Meaning, keep void in there. However, change array1 = arrayClass.saveInArray() to arrayClass.saveInArray().
Polaris878
@Polaris878 - appreciate your patience :]
davsan
Thank you very much Polaris, I have just one more problem sorry to be such a nuisance. "No overload for method 'saveInArray' takes '0' arguments" I've been looking around, and apparently i'm passing something through which I believe I am, I'm passing a time value through correctly as an integer. But I don't completely understand why i'm getting this error. Thanks again.
O.Lodhi
O.Lodhi, this means that you are trying to call saveInArray with zero arguments, when it really requires an integer... try this: arrayClass.saveInArray(myInt)... where myInt is an integer variable. Sorry if I was misleading earlier.
Polaris878
Hello Polaris, I would like to thank you for all your help. However after your last suggestion I still can't seem to get this working. 'No overload for method 'saveInArray' takes '0' arguments'. Thats still the error im getting! I really dont understand! Apologies for dragging this out.
O.Lodhi
+1  A: 

One of your problems is that you're missing the fundamental concept of what an array is. Think of an array as a row of numbered mailboxes. This line of code:

int[] TopTenScores = {000,1000,2000,3000,4000,5000,6000,7000,8000,9000};

is creating an array of 10 integers that look something like this in memory:

  Index  Value
  -----  -----
  0          0
  1       1000
  2       2000
  3       3000
  4       4000
  5       5000
  6       6000
  7       7000
  8       8000
  9       9000

It is unclear how this is a useful structure to represent your top scores, and I'm not sure what your saveInArray method is trying to do. In that method, here's how one of your lines of code is interpreted:

duration = TopTenScores[1000];

What that means is "take what's at index 1000 of TopTenScores and store it in duration." As you can see from the table above, there is no index 1000, and besides, that code has nothing to do with saving a top score.

Another problem you're having is that you don't seem to have your algorithm in place for accomplishing the task. For the top ten functionality, try breaking down what needs to be done into instructions on how you would do it manually if you were a score keeper. It would be something like this:

  • I keep track of the top scores by stacking index cards with the scores on them in order of highest to lowest. At first, I have no index cards.
  • I can do two things: record scores and tell someone the top ten scores.
  • When someone asks me to record a score, I:
    1. Write the score down on an index card
    2. Look through the stack of previous scores in order until I find a score lower than this new score.
    3. If I find a score that was lower than this new one, I place the card on top of the lower score.
    4. Otherwise, if this score is the lowest one of the bunch, including if this is the first score recorded, I'll place the score at the bottom of the stack.
  • When someone asks me to tell them the top 10 scores, I:
    1. Go through the first 10 cards or all the cards if I have less than 10.
    2. For each of those scores, write them down in order.
    3. Give the list of scores to the one requesting them.

It may seem silly to do this, but most programs are really only sequences of simple steps, and as a programmer, you need to be able to determine those steps before translating them into a language that the compiler can understand. Once you formulate the problem in simple terms, you can start translating it into code for example:

// You can think of a role a person would do for a manual process as a class
// in a program.
public class ScoreKeeper
{
    // Our high score list (stack of cards) is empty to begin with.  Unlike
    // arrays, lists allow us insert items rather than placing them in 
    // numbered slots.
    private List<int> _scores = new List<int>();

    // This is the method for when someone asks us to record a score.  The
    // "score" parameter is the new score which you can think of as being 
    // written on a card.
    public void RecordScore(int score)
    {
        // Go through each of the existing scores.  "i" is the index in the
        // list.
        for (int i = 0; i < _scores.Count; i++)
        {
            // See if the new score is less than the score at index #i
            if (_scores[i] < score)
            {
                // It is lower than this new score.  Insert the new score
                // above that score.
                _scores.Insert(i, score);

                // We're done.  Stop looping and exit RecordScore.
                return;
            }
        }

        // If we get here, we found no scores lower than this new one.  Add 
        // this score to the bottom of the stack.
        _scores.Add(score);
    }

    // This is the method for when someone asks us for the top 10 scores.
    // Notice that we return an array of integers, which will represent 
    // our piece of paper we hand back to the one requesting the scores.
    public int[] GetTop10Scores()
    {
        // We start with a blank piece of paper.
        int[] result = new int[10];

        // Go through the scores.  The first 10 are the top 10 because
        // RecordScore puts them in order.  We also need to make sure
        // we don't try to get more scores than we've recorded.
        for (int i = 0; i < 10 && i < _scores.Count; i++)
        {
            // Write down the score on the paper
            result[i] = _scores[i];
        }

        // Send back the list of scores to the requester
        return result;
    }
}

Now, inside of your main program, you can create a ScoreKeeper and ask it to do its score keeping:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Welcome to the Maths game!");
        Console.WriteLine("(Apologies for the glitchiness!)");
        Console.WriteLine();
        Console.WriteLine("Please choose from the following options:");
        Console.WriteLine();

        // This object keeps track of scores
        ScoreKeeper scoreKeeper = new ScoreKeeper();

        bool keepRunning = true;
        while (keepRunning)
        {
            Console.WriteLine("1 - Test your Maths against the clock!");
            Console.WriteLine("2 - Exit the application.");
            Console.WriteLine("3 - Top scores");
            Console.WriteLine();
            string input = Console.ReadLine();
            int intInput = int.Parse(input);

            if (intInput == 1)
            {
                // You should avoid gotos.  Try writing a method instead

                // Play the game and get the player's score.
                int newScore = PlayGame();

                // Have the score keeper record the new score.
                scoreKeeper.RecordScore(newScore);
            }
            else if (intInput == 2)
            {
                keepRunning = false;
            }
            else if (intInput == 3)
            {
                // Get the top scores from the score keeper
                int[] topScores = scoreKeeper.GetTop10Scores();

                // Print each score
                for (int i = 0; i < topScores.Length; i++)
                {
                    Console.WriteLine("{0}: {1}", i + 1, topScores[i]);
                }
            }
        }
    }

    private static int PlayGame()
    {
        // Put your game logic in here.  Return the score.
    }
}

Once you become more familiar with the fundamentals of programming, you'll find there are existing classes you can reuse, like SortedList, that can already take care of common tasks like maintaining an ordered list.

Jacob
I appreciate the suggestion to further improve my program but at the moment i'm on a tight schedule and don't have enough time to change my program that much. Thank you for your help though. If you look at my last comment above you can see that i'm trying to deal with what i think might be the last problem.
O.Lodhi