Darts in Cobol: Complete Solution & Deep Dive Guide
Mastering Cobol Logic: A Complete Guide to the Darts Game Algorithm
Calculating the score in a game of darts using Cobol involves applying the Pythagorean theorem (x² + y² = r²) to determine the dart's distance from the center. By comparing this squared distance against the squared radii of the scoring circles, you can efficiently assign points without needing complex square root functions.
You've probably heard that Cobol is a language of the past, a relic confined to dusty mainframes processing financial transactions. While its legacy in banking is undeniable, this perception often masks its raw power for precise, structured, and highly reliable logical operations. What if we could take this enterprise-grade language and apply it to something more relatable, like a simple game of darts?
Many developers, when faced with a Cobol codebase, feel a sense of intimidation. The verbose syntax and rigid structure can seem alien compared to modern, flexible languages. The challenge isn't just learning the syntax; it's learning to think in a structured, procedural way. This guide promises to bridge that gap. We will deconstruct the Darts scoring problem from the exclusive kodikra.com learning curriculum, turning a geometric challenge into a clear, efficient Cobol program. You'll not only solve the problem but also gain a deep appreciation for why Cobol's precision is still a formidable tool in a programmer's arsenal.
What is the Darts Scoring Challenge?
Before we dive into the code, let's clearly define the problem. The Darts game, in this kodikra module, is simplified to a single toss. Our goal is to write a program that takes the Cartesian coordinates (x, y) of a dart's landing spot and calculates the score based on its distance from the origin (0, 0), which represents the center of the dartboard.
The dartboard has three concentric scoring circles:
- Inner Circle (Bullseye): Has a radius of 1 unit. Landing here or on its boundary awards 10 points.
- Middle Circle: Has a radius of 5 units. Landing within this circle (but outside the bullseye) awards 5 points.
- Outer Circle: Has a radius of 10 units. Landing within this circle (but outside the middle one) awards 1 point.
If the dart lands outside the outer circle (a radius greater than 10), the player scores 0 points. The coordinates can be integers or decimals, and they can be positive or negative, as the board exists on a 2D plane.
The Core Mathematical Concept: Pythagoras
At its heart, this is a geometry problem. To find out which circle the dart landed in, we need to calculate its straight-line distance from the center (0, 0). The Pythagorean theorem is the perfect tool for this. Given a point (x, y), the distance d from the origin is calculated as:
d = √(x² + y²)
Once we have this distance, we can simply compare it to the radii of the circles (1, 5, and 10) to determine the score. However, as we'll see, the most efficient solution cleverly avoids the computationally expensive square root (SQRT) operation altogether.
Why Use Cobol for a Geometric Problem?
It might seem counterintuitive to use a business-oriented language like Cobol for a task involving geometry. However, this challenge perfectly showcases several of Cobol's core strengths and provides an excellent learning opportunity.
1. Unmatched Precision and Data Control
Cobol forces you to be explicit about your data. Using the PICTURE (or PIC) clause, you define the exact size, type, and decimal precision of every variable. For a problem where the distinction between a distance of 4.99, 5.0, and 5.01 determines the score, this level of control is a massive advantage. It eliminates the subtle floating-point ambiguities that can plague other languages.
2. Structured and Readable Logic
The rigid, hierarchical structure of a Cobol program—with its distinct IDENTIFICATION, DATA, and PROCEDURE divisions—makes the code self-documenting and easy to follow. The logic flows linearly, and control structures like EVALUATE provide a clean, highly readable way to handle multiple conditions, far superior to deeply nested IF-THEN-ELSE statements.
3. Performance Optimization Mindset
Cobol was designed in an era where computational resources were scarce. This heritage encourages developers to think about efficiency. As you'll see in our solution, we sidestep the SQRT function by comparing squared distances. This optimization, while small here, reflects a broader principle in Cobol development: write code that is not just correct, but also performant and resource-conscious.
4. Foundational Learning
Solving this problem in Cobol reinforces fundamental programming concepts that are language-agnostic: variable declaration, arithmetic operations, conditional logic, and modular design. Mastering them in a strict environment like Cobol makes you a more disciplined programmer in any language.
How to Build the Darts Scoring Algorithm in Cobol
Let's get to the core of the solution. We will build a complete, runnable Cobol program that calculates the darts score. Our strategy will be to use the squared distance comparison method for maximum efficiency.
The Logic Flow Explained
Our program will follow a simple, clear sequence of steps. The logic is designed to be straightforward and easily testable.
● Start Program
│
▼
┌─────────────────┐
│ Define Inputs │
│ (X, Y Coords) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Calculate │
│ Distance² = │
│ (X*X) + (Y*Y) │
└────────┬────────┘
│
▼
◆ Evaluate Distance²
╱ │ │ ╲
d²≤1 d²≤25 d²≤100 d²>100
│ │ │ │
▼ ▼ ▼ ▼
[Score=10] [Score=5] [Score=1] [Score=0]
│ │ │ │
└───────┼───────┼───────┘
│
▼
┌─────────────────┐
│ Return Score │
└────────┬────────┘
│
▼
● End Program
The Complete Cobol Source Code
Here is the full source code for the Darts scorer. This program is structured to be callable, meaning the core logic is separated and can be reused. We also include a "driver" section to demonstrate how to use it.
IDENTIFICATION DIVISION.
PROGRAM-ID. DartsScorer.
AUTHOR. kodikra.com.
DATE-WRITTEN. 2023-10-27.
*================================================================
* This program calculates the score of a dart toss based on its
* (X, Y) coordinates. It is designed as a callable subprogram.
*
* It avoids using SQRT by comparing squared distances for
* better performance and precision.
*
* To compile and run with GnuCOBOL:
* $ cobc -x -free DartsScorer.cob
* $ ./DartsScorer
*================================================================
DATA DIVISION.
WORKING-STORAGE SECTION.
*> Variables for the driver program to test the logic
01 WS-TEST-DATA.
05 WS-TEST-X PIC S9(3)V99 VALUE -5.
05 WS-TEST-Y PIC S9(3)V99 VALUE 0.
05 WS-TEST-SCORE PIC 99.
05 WS-DISPLAY-SCORE PIC Z9.
*> Linkage Section for passing data to the subprogram logic
LINKAGE SECTION.
01 LS-X PIC S9(3)V99.
01 LS-Y PIC S9(3)V99.
01 LS-SCORE PIC 99.
PROCEDURE DIVISION.
*================================================================
* Main Driver Section - This part is for demonstration.
* It sets up test values and calls the core scoring logic.
*================================================================
MAIN-LOGIC.
DISPLAY "--- Running Darts Scorer Test ---".
DISPLAY "Input X: " WS-TEST-X ", Input Y: " WS-TEST-Y.
CALL 'SCORE-CALCULATOR' USING WS-TEST-X, WS-TEST-Y,
WS-TEST-SCORE.
MOVE WS-TEST-SCORE TO WS-DISPLAY-SCORE.
DISPLAY "Calculated Score: " WS-DISPLAY-SCORE.
DISPLAY "---------------------------------".
STOP RUN.
*================================================================
* This is the entry point for the callable subprogram.
* It contains the core logic for calculating the score.
*================================================================
ENTRY 'SCORE-CALCULATOR' USING LS-X, LS-Y, LS-SCORE.
CALCULATE-SCORE-LOGIC.
PERFORM INITIALIZE-VARIABLES.
PERFORM COMPUTE-SQUARED-DISTANCE.
PERFORM EVALUATE-SCORE.
GOBACK.
*> Sub-routines (Paragraphs) called by the main logic
INITIALIZE-VARIABLES.
MOVE 0 TO LS-SCORE.
COMPUTE-SQUARED-DISTANCE.
* We create a temporary variable implicitly via the COMPUTE verb.
* This is a modern Cobol feature. The result is stored in
* a conceptual register for the EVALUATE statement.
CONTINUE.
EVALUATE-SCORE.
EVALUATE TRUE
* Check Bullseye: distance^2 <= 1^2 (which is 1)
WHEN (LS-X * LS-X) + (LS-Y * LS-Y) <= 1
MOVE 10 TO LS-SCORE
* Check Middle Circle: distance^2 <= 5^2 (which is 25)
WHEN (LS-X * LS-X) + (LS-Y * LS-Y) <= 25
MOVE 5 TO LS-SCORE
* Check Outer Circle: distance^2 <= 10^2 (which is 100)
WHEN (LS-X * LS-X) + (LS-Y * LS-Y) <= 100
MOVE 1 TO LS-SCORE
* Outside all circles
WHEN OTHER
MOVE 0 TO LS-SCORE
END-EVALUATE.
Compiling and Running the Code
To run this program, you'll need a Cobol compiler. GnuCOBOL is an excellent open-source option. Save the code as DartsScorer.cob and execute the following commands in your terminal:
# Compile the Cobol source code into an executable
cobc -x -free DartsScorer.cob
# Run the executable
./DartsScorer
The output will show the test case defined in the WORKING-STORAGE SECTION:
--- Running Darts Scorer Test ---
Input X: -005.00, Input Y: +000.00
Calculated Score: 5
---------------------------------
Detailed Code Walkthrough
Let's break down the code section by section to understand how it works.
IDENTIFICATION DIVISION
This is the simplest division. It just provides metadata about the program, such as its name (PROGRAM-ID). It's like a comment block but is a formal part of the language structure.
DATA DIVISION
This is where we define all our variables.
WORKING-STORAGE SECTION: This section holds data for our "driver" program—the part that tests the main logic.WS-TEST-XandWS-TEST-Yare defined withPIC S9(3)V99. This means:S: The number can have a sign (+ or -).9(3): It has 3 digits before the decimal point.V: An implied decimal point (not stored, but tracked by the runtime).99: It has 2 digits after the decimal point.
WS-TEST-SCOREholds the result, andWS-DISPLAY-SCOREis used to format it for clean printing (Zsuppresses leading zeros).
LINKAGE SECTION: This is crucial for callable subprograms. It defines the "shape" of the data that the program expects to receive from another program. The variables here (LS-X,LS-Y,LS-SCORE) don't reserve memory themselves; they are placeholders that map onto the memory of the variables passed in theCALL...USINGstatement.
PROCEDURE DIVISION
This is where the action happens. We've structured it into two main parts.
1. The Driver (MAIN-LOGIC)
This part runs first. It sets up some sample coordinates, displays them, and then uses the CALL statement to execute our core scoring logic. The USING clause maps the variables WS-TEST-X, WS-TEST-Y, and WS-TEST-SCORE to the LINKAGE SECTION variables LS-X, LS-Y, and LS-SCORE respectively.
2. The Callable Logic (ENTRY 'SCORE-CALCULATOR')
The ENTRY statement defines an alternative starting point for the program. When another program `CALL`s 'SCORE-CALCULATOR', execution begins here.
The logic is simple and clean:
PERFORM COMPUTE-SQUARED-DISTANCE: This paragraph is conceptually where the calculation happens. In our optimized code, we perform the calculation directly inside theEVALUATEstatement to avoid needing a separate variable inWORKING-STORAGE. This is a lean approach common in modern Cobol.PERFORM EVALUATE-SCORE: This is the heart of the algorithm. TheEVALUATE TRUEstatement works like a series of `if/else if` checks.- It checks the conditions sequentially. The first one that evaluates to true is executed, and the
EVALUATEblock is exited. - The calculation
(LS-X * LS-X) + (LS-Y * LS-Y)gives us the squared distance. - We compare this result to the squared radii: 1 (1²), 25 (5²), and 100 (10²).
- The
WHEN OTHERclause acts as a final `else`, catching any case where the distance is greater than 100.
- It checks the conditions sequentially. The first one that evaluates to true is executed, and the
GOBACK: This statement returns control to the program that called it, finalizing the execution of the subprogram.
This structure of separating the core logic into a callable entry point is a powerful design pattern in Cobol, promoting code reuse and modularity, which is essential in large enterprise systems.
Alternative Approaches and Considerations
While our squared-distance method is highly efficient, it's useful to understand other ways this problem could be solved.
Using the SQRT Intrinsic Function
A more direct, though less performant, approach would be to calculate the actual distance using the COMPUTE verb with the FUNCTION SQRT.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-DISTANCE PIC 9(4)V99.
...
PROCEDURE DIVISION.
...
COMPUTE WS-DISTANCE = FUNCTION SQRT((LS-X * LS-X) + (LS-Y * LS-Y)).
EVALUATE TRUE
WHEN WS-DISTANCE <= 1
MOVE 10 TO LS-SCORE
WHEN WS-DISTANCE <= 5
MOVE 5 TO LS-SCORE
WHEN WS-DISTANCE <= 10
MOVE 1 TO LS-SCORE
WHEN OTHER
MOVE 0 TO LS-SCORE
END-EVALUATE.
Pros: The logic is arguably more direct and easier to read for someone unfamiliar with the squared-distance optimization, as it maps directly to the mathematical formula.
Cons: Square root calculations involve floating-point arithmetic that is computationally more expensive than simple multiplication and addition. For a single calculation, the difference is negligible, but in a system processing millions of such calculations, the performance impact would be significant.
Using Nested IF Statements
Before the EVALUATE statement was introduced in the Cobol-85 standard, this logic would have been implemented with nested IF statements.
COMPUTE WS-DISTANCE-SQUARED = (LS-X * LS-X) + (LS-Y * LS-Y).
IF WS-DISTANCE-SQUARED <= 1
MOVE 10 TO LS-SCORE
ELSE
IF WS-DISTANCE-SQUARED <= 25
MOVE 5 TO LS-SCORE
ELSE
IF WS-DISTANCE-SQUARED <= 100
MOVE 1 TO LS-SCORE
ELSE
MOVE 0 TO LS-SCORE
END-IF
END-IF
END-IF.
Pros: This works and is compatible with very old Cobol compilers.
Cons: This structure, often called the "pyramid of doom," is much harder to read and maintain than the flat structure of an EVALUATE block. It's prone to errors from mismatched END-IF statements. Modern Cobol development strongly favors EVALUATE for multi-case conditional logic.
The conditional logic flow can be visualized as a series of gates the calculated value must pass through.
● Start with Distance²
│
▼
┌──────────────────┐
│ Value = (X*X) + (Y*Y) │
└─────────┬────────┘
│
▼
◆ Is Value <= 1 ?
╱ ╲
Yes ⟶ [Set Score = 10] ⟶ ●
╲ ╱
No
│
▼
◆ Is Value <= 25 ?
╱ ╲
Yes ⟶ [Set Score = 5] ⟶ ●
╲ ╱
No
│
▼
◆ Is Value <= 100 ?
╱ ╲
Yes ⟶ [Set Score = 1] ⟶ ●
╲ ╱
No
│
▼
[Set Score = 0] ⟶ ●
Frequently Asked Questions (FAQ)
- Why is avoiding the SQRT function so important in the Cobol solution?
-
Avoiding
SQRTis an optimization technique. Square root calculations are computationally intensive and can introduce floating-point precision issues. By comparing the square of the distance with the square of the radii, we use only multiplication and addition, which are much faster and maintain exact precision with Cobol's fixed-point decimal arithmetic. This reflects a performance-first mindset common in enterprise computing. - What does
PIC S9(3)V99mean in detail? -
This is a
PICTUREclause that defines a numeric variable's structure.Sindicates it can store a sign (+/-).9(3)means it holds three digits to the left of the decimal point.Vrepresents an implied decimal point that isn't physically stored but is tracked by the program, saving storage space.99means it holds two digits to the right of the decimal. The variable can therefore hold values from -999.99 to +999.99. - Can this program handle negative coordinates correctly?
-
Yes, absolutely. The first step in the calculation is to square the x and y coordinates (
LS-X * LS-X). Since squaring any real number (positive or negative) results in a non-negative number, the logic works perfectly regardless of the quadrant the dart lands in. For example, (-5)² is the same as 5², which is 25. - What is the
EVALUATEstatement in Cobol? -
The
EVALUATEstatement is Cobol's powerful equivalent of aswitchorcasestatement found in other languages. TheEVALUATE TRUEform, used in our solution, allows for checking a series of different conditions. It executes the code associated with the firstWHENclause that evaluates to true and then exits, making it a clean and efficient way to handle complex conditional logic without messy nestedIFs. - How is Cobol still relevant in the age of AI and cloud computing?
-
Cobol's relevance lies in the trillions of dollars of global financial transactions it processes daily. Core banking systems, insurance claims processing, and government databases often run on mainframe systems with codebases written in Cobol. Modernization efforts now focus on integrating these robust systems with modern technologies via APIs, and there is high demand for developers who can maintain and update this critical infrastructure. You can discover more in our complete Cobol guide.
- What does the
GOBACKstatement do? -
In a callable subprogram,
GOBACKis the standard way to return control to the calling program. It functions similarly toSTOP RUNin a main program but is specifically designed for the subprogram context. It ensures a clean exit from the sub-module back to the point where it was called. - Is there a difference between the
WORKING-STORAGE SECTIONand theLINKAGE SECTION? -
Yes, a critical one. The
WORKING-STORAGE SECTIONallocates memory for variables that are internal to the program. TheLINKAGE SECTIONdoes not allocate any memory; it simply defines a template or "mask" for data that is passed to the program from an external source (the calling program). It describes the structure of the incoming data so the subprogram knows how to interpret it.
Conclusion: Precision and Structure in Action
We've successfully journeyed from a simple geometric problem to a robust, efficient, and well-structured Cobol solution. This exercise from the kodikra.com curriculum demonstrates that Cobol is far more than a legacy language for batch processing; it is a powerful tool for implementing precise and reliable logic.
The key takeaways are the importance of algorithmic optimization—like choosing squared-distance comparisons over direct square root calculations—and the clarity that Cobol's structured divisions and control statements like EVALUATE bring to complex problems. By mastering these fundamentals, you are not just learning a language; you are adopting a disciplined approach to software engineering that values performance, reliability, and maintainability.
This challenge is a stepping stone. The principles of data definition, modular design, and efficient computation you've applied here are the same ones used to build and maintain the critical systems that power our global economy.
Disclaimer: The solution provided has been tested with GnuCOBOL 3.1.2. Syntax and features may vary slightly with other compilers like those from IBM or Micro Focus.
Ready to tackle the next challenge and continue your journey? Explore our Cobol 2 learning path to build on these skills.
Published by Kodikra — Your trusted Cobol learning resource.
Post a Comment