Jump to content

A-level Computing/AQA/Paper 1/Skeleton program/2025

From Wikibooks, open books for an open world

This is for the AQA A-level Computer Science Specification.

This is where suggestions can be made about what some of the questions might be and how we can solve them.

Please be respectful and do not vandalise the page, as this would affect students' preparation for exams!

Section C Predictions

[edit | edit source]

The 2025 paper 1 will contain four questions worth 23 marks.

Section D Predictions

[edit | edit source]

Mark distribution for this year:

  • The 2025 paper 1 contains 4 questions: a 5 mark, an 8 mark, a 12 mark, and a 14 mark question(s).

Mark distribution for previous years:

  • The 2024 paper 1 contained 4 questions: a 5 mark, a 6 mark question, a 14 mark question and one 14 mark question(s).
  • The 2023 paper 1 contained 4 questions: a 5 mark, a 9 mark, a 10 mark question, and a 13 mark question(s).
  • The 2022 paper 1 contained 4 questions: a 5 mark, a 9 mark, an 11 mark, and a 13 mark question(s).
  • The 2021 paper 1 contained 4 questions: a 6 mark, an 8 mark, a 9 mark, and a 14 mark question(s).
  • The 2020 paper 1 contained 4 questions: a 6 mark, an 8 mark, an 11 mark and a 12 mark question(s).
  • The 2019 paper 1 contained 4 questions: a 5 mark, an 8 mark, a 9 mark, and a 13 mark question(s).
  • The 2018 paper 1 contained 5 questions: a 2 mark, a 5 mark, two 9 mark, and a 12 mark question(s).
  • The 2017 paper 1 contained 5 questions: a 5 mark question, three 6 mark questions, and one 12 mark question.

Please note the marks above include the screen capture(s), so the likely marks for the coding will be 1-2 marks lower.

Current questions are speculation by contributors to this page.

Adjust the program so that it can use each number more than once but does not allow repeats within the 5 numbers given

[edit | edit source]

C#:

C# - DM - Riddlesdown

________________________________________________________________

In CheckNumbersUsedAreAllInNumbersAllowed you can remove the line Temp.Remove(Convert.ToInt32(Item)) around line 150

