Darts in Abap: Complete Solution & Deep Dive Guide

a close-up of a pool table

Mastering ABAP Logic: The Complete Guide to Solving the Darts Score Challenge

Calculating a Darts game score in ABAP involves translating Cartesian coordinates (X, Y) into points. This is achieved by first calculating the dart's distance from the center (0,0) using the Pythagorean theorem, d = sqrt(x² + y²). Then, a conditional statement, typically CASE, maps this distance to the appropriate score.

Ever stared at a problem that seems simple on the surface, like a game of darts, but translating it into code feels like a puzzle? You know the rules, you see the target, but making the logic click in a language like ABAP can be a hurdle. This feeling is a universal part of the developer's journey, especially when blending mathematical concepts with business-oriented programming.

This guide is designed to dissolve that confusion. We will deconstruct the Darts score challenge from the exclusive kodikra.com curriculum, transforming a geometric problem into elegant, efficient, and understandable ABAP code. By the end, you won't just have a solution; you'll have a deeper understanding of fundamental programming principles that are critical for any aspiring SAP developer.


What is the Darts Score Challenge?

The Darts Score challenge is a classic programming exercise designed to test your understanding of basic geometry, mathematical functions, and conditional logic within a specific programming language—in this case, ABAP. It's a cornerstone problem in the ABAP Learning Path Module 2.

The premise is straightforward: you are given the Cartesian coordinates (an X and a Y value) representing where a single dart has landed on a 2D plane. The center of the dartboard is at the origin point (0, 0). Your task is to write a function or method that calculates and returns the score based on the dart's distance from this center.

The scoring is based on concentric circles, each with a specific radius:

  • Inner Circle (Bullseye): If the dart lands within or on the circle with a radius of 1 unit, the player scores 10 points.
  • Middle Circle: If the dart lands outside the inner circle but within or on the circle with a radius of 5 units, the player scores 5 points.
  • Outer Circle: If the dart lands outside the middle circle but within or on the circle with a radius of 10 units, the player scores 1 point.
  • Outside the Target: If the dart lands anywhere outside the outer circle (a radius greater than 10), the player scores 0 points.

Essentially, you must implement a program that takes two numbers (X and Y) as input and outputs a single integer (0, 1, 5, or 10) based on these rules.


Why is This ABAP Module Crucial for Your SAP Career?

While calculating a game's score might seem trivial, the underlying concepts are fundamental to building robust and complex SAP applications. Mastering this kodikra module provides a solid foundation in several key areas of ABAP development.

Strengthening Core Logic Skills