static bool CheckNumbersUsedAreAllInNumbersAllowed(List<int> NumbersAllowed, List<string> UserInputInRPN, int MaxNumber)
        {
            List<int> Temp = new List<int>();
            foreach (int Item in NumbersAllowed)
            {
                Temp.Add(Item);
            }
            foreach (string Item in UserInputInRPN)
            {
                if (CheckValidNumber(Item, MaxNumber))
                {
                    if (Temp.Contains(Convert.ToInt32(Item)))
                    {
                        // CHANGE START (line removed)
                        
                        // CHANGE END
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            return true;
        }

C# KN - Riddlesdown

________________________________________________________________

In FillNumbers in the while (NumbersAllowed < 5) loop, you should add a ChosenNumber int variable and check it’s not already in the allowed numbers so there are no duplicates (near line 370):

static List<int> FillNumbers(List<int> NumbersAllowed, bool TrainingGame, int MaxNumber)
        {
            if (TrainingGame)
            {
                return new List<int> { 2, 3, 2, 8, 512 };
            }
            else
            {
                while (NumbersAllowed.Count < 5)
                {
                    // CHANGE START
                    int ChosenNumber = GetNumber(MaxNumber);
                    while (NumbersAllowed.Contains(ChosenNumber))
                    {
                        ChosenNumber = GetNumber(MaxNumber);
                    }

                    NumbersAllowed.Add(ChosenNumber);
                    // CHANGE END
                }
                return NumbersAllowed;
            }
        }

Python:

Edit FillNumbers() to add a selection (if) statement to ensure that the number returned from GetNumber() has not already been appended to the list NumbersAllowed.

def FillNumbers(NumbersAllowed, TrainingGame, MaxNumber):
    if TrainingGame:
        return [2, 3, 2, 8, 512]
    else:
        while len(NumbersAllowed) < 5:
            NewNumber = GetNumber(MaxNumber)
            if NewNumber not in NumbersAllowed:
                NumbersAllowed.append(NewNumber)
            else: continue
        return NumbersAllowed

Edit CheckNumbersUsedAreAllInNumbersAllowed() to ensure that numbers that the user has inputted are not removed from the Temp list, allowing numbers to be re-used.

def CheckNumbersUsedAreAllInNumbersAllowed(NumbersAllowed, UserInputInRPN, MaxNumber):
    Temp = []
    for Item in NumbersAllowed:
        Temp.append(Item)
    for Item in UserInputInRPN:
        if CheckValidNumber(Item, MaxNumber):
            if int(Item) in Temp:
                continue
            else:
                return False            
    return True


Update program so expressions with whitespace are validated

[edit | edit source]

C#:

Riddlesdown - KH

__________________________________________________________________

At the moment if you put spaces between your numbers or operators it doesn't work so you will have to fix that

Put remove spaces under user input

  static string RemoveSpaces(string UserInput)
  {
      return UserInput.replace(" ", "");
  }


PS
__________________________________________________________________

I doubt this will be a question because it could be resolved in a couple of lines

        
static bool CheckIfUserInputValid(string UserInput)
        {
            string[] S = UserInput.Split(' ');
            string UserInputWithoutSpaces = "";
            foreach(string s in S)
            {
                UserInputWithoutSpaces += s;
            }
            return Regex.IsMatch(UserInputWithoutSpaces, @"^([0-9]+[\+\-\*\/])+[0-9]+$");
        }


Add exponentials (using ^ or similar)

[edit | edit source]

C#:

Riddlesdown - Unknown

_________________________________________________________________________

static bool CheckIfUserInputValid(string UserInput)
{
    // CHANGE START
    return Regex.IsMatch(UserInput, @"^([0-9]+[\+\-\*\/\^])+[0-9]+$");
    // CHANGE END
}

Answer:


In  ConvertToRPN() add the ^ to the list of operators and give it the highest precedence

}}

Riddlesdown - Unknown 
static List<string> ConvertToRPN(string UserInput)
{
    int Position = 0;
    Dictionary<string, int> Precedence = new Dictionary<string, int>
    {
        // CHANGE START
        { "+", 2 }, { "-", 2 }, { "*", 4 }, { "/", 4 }, { "^", 5 }
        // CHANGE END
    };
    List<string> Operators = new List<string>();
In EvaluateRPN() add the check to see if the current user input contains the ^, and make it evaluate the exponential if it does
Riddlesdown - Unknown<br></br>
_________________________________________________________________________<br></br>

static int EvaluateRPN(List<string> UserInputInRPN)
{
    List<string> S = new List<string>();
    while (UserInputInRPN.Count > 0)
    {
        // CHANGE START
        while (!"+-*/^".Contains(UserInputInRPN[0]))
        // CHANGE END
        {
            S.Add(UserInputInRPN[0]);
            UserInputInRPN.RemoveAt(0);
        }
        double Num2 = Convert.ToDouble(S[S.Count - 1]);
        S.RemoveAt(S.Count - 1);
        double Num1 = Convert.ToDouble(S[S.Count - 1]);
        S.RemoveAt(S.Count - 1);
        double Result = 0;
        switch (UserInputInRPN[0])
        {
            case "+":
                Result = Num1 + Num2;
                break;
            case "-":
                Result = Num1 - Num2;
                break;
            case "*":
                Result = Num1 * Num2;
                break;
            case "/":
                Result = Num1 / Num2;
                break;
            // CHANGE START
            case "^":
                Result = Math.Pow(Num1, Num2);
                break;
            // CHANGE END
        }
        UserInputInRPN.RemoveAt(0);
        S.Add(Convert.ToString(Result));
    }


Python:


def ConvertToRPN(UserInput):
    Position = 0
    Precedence = {"+": 2, "-": 2, "*": 4, "/": 4, "^": 5} # Add exponent value to dictionary
    Operators = []
def EvaluateRPN(UserInputInRPN):
    S = []
    while len(UserInputInRPN) > 0:
        while UserInputInRPN[0] not in ["+", "-", "*", "/", "^"]: # Define ^ as a valid operator
            S.append(UserInputInRPN[0])
            UserInputInRPN.pop(0)        
        Num2 = float(S[-1])
        S.pop()
        Num1 = float(S[-1])
        S.pop()
        Result = 0.0
        if UserInputInRPN[0] == "+":
            Result = Num1 + Num2
        elif UserInputInRPN[0] == "-":
            Result = Num1 - Num2
        elif UserInputInRPN[0] == "*":
            Result = Num1 * Num2
        elif UserInputInRPN[0] == "/":
            Result = Num1 / Num2
        elif UserInputInRPN[0] == "^":
            Result = Num1 ** Num2
        UserInputInRPN.pop(0)
        S.append(str(Result))       
    if float(S[0]) - math.floor(float(S[0])) == 0.0:
        return math.floor(float(S[0]))
    else:
        return -1
def CheckIfUserInputValid(UserInput):
    if re.search("^([0-9]+[\\+\\-\\*\\/\\^])+[0-9]+$", UserInput) is not None: # Add the operator here to make sure its recognized when the RPN is searched, otherwise it wouldn't be identified correctly.
        return True
    else:
        return False


Allow the user to include brackets for their own order of operations

[edit | edit source]

C#:

C# - AC - Coombe Wood

________________________________________________________________

while (Position < UserInput.Length)
{
               char CurrentChar = UserInput[Position];
               if (char.IsDigit(CurrentChar))
               {
                   string Number = "";
                   while (Position < UserInput.Length && char.IsDigit(UserInput[Position]))
                   {
                       Number += UserInput[Position];
                       Position++;
                   }
                   UserInputInRPN.Add(Number);
               }
               else if (CurrentChar == '(')
               {
                   Operators.Add("(");
                   Position++;
               }
               else if (CurrentChar == ')')
               {
                   while (Operators.Count > 0 && Operators[Operators.Count - 1] != "(")
                   {
                       UserInputInRPN.Add(Operators[Operators.Count - 1]);
                       Operators.RemoveAt(Operators.Count - 1);
                   }
                   Operators.RemoveAt(Operators.Count - 1);
                   Position++;
               }
               else if ("+-*/^".Contains(CurrentChar))
               {
                   string CurrentOperator = CurrentChar.ToString();
                   while (Operators.Count > 0 && Operators[Operators.Count - 1] != "(" && Precedence[Operators[Operators.Count - 1]] >= Precedence[CurrentOperator])
                   {
                       UserInputInRPN.Add(Operators[Operators.Count - 1]);
                       Operators.RemoveAt(Operators.Count - 1);
                   }
                   Operators.Add(CurrentOperator);
                   Position++;
               }
           }


Implement a Postfix game mode which takes the user's input in RPN instead of infix

[edit | edit source]

TBA

Do not advance the target list forward for invalid entries, instead inform the user the entry was invalid and prompt them for a new one

[edit | edit source]

TBA

Implement a menu where the user can start a new game or quit their current game

[edit | edit source]

TBA

Ensure the program ends when the game is over

[edit | edit source]

TBA

Program does not stop after 'Game Over!' with no way for the user to exit.

[edit | edit source]

Python:

def PlayGame(Targets, NumbersAllowed, TrainingGame, MaxTarget, MaxNumber):
    Score = 0
    GameOver = False
    while not GameOver:
        DisplayState(Targets, NumbersAllowed, Score)
        UserInput = input("Enter an expression (+, -, *, /, ^) : ")
        print()
        if CheckIfUserInputValid(UserInput):
            UserInputInRPN = ConvertToRPN(UserInput)
            if CheckNumbersUsedAreAllInNumbersAllowed(NumbersAllowed, UserInputInRPN, MaxNumber):
                IsTarget, Score = CheckIfUserInputEvaluationIsATarget(Targets, UserInputInRPN, Score)
                if IsTarget:
                    NumbersAllowed = RemoveNumbersUsed(UserInput, MaxNumber, NumbersAllowed)
                    NumbersAllowed = FillNumbers(NumbersAllowed, TrainingGame, MaxNumber)
        Score -= 1
        if Targets[0] != -1:
            GameOver = True
        else:
            Targets = UpdateTargets(Targets, TrainingGame, MaxTarget)        
    print("Game over!")
    DisplayScore(Score)

=== '''Practice game - only generates 119 as new targets''' ===
{{CPTAnswerTab|Python}}
The way that it is currently appending new targets to the list is just by re-appending the value on the end of the original list
<syntaxhighlight lang = "python" line="1" start = "1">
        Targets = [-1, -1, -1, -1, -1, 23, 9, 140, 82, 121, 34, 45, 68, 75, 34, 23, 119, 43, 23, 119]

So by adding the PredefinedTargets list to the program, it will randomly pick one of those targets, rather than re-appending 119.

def UpdateTargets(Targets, TrainingGame, MaxTarget):
    for Count in range (0, len(Targets) - 1):
        Targets[Count] = Targets[Count + 1]
    Targets.pop()
    if TrainingGame:
        PredefinedTargets = [23, 9, 140, 82, 121, 34, 45, 68, 75, 34, 23, 119, 43] # Updated list that is randomly picked from by using the random.choice function from the random library
        Targets.append(random.choice(PredefinedTargets))
    else:
        Targets.append(GetTarget(MaxTarget))
    return Targets


Give the user a single-use ability to generate a new set of allowable numbers

[edit | edit source]

TBA

Allow the user to input and work with negative numbers

[edit | edit source]

TBA

Allow the user to quit the game

[edit | edit source]

C#:

If the user types a certain word the program ends:

                Console.Write("Enter an expression or type stop to quit and see current score: ");   
                UserInput = Console.ReadLine(); // Get user input for the mathematical expression
                Console.WriteLine();
                string lowerUserInput = UserInput.ToLower();     //Makes a seperate string in case user types stop with capitals
                if (lowerUserInput == "stop")                     //Checks if stop is entered
                { break; }                                     //Stop program and show final score

AA - Coombe Wood


Increase the score with a bonus equal to the quantity of allowable numbers used in a qualifying expression

[edit | edit source]

TBA

Implement a multiplicative score bonus for each priority (first number in the target list) number completed sequentially

[edit | edit source]

TBA

If the user creates a qualifying expression which uses all the allowable numbers, grant the user a special reward ability (one use until unlocked again) to allow the user to enter any number of choice and this value will be removed from the target list

[edit | edit source]

TBA

Add an item that lets you clear any target

[edit | edit source]

C#:

C# - AC - Coombe Wood

________________________________________________________________

Console.WriteLine("Do you want to remove a target?");
               UserInput1 = Console.ReadLine().ToUpper();
               if (UserInput1 == "YES")
               {
                   if (Score >= 10)
                   {
                       Console.WriteLine("What number?");
                       UserInput3 = Console.Read();
                       Score = Score - 10;


                   }
                   else
                   {
                       Console.WriteLine("You do not have enough points");
                       Console.ReadKey();
                   }
               }
               else if (UserInput1 == "NO")
               {
                   Console.WriteLine("You selected NO");
               }
               Score--;
               if (Targets[0] != -1)
               {
                   GameOver = true;
               }
               else
               {
                   UpdateTargets(Targets, TrainingGame, MaxTarget);

C# - KH- Riddlesdown

_____________________________________________________________________________


  static bool RemoveTarget(List<int> Targets, string Userinput)
        {
            bool removed = false;
            int targetremove = int.Parse(Userinput);
            for (int Count = 0; Count < Targets.Count - 1; Count++)
            {
                if(targetremove == Targets[Count])
                {
                    removed = true;
                    Targets.RemoveAt(Count);
                }

            }
            if (!removed)
            {
                Console.WriteLine("invalid target");
                return (false);
            }
            return (true);
        }




 while (!GameOver)
            {
                DisplayState(Targets, NumbersAllowed, Score);
                Console.Write("Enter an expression: ");
                UserInput = Console.ReadLine();
                Console.WriteLine(UserInput);
                Console.ReadKey();
                Console.WriteLine();
                if(UserInput.ToUpper() == "R")
                {
                    Console.WriteLine("Enter the target");
                    UserInput = Console.ReadLine();
                    if(RemoveTarget(Targets, UserInput))
                    {
                        Score -= 5;
                    }
                }
                else
                {
                    if (CheckIfUserInputValid(UserInput))
                    {
                        UserInputInRPN = ConvertToRPN(UserInput);
                        if (CheckNumbersUsedAreAllInNumbersAllowed(NumbersAllowed, UserInputInRPN, MaxNumber))
                        {
                            if (CheckIfUserInputEvaluationIsATarget(Targets, UserInputInRPN, ref Score))
                            {
                                RemoveNumbersUsed(UserInput, MaxNumber, NumbersAllowed);
                                NumbersAllowed = FillNumbers(NumbersAllowed, TrainingGame, MaxNumber);
                            }
                        }
                    }
                    Score--;
                }
              
                if (Targets[0] != -1)
                {
                    GameOver = true;
                }
                else
                {
                    UpdateTargets(Targets, TrainingGame, MaxTarget);
                }
            }
            Console.WriteLine("Game over!");
            DisplayScore(Score);
        }


Allowed numbers don’t have any duplicate numbers, and can be used multiple times

[edit | edit source]

C#:

C# - KH- Riddlesdown

________________________________________________________________

In CheckNumbersUsedAreAllInNumbersAllowed you can remove the line Temp.Remove(Convert.ToInt32(Item)) around line 150


static bool CheckNumbersUsedAreAllInNumbersAllowed(List<int> NumbersAllowed, List<string> UserInputInRPN, int MaxNumber)
        {
            List<int> Temp = new List<int>();
            foreach (int Item in NumbersAllowed)
            {
                Temp.Add(Item);
            }
            foreach (string Item in UserInputInRPN)
            {
                if (CheckValidNumber(Item, MaxNumber))
                {
                    if (Temp.Contains(Convert.ToInt32(Item)))
                    {
                        // CHANGE START (line removed)
                        
                        // CHANGE END
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            return true;
        }

In FillNumbers in the while (NumbersAllowed < 5) loop, you should add a ChosenNumber int variable and check it’s not already in the allowed numbers so there are no duplicates (near line 370):

static List<int> FillNumbers(List<int> NumbersAllowed, bool TrainingGame, int MaxNumber)
        {
            if (TrainingGame)
            {
                return new List<int> { 2, 3, 2, 8, 512 };
            }
            else
            {
                while (NumbersAllowed.Count < 5)
                {
                    // CHANGE START
                    int ChosenNumber = GetNumber(MaxNumber);
                    while (NumbersAllowed.Contains(ChosenNumber))
                    {
                        ChosenNumber = GetNumber(MaxNumber);
                    }

                    NumbersAllowed.Add(ChosenNumber);
                    // CHANGE END
                }
                return NumbersAllowed;
            }
        }


Update program so expressions with whitespace are validated

[edit | edit source]

C#:

C# - KH- Riddlesdown

________________________________________________________________

At the moment if you put spaces between your numbers or operators it doesn't work so you will have to fix that

Put RemoveSpaces() under user input.


 static string RemoveSpaces(string UserInput)
        {
            char[] temp = new char[UserInput.Length];
            string bufferstring = "";
            bool isSpaces = true;

            

            for (int i = 0; i < UserInput.Length; i++)
            {
                temp[i] = UserInput[i];
            }

            while (isSpaces)
            {
                int spaceCounter = 0;
                for (int i = 0; i < temp.Length-1 ; i++)
                {
                    if(temp[i]==' ')
                    {   
                        
                        spaceCounter++;
                        temp = shiftChars(temp, i);
                        
                    }
                }
                if (spaceCounter == 0)
                {
                    isSpaces = false;
                }
                else
                {
                    temp[(temp.Length - 1)] = '¬';
                }
                
            }
            for (int i = 0; i < temp.Length; i++)
            {
                if(temp[i] != ' ' && temp[i] != '¬')
                {
                    bufferstring += temp[i];
                }
            }
            
            return (bufferstring);
        }
        static char[] shiftChars(char[] Input, int startInt)
        {
            for (int i = startInt; i < Input.Length; i++)
            {
                if(i != Input.Length - 1)
                {
                    Input[i] = Input[i + 1];
                }
                else
                {
                    Input[i] = ' ';
                }
            }
            return (Input);
        }

A shorter way

static string RemoveSpaces2(string UserInput)
{
    string newString = "";
    foreach (char c in UserInput)
    {
        if (c != ' ')
        {
            newString += c;
        }
    }

    return newString;
}

Also don’t forget to add a call to it around line 58

static void PlayGame(List<int> Targets, List<int> NumbersAllowed, bool TrainingGame, int MaxTarget, int MaxNumber)
{
    ...
    while (!GameOver)
    {
        DisplayState(Targets, NumbersAllowed, Score);
        Console.Write("Enter an expression: ");
        UserInput = Console.ReadLine();
        // Add remove spaces func here
        UserInput = RemoveSpaces2(UserInput);
        Console.WriteLine();
        ...


PS
__________________________________________________________________

Alternative shorter solution:

        
static bool CheckIfUserInputValid(string UserInput)
        {
            string[] S = UserInput.Split(' ');
            string UserInputWithoutSpaces = "";
            foreach(string s in S)
            {
                UserInputWithoutSpaces += s;
            }
            return Regex.IsMatch(UserInputWithoutSpaces, @"^([0-9]+[\+\-\*\/])+[0-9]+$");
        }


Implement a hard mode where the same target can't appear twice

[edit | edit source]

C#:

C# - Riddlesdown

________________________________________________________________

static void UpdateTargets(List<int> Targets, bool TrainingGame, int MaxTarget)
{
    for (int Count = 0; Count < Targets.Count - 1; Count++)
    {
        Targets[Count] = Targets[Count + 1];
    }
    Targets.RemoveAt(Targets.Count - 1);
    if (TrainingGame)
    {
        Targets.Add(Targets[Targets.Count - 1]);
    }
    else
    {
        // CHANGE START
        int NewTarget = GetTarget(MaxTarget);
        while (Targets.Contains(NewTarget))
        {
            NewTarget = GetTarget(MaxTarget);
        }

        Targets.Add(NewTarget);
        // CHANGE END
    }
}

Also, at line 355 update CreateTargets:

static List<int> CreateTargets(int SizeOfTargets, int MaxTarget)
{
    List<int> Targets = new List<int>();
    for (int Count = 1; Count <= 5; Count++)
    {
        Targets.Add(-1);
    }
    for (int Count = 1; Count <= SizeOfTargets - 5; Count++)
    {
        // CHANGE START
        int NewTarget = GetTarget(MaxTarget);
        while (Targets.Contains(NewTarget))
        {
            NewTarget = GetTarget(MaxTarget);
        }

        Targets.Add(NewTarget);
        // CHANGE END
    }
    return Targets;
}


Once a target is cleared, prevent it from being generated again

[edit | edit source]

C#:

C# - Riddlesdown

________________________________________________________________


internal class Program
    {
        static Random RGen = new Random();
        // CHANGE START
        static List<int> TargetsUsed = new List<int>();
        // CHANGE END
        ...

Next create these new functions at the bottom:

// CHANGE START
static bool CheckIfEveryPossibleTargetHasBeenUsed(int MaxNumber)
{
    if (TargetsUsed.Count >= MaxNumber)
    {
        return true;
    }
    else
    {
        return false;
    }
}

static bool CheckAllTargetsCleared(List<int> Targets)
{
    bool allCleared = true;
    foreach (int i in Targets)
    {
        if (i != -1)
        {
            allCleared = false;
        }
    }

    return allCleared;
}
// CHANGE END

Update CreateTargets (line 366) and UpdateTargets (line 126) so that they check if the generated number is in the TargetsUsed list we made

static List<int> CreateTargets(int SizeOfTargets, int MaxTarget)
{
    List<int> Targets = new List<int>();
    for (int Count = 1; Count <= 5; Count++)
    {
        Targets.Add(-1);
    }
            
    for (int Count = 1; Count <= SizeOfTargets - 5; Count++)
    {
        // CHANGE START
        int SelectedTarget = GetTarget(MaxTarget);
        Targets.Add(SelectedTarget);
        if (!TargetsUsed.Contains(SelectedTarget))
        {
            TargetsUsed.Add(SelectedTarget);
        }
        // CHANGE END
    }
    return Targets;
}


static void UpdateTargets(List<int> Targets, bool TrainingGame, int MaxTarget)
{
    for (int Count = 0; Count < Targets.Count - 1; Count++)
    {
        Targets[Count] = Targets[Count + 1];
    }
    Targets.RemoveAt(Targets.Count - 1);
    if (TrainingGame)
    {
        Targets.Add(Targets[Targets.Count - 1]);
    }
    else
    {
        // CHANGE START
        if (TargetsUsed.Count == MaxTarget)
        {
            Targets.Add(-1);
            return;
        }
        int ChosenTarget = GetTarget(MaxTarget);
        while (TargetsUsed.Contains(ChosenTarget))
        {
            ChosenTarget = GetTarget(MaxTarget);    
        }
        Targets.Add(ChosenTarget);
        TargetsUsed.Add(ChosenTarget);
        // CHANGE END
    }
}

Finally in the main game loop (line 57) you should add the check to make sure that the user has cleared every possible number

    ...
    while (!GameOver)
    {
        DisplayState(Targets, NumbersAllowed, Score);
        Console.Write("Enter an expression: ");
        UserInput = Console.ReadLine();
        Console.WriteLine();
        if (CheckIfUserInputValid(UserInput))
        {
            UserInputInRPN = ConvertToRPN(UserInput);
            if (CheckNumbersUsedAreAllInNumbersAllowed(NumbersAllowed, UserInputInRPN, MaxNumber))
            {
                if (CheckIfUserInputEvaluationIsATarget(Targets, UserInputInRPN, ref Score))
                {
                    RemoveNumbersUsed(UserInput, MaxNumber, NumbersAllowed);
                    NumbersAllowed = FillNumbers(NumbersAllowed, TrainingGame, MaxNumber);
                }
            }
        }
        Score--;
        // CHANGE START
        if (Targets[0] != -1 || (CheckIfEveryPossibleTargetHasBeenUsed(MaxNumber) && CheckAllTargetsCleared(Targets)))
        {
            GameOver = true;
        }
        else
        {
            UpdateTargets(Targets, TrainingGame, MaxTarget);
        }
        // CHANGE END
    }
    Console.WriteLine("Game over!");
    DisplayScore(Score);



When a target is cleared, put a £ symbol in its position in the target list. When the £ symbol reaches the end of the tracker, increase the score by 1

[edit | edit source]

TBA

Implement a victory condition which allows the player to win the game by achieving a certain score. Allow the user to pick difficulty, e.g. easy (10), normal (20), hard (40)

[edit | edit source]

TBA

Shotgun. If an expression exactly evaluates to a target, the score is increased by 3 and remove the target as normal. If an evaluation is within 1 of the target, the score is increased by 1 and remove those targets too

[edit | edit source]

TBA

Every time the user inputs an expression, shuffle the current position of all targets (cannot push a number closer to the end though)

[edit | edit source]

TBA

Speed Demon. Implement a mode where the target list moves a number of places equal to the current player score. Instead of ending the game when a target gets to the end of the tracker, subtract 1 from their score. If their score ever goes negative, the player loses

[edit | edit source]

TBA

Allow the user to save the current state of the game using a text file and implement the ability to load up a game when they begin the program

[edit | edit source]

TBA

Multiple of X. The program should randomly generate a number each turn, e.g. 3 and if the user creates an expression which removes a target which is a multiple of that number, give them a bonus of their score equal to the multiple (in this case, 3 extra score)

[edit | edit source]

TBA

Validate a user's entry to confirm their choice before accepting an expression

[edit | edit source]

TBA

Prime time punch. If the completed target was a prime number, destroy the targets on either side of the prime number (count them as scored)

[edit | edit source]

TBA

Make the program object oriented

[edit | edit source]

Answer:

import re import random import math

class Game:

   def __init__(self):
       self.numbers_allowed = []
       self.targets = []
       self.max_number_of_targets = 20
       self.max_target = 0
       self.max_number = 0
       self.training_game = False
       self.score = 0
   def main(self):
       choice = input("Enter y to play the training game, anything else to play a random game: ").lower()
       print()
       if choice == "y":
           self.max_number = 1000
           self.max_target = 1000
           self.training_game = True
           self.targets = [-1, -1, -1, -1, -1, 23, 9, 140, 82, 121, 34, 45, 68, 75, 34, 23, 119, 43, 23, 119]
       else:
           self.max_number = 10
           self.max_target = 50
           self.targets = TargetManager.create_targets(self.max_number_of_targets, self.max_target)
       self.numbers_allowed = NumberManager.fill_numbers([], self.training_game, self.max_number)
       self.play_game()
       input()
   def play_game(self):
       game_over = False
       while not game_over:
           self.display_state()
           user_input = input("Enter an expression: ")
           print()
           if ExpressionValidator.is_valid(user_input):
               user_input_rpn = ExpressionConverter.to_rpn(user_input)
               if NumberManager.check_numbers_used(self.numbers_allowed, user_input_rpn, self.max_number):
                   is_target, self.score = TargetManager.check_if_target(self.targets, user_input_rpn, self.score)
                   if is_target:
                       self.numbers_allowed = NumberManager.remove_numbers(user_input, self.max_number, self.numbers_allowed)
                       self.numbers_allowed = NumberManager.fill_numbers(self.numbers_allowed, self.training_game, self.max_number)
           self.score -= 1
           if self.targets[0] != -1:
               game_over = True
           else:
               self.targets = TargetManager.update_targets(self.targets, self.training_game, self.max_target)
       print("Game over!")
       print(f"Final Score: {self.score}")
   def display_state(self):
       TargetManager.display_targets(self.targets)
       NumberManager.display_numbers(self.numbers_allowed)
       print(f"Current score: {self.score}\n")

class TargetManager:

   @staticmethod
   def create_targets(size_of_targets, max_target):
       targets = [-1] * 5
       for _ in range(size_of_targets - 5):
           targets.append(TargetManager.get_target(max_target))
       return targets
   @staticmethod
   def update_targets(targets, training_game, max_target):
       for i in range(len(targets) - 1):
           targets[i] = targets[i + 1]
       targets.pop()
       if training_game:
           targets.append(targets[-1])
       else:
           targets.append(TargetManager.get_target(max_target))
       return targets
   @staticmethod
   def check_if_target(targets, user_input_rpn, score):
       user_input_eval = ExpressionEvaluator.evaluate_rpn(user_input_rpn)
       is_target = False
       if user_input_eval != -1:
           for i in range(len(targets)):
               if targets[i] == user_input_eval:
                   score += 2
                   targets[i] = -1
                   is_target = True
       return is_target, score
   @staticmethod
   def display_targets(targets):
       print("|", end=)
       for target in targets:
           print(f"{target if target != -1 else ' '}|", end=)
       print("\n")
   @staticmethod
   def get_target(max_target):
       return random.randint(1, max_target)

class NumberManager:

   @staticmethod
   def fill_numbers(numbers_allowed, training_game, max_number):
       if training_game:
           return [2, 3, 2, 8, 512]
       while len(numbers_allowed) < 5:
           numbers_allowed.append(NumberManager.get_number(max_number))
       return numbers_allowed
   @staticmethod
   def check_numbers_used(numbers_allowed, user_input_rpn, max_number):
       temp = numbers_allowed.copy()
       for item in user_input_rpn:
           if ExpressionValidator.is_valid_number(item, max_number):
               if int(item) in temp:
                   temp.remove(int(item))
               else:
                   return False
       return True
   @staticmethod
   def remove_numbers(user_input, max_number, numbers_allowed):
       user_input_rpn = ExpressionConverter.to_rpn(user_input)
       for item in user_input_rpn:
           if ExpressionValidator.is_valid_number(item, max_number):
               if int(item) in numbers_allowed:
                   numbers_allowed.remove(int(item))
       return numbers_allowed
   @staticmethod
   def display_numbers(numbers_allowed):
       print("Numbers available: ", "  ".join(map(str, numbers_allowed)))
   @staticmethod
   def get_number(max_number):
       return random.randint(1, max_number)

class ExpressionValidator:

   @staticmethod
   def is_valid(expression):
       return re.search(r"^([0-9]+[\+\-\*\/])+[0-9]+$", expression) is not None
   @staticmethod
   def is_valid_number(item, max_number):
       if re.search(r"^[0-9]+$", item):
           item_as_int = int(item)
           return 0 < item_as_int <= max_number
       return False

class ExpressionConverter:

   @staticmethod
   def to_rpn(expression):
       precedence = {"+": 2, "-": 2, "*": 4, "/": 4}
       operators = []
       position = 0
       operand, position = ExpressionConverter.get_number_from_expression(expression, position)
       rpn = [str(operand)]
       operators.append(expression[position - 1])
       while position < len(expression):
           operand, position = ExpressionConverter.get_number_from_expression(expression, position)
           rpn.append(str(operand))
           if position < len(expression):
               current_operator = expression[position - 1]

while operators and precedence[operators[-1]] > precedence[current_operator]:

                   rpn.append(operators.pop())

if operators and precedence[operators[-1]] == precedence[current_operator]:

                   rpn.append(operators.pop())
               operators.append(current_operator)
           else:
               while operators:
                   rpn.append(operators.pop())
       return rpn
   @staticmethod
   def get_number_from_expression(expression, position):
       number = ""
       while position < len(expression) and re.search(r"[0-9]", expression[position]):
           number += expression[position]
           position += 1
       position += 1
       return int(number), position

class ExpressionEvaluator:

   @staticmethod
   def evaluate_rpn(user_input_rpn):
       stack = []
       while user_input_rpn:
           token = user_input_rpn.pop(0)
           if token not in ["+", "-", "*", "/"]:
               stack.append(float(token))
           else:
               num2 = stack.pop()
               num1 = stack.pop()
               if token == "+":
                   stack.append(num1 + num2)
               elif token == "-":
                   stack.append(num1 - num2)
               elif token == "*":
                   stack.append(num1 * num2)
               elif token == "/":
                   stack.append(num1 / num2)
       result = stack[0]
       return math.floor(result) if result.is_integer() else -1

if __name__ == "__main__":

   game = Game()
   game.main()


Do not use reverse polish notation

[edit | edit source]

TBA

Allow the user to specify the highest number within the five NumbersAllowed

[edit | edit source]

TBA

Allow the user to save and reload the game

[edit | edit source]

Python:

This solution focuses on logging all values that had been printed the previous game, overwriting the score, and then continuing the game as before. A game log can be saved, reloaded and then continued before being saved again without loss of data.

Add selection (if) statement at the top of PlayGame() to allow for user to input desired action

Score = 0
    GameOver = False
    if (input("Load last saved game? (y/n): ").lower() == "y"):
        with open("savegame.txt", "r") as f:
            lines = []
            for line in f:
                lines.append(line)
                print(line)
            Score = re.search(r'\d+', lines[-2])
    else:
        open("savegame.txt", 'w').close()
    while not GameOver:

Change DisplayScore(), DisplayNumbersAllowed() and DisplayTargets() to allow for the values to be returned instead of being printed.

def DisplayScore(Score):
    output = str("Current score: " + str(Score))
    print(output)
    print()
    print()
    return output
    
def DisplayNumbersAllowed(NumbersAllowed):
    list_of_numbers = []
    for N in NumbersAllowed:
        list_of_numbers.append((str(N) + "  "))
    output = str("Numbers available: " + "".join(list_of_numbers))
    print(output)
    print()
    print()
    return output
    
def DisplayTargets(Targets):
    list_of_targets = []
    for T in Targets:
        if T == -1:
            list_of_targets.append(" ")
        else:
            list_of_targets.append(str(T))
        list_of_targets.append("|")
    output = str("|" + "".join(list_of_targets))
    print(output)
    print()
    print()
    return output

Print returned values, as well as appending to the save file. <syntaxhighlight> def DisplayState(Targets, NumbersAllowed, Score):

   DisplayTargets(Targets)
   DisplayNumbersAllowed(NumbersAllowed)
   DisplayScore(Score)
   try:
       with open("savegame.txt", "a") as f:
           f.write(DisplayTargets(Targets) + "\n\n" + DisplayNumbersAllowed(NumbersAllowed) + "\n\n" + DisplayScore(Score) + "\n\n")
   except Exception as e:
       print(f"There was an exception: {e}")
</syntaxhighlighting>