At its heart, this problem is about conditional logic. You must evaluate a condition (the dart's distance) and take different actions based on the result. This is the bedrock of programming. In SAP, this same logic is used to determine pricing conditions, validate user input in a Fiori app, or control workflow approvals in an S/4HANA system.

Understanding Data Types and Precision

The calculation involves coordinates that can be fractional, and the distance calculation will almost certainly result in a non-integer. This forces you to work with different data types, such as f (Float) for calculations requiring precision and i (Integer) for the final score. Mishandling data types is a common source of bugs in real-world applications, and this exercise hones that critical skill.

Applying Mathematical Functions in a Business Context

SAP systems often deal with more than just financial data. Logistics modules (SAP EWM/TM) might need to calculate distances between locations, and manufacturing modules (SAP PP/QM) might involve geometric quality checks. Knowing how to use ABAP's built-in mathematical functions like SQRT() and POWER() is an invaluable tool in your developer toolkit.

By mastering this simple challenge, you are preparing yourself for the complex logical evaluations required in professional SAP development. For a broader view of the language's capabilities, explore our complete guide to the ABAP language.


How to Solve the Darts Challenge in ABAP: A Deep Dive

Solving this problem involves a clear, three-step process: calculating the distance from the origin, comparing that distance against the scoring radii, and returning the correct score. We will implement this logic within a local ABAP class, which is modern best practice.

Step 1: The Core Concept - The Pythagorean Theorem

To find the distance of a point (x, y) from the origin (0, 0) on a 2D plane, we use the Pythagorean theorem. The distance d is the hypotenuse of a right-angled triangle whose other two sides have lengths equal to the absolute values of x and y.

The formula is:

d = √(x² + y²)

In ABAP, we will use the POWER() function to square the coordinates and the SQRT() function to find the square root of their sum. This distance value is the single most important piece of data we need to determine the score.

● Start: Receive (X, Y) Coordinates
│
▼
┌─────────────────────────┐
│ Calculate Distance `d`  │
│ d = SQRT( X² + Y² )     │
└──────────┬──────────────┘
           │
           ▼
    ◆ Is d <= 1 ?
   ╱           ╲
  Yes           No
  │              │
  ▼              ▼
[Score = 10]   ◆ Is d <= 5 ?
                 ╱           ╲
                Yes           No
                │              │
                ▼              ▼
              [Score = 5]    ◆ Is d <= 10 ?
                               ╱           ╲
                              Yes           No
                              │              │
                              ▼              ▼
                            [Score = 1]    [Score = 0]
                              │              │
                              └──────┬───────┘
                                     │
                                     ▼
                                ● End: Return Score

Step 2: Structuring the ABAP Solution

We'll encapsulate our logic within a local class named lcl_darts. This class will have a single public method called score that accepts the X and Y coordinates and returns the integer score.

This approach promotes clean, reusable, and testable code, which are hallmarks of professional software development. The method signature will look like this:

  • IMPORTING: i_x TYPE f, i_y TYPE f. We use type f (float) to handle decimal coordinates accurately.
  • RETURNING: VALUE(r_score) TYPE i. The final score is always a whole number, so type i (integer) is appropriate.

Step 3: The Complete ABAP Implementation

Here is the full, well-commented code for solving the Darts challenge. You can place this code within an executable program (SE38) or a global class method (SE24) for testing.


*&---------------------------------------------------------------------*
*& Report Z_SOLVE_DARTS_CHALLENGE
*&---------------------------------------------------------------------*
*& This program demonstrates the solution for the Darts score
*& challenge from the kodikra.com learning curriculum.
*&---------------------------------------------------------------------*
REPORT z_solve_darts_challenge.

*&---------------------------------------------------------------------*
*& Local Class Definition for Darts Logic
*&---------------------------------------------------------------------*
CLASS lcl_darts DEFINITION.
  PUBLIC SECTION.
    METHODS score
      IMPORTING
        i_x            TYPE f
        i_y            TYPE f
      RETURNING
        VALUE(r_score) TYPE i.
ENDCLASS.

*&---------------------------------------------------------------------*
*& Local Class Implementation
*&---------------------------------------------------------------------*
CLASS lcl_darts IMPLEMENTATION.
  METHOD score.
    "&-------------------------------------------------------------------&
    "& STEP 1: Calculate the distance from the origin (0,0).
    "& The distance 'd' is calculated using the Pythagorean theorem:
    "& d = sqrt(x^2 + y^2)
    "& We use a FLOAT variable for precision during calculation.
    "&-------------------------------------------------------------------&
    DATA(lv_distance) = sqrt( power( val = i_x exp = 2 ) +
                              power( val = i_y exp = 2 ) ).

    "&-------------------------------------------------------------------&
    "& STEP 2: Determine the score based on the calculated distance.
    "& We use a CASE statement for clear, readable conditional logic.
    "& The conditions check from the smallest radius (inner circle)
    "& to the largest (outer circle).
    "&-------------------------------------------------------------------&
    CASE abap_true.
      WHEN lv_distance <= 1.
        " Bullseye: Within or on the circle with radius 1.
        r_score = 10.
      WHEN lv_distance <= 5.
        " Middle Circle: Within or on the circle with radius 5.
        r_score = 5.
      WHEN lv_distance <= 10.
        " Outer Circle: Within or on the circle with radius 10.
        r_score = 1.
      WHEN OTHERS.
        " Outside the target.
        r_score = 0.
    ENDCASE.

  ENDMETHOD.
ENDCLASS.

*&---------------------------------------------------------------------*
*& START-OF-SELECTION: Demonstration of the class usage.
*&---------------------------------------------------------------------*
START-OF-SELECTION.
  DATA(lo_darts) = NEW lcl_darts( ).

  " --- Test Cases ---
  " Bullseye
  DATA(lv_score_1) = lo_darts->score( i_x = '0' i_y = '0' ).
  WRITE: / |Dart at (0, 0) scores: { lv_score_1 }|. " Expected: 10

  " On the edge of the bullseye
  DATA(lv_score_2) = lo_darts->score( i_x = '1' i_y = '0' ).
  WRITE: / |Dart at (1, 0) scores: { lv_score_2 }|. " Expected: 10

  " In the middle circle
  DATA(lv_score_3) = lo_darts->score( i_x = '3' i_y = '-3' ).
  WRITE: / |Dart at (3, -3) scores: { lv_score_3 }|. " Expected: 5

  " On the edge of the outer circle
  DATA(lv_score_4) = lo_darts->score( i_x = '-10' i_y = '0' ).
  WRITE: / |Dart at (-10, 0) scores: { lv_score_4 }|. " Expected: 1

  " Just outside the target
  DATA(lv_score_5) = lo_darts->score( i_x = '10.1' i_y = '0' ).
  WRITE: / |Dart at (10.1, 0) scores: { lv_score_5 }|. " Expected: 0

END-OF-SELECTION.

Step 4: Detailed Code Walkthrough

Let's break down the implementation of the score method step-by-step.

  1. Distance Calculation:
    DATA(lv_distance) = sqrt( power( val = i_x exp = 2 ) + power( val = i_y exp = 2 ) ).

    This is the mathematical core of the solution. We use modern ABAP inline declaration with DATA() to create the lv_distance variable. The power() function is called twice to square i_x and i_y. These results are added together, and the final sum is passed to the sqrt() function. The result—the dart's distance from the center—is stored in lv_distance.

  2. Conditional Logic with CASE:
    CASE abap_true.
      WHEN lv_distance <= 1.
        r_score = 10.
      ...
    ENDCASE.

    Instead of a series of IF...ELSEIF...ELSE statements, we use a CASE abap_true construct. This is a common and highly readable pattern in modern ABAP for handling complex conditions. The program evaluates each WHEN condition sequentially.

  3. Evaluation Flow:
    • WHEN lv_distance <= 1: Is the distance 1 or less? If true, it sets r_score to 10 and exits the CASE block.
    • WHEN lv_distance <= 5: If the first condition was false, it checks if the distance is 5 or less. If true, r_score becomes 5, and the block is exited.
    • WHEN lv_distance <= 10: If the previous two were false, this condition is checked.
    • WHEN OTHERS: This is a catch-all. If none of the preceding WHEN conditions are met (meaning the distance is greater than 10), it executes this block, setting the score to 0.

    This sequential evaluation is crucial. Because we check from the smallest radius outwards, we don't need to write complex conditions like WHEN lv_distance > 1 AND lv_distance <= 5. The logic is implicitly handled by the order of the WHEN statements.

  Input (X, Y)
      │
      ▼
┌──────────────────┐
│  METHOD score    │
└────────┬─────────┘
         │
         ▼
  ┌─────────────────┐
  │ Calculate d² =  │
  │ X² + Y²         │
  └────────┬────────┘
           │
           ▼
  ┌─────────────────┐
  │ d = SQRT(d²)    │
  └────────┬────────┘
           │
           ▼
    ◆ CASE d
   ╱   │    │   ╲
d≤1  d≤5  d≤10  d>10
 │    │    │    │
 ▼    ▼    ▼    ▼
[10] [5]  [1]  [0]
  ╲   │    │   ╱
   └───┬────┘
       │
       ▼
┌──────────────────┐
│ RETURN r_score   │
└──────────────────┘

Alternative Approaches and Performance Considerations

While the provided solution is clean and idiomatic, it's valuable to understand alternative ways to solve the problem and their trade-offs.

Alternative 1: Using IF/ELSEIF/ELSE

The most direct alternative to a CASE statement is a chain of IF, ELSEIF, and ELSE. The logic remains identical, but the syntax differs.


    " Alternative using IF/ELSEIF/ELSE
    IF lv_distance <= 1.
      r_score = 10.
    ELSEIF lv_distance <= 5.
      r_score = 5.
    ELSEIF lv_distance <= 10.
      r_score = 1.
    ELSE.
      r_score = 0.
    ENDIF.

Comparison: CASE vs. IF/ELSEIF

Aspect CASE abap_true IF/ELSEIF/ELSE
Readability Often considered cleaner and more declarative, especially with many conditions. The intent is very clear. Perfectly readable for simple cases but can become visually cluttered with many nested or chained conditions.
Performance For this specific use case, the performance difference is negligible and should not be a deciding factor. Effectively identical to the CASE statement in terms of performance for this logic.
Best Practice Generally preferred in modern ABAP when evaluating a single variable against a series of distinct conditions. Still a fundamental and widely used construct, especially for more complex boolean logic (e.g., combining AND/OR).

Alternative 2: Avoiding the Square Root Calculation

For performance-critical applications, the SQRT() function can be computationally expensive. We can avoid it entirely by comparing the square of the distance with the square of the radii.

The logic becomes:

  • Instead of d <= 1, we check d² <= 1² (i.e., d² <= 1).
  • Instead of d <= 5, we check d² <= 5² (i.e., d² <= 25).
  • Instead of d <= 10, we check d² <= 10² (i.e., d² <= 100).

  METHOD score_optimized.
    " Calculate the square of the distance, avoiding SQRT.
    DATA(lv_distance_squared) = power( val = i_x exp = 2 ) +
                                power( val = i_y exp = 2 ).

    " Compare squared distance with squared radii.
    CASE abap_true.
      WHEN lv_distance_squared <= 1.  " 1*1
        r_score = 10.
      WHEN lv_distance_squared <= 25. " 5*5
        r_score = 5.
      WHEN lv_distance_squared <= 100. " 10*10
        r_score = 1.
      WHEN OTHERS.
        r_score = 0.
    ENDCASE.
  ENDMETHOD.

While this optimization is clever and demonstrates a deeper understanding of the mathematics, for a simple problem like this, the readability of the original approach might be preferable. However, in scenarios involving millions of calculations (e.g., analyzing large datasets), this technique can provide a noticeable performance boost.


Frequently Asked Questions (FAQ)

1. What happens if the input coordinates X and Y are negative?
The solution works perfectly with negative coordinates. This is because the first step in the calculation is to square each coordinate (power(val = i_x exp = 2)). Squaring any number, positive or negative, always results in a positive number. For example, (-3)² is 9, just as 3² is 9. Therefore, the distance calculation is always based on positive values.
2. Why is it important to use a FLOAT data type for the distance calculation?
The result of a square root operation is often a number with a fractional part (e.g., sqrt(2) is approximately 1.414). If we were to use an INTEGER data type to store this intermediate result, the decimal part would be truncated, leading to incorrect calculations and wrong scores. Using FLOAT (type f) ensures we maintain the necessary precision for accurate comparisons.
3. Can this logic be implemented without a class in ABAP?
Yes, you could implement this logic directly in a program or, more traditionally, within a FORM...ENDFORM subroutine or a FUNCTION MODULE. However, using local or global classes is the modern, object-oriented approach recommended by SAP. It leads to more structured, reusable, and maintainable code, which is a critical skill for professional developers.
4. How can I test this code in my SAP system?
You can copy the entire code block into a new Executable Program using transaction SE38 in the SAP GUI or via ABAP Development Tools (ADT) in Eclipse. The START-OF-SELECTION block contains sample calls to the method that will run when you execute the program, printing the results to the screen.
5. Is the optimized approach (avoiding SQRT) always better?
Not necessarily. While it is technically faster, the primary goal in most business application development is code clarity and maintainability. For a non-performance-critical task, the first solution using SQRT() is more readable because it directly mirrors the mathematical formula for distance. The optimized approach should be reserved for situations where performance is a measured and proven bottleneck.
6. What is the difference between CASE abap_true and a simple CASE variable?
A simple CASE variable is used to check for specific, discrete values of that variable (e.g., CASE lv_day. WHEN 'MON'. ... WHEN 'TUE'. ... ENDCASE.). The CASE abap_true construct is more flexible; it allows you to evaluate complex boolean conditions in each WHEN branch (e.g., WHEN lv_distance <= 10), making it a powerful alternative to long IF/ELSEIF chains.

Conclusion: From Geometry to Clean Code

We have successfully translated the rules of a Darts game into a robust and readable ABAP solution. This journey took us from a fundamental mathematical concept, the Pythagorean theorem, through to modern ABAP syntax, including local classes, inline declarations, and the powerful CASE abap_true statement.

Mastering this challenge from the kodikra.com curriculum is more than just solving a puzzle; it's about building a mental toolkit. You've practiced decomposing a problem, choosing the right data types for precision, implementing conditional logic cleanly, and even considering performance optimizations. These are the skills that separate a novice coder from a professional SAP developer. As you continue on your ABAP learning path, remember these foundational principles, as they will appear in every complex application you build.

Disclaimer: The code and concepts discussed are based on modern ABAP syntax available in SAP S/4HANA and recent versions of SAP NetWeaver. Syntax may vary in older systems.


Published by Kodikra — Your trusted Abap learning resource.