High Scores in Cobol: Complete Solution & Deep Dive Guide

Code Debug

The Complete Guide to Managing High Scores in Cobol

This guide provides a comprehensive walkthrough for managing a high-score list in Cobol. You will learn to leverage Cobol's powerful data structures, specifically tables (arrays), and its built-in SORT verb to efficiently find the highest score, the last added score, and the top three scores from any given list.

Ever feel a wave of nostalgia for the golden age of arcade games? The frantic challenge of Frogger, the relentless pace of Pac-Man—these classics were defined by a simple, yet powerful motivator: the high-score list. It was your digital monument, a testament to your skill. But have you ever wondered how developers in that era, using languages like Cobol, managed this seemingly simple task? You might think Cobol is just for dusty mainframes and financial reports, but its data manipulation capabilities are surprisingly robust and perfectly suited for this challenge.

If you've found yourself staring at a Cobol program, puzzled by its verbose structure and wondering how to perform basic data operations like sorting and searching, you're not alone. Many developers transitioning from modern languages find Cobol's approach to data handling unfamiliar. This article is your solution. We will demystify Cobol's data structures and procedural logic, guiding you step-by-step to build a fully functional high-score component. You'll not only solve the problem but also gain a deep appreciation for the power hidden within this legendary language.


What is Data Manipulation in Cobol?

Before diving into the code, it's essential to understand the fundamental concepts of how Cobol handles data. Unlike modern languages where you might declare a dynamic list or array with a single line of code, Cobol requires a more structured and explicit approach, primarily managed within the DATA DIVISION.

The Working-Storage Section

The WORKING-STORAGE SECTION is the primary area within a Cobol program where you define your variables, constants, and data structures that are not part of input or output files. Think of it as the program's internal memory or scratchpad. Every piece of data your program will manipulate—from a simple counter to a complex record—must be declared here first.

This section is hierarchical, using level numbers (like 01, 05, 10) to define relationships between data items. A level 01 item is a top-level record, and higher numbers like 05 or 10 represent subordinate fields within that record.

Cobol Tables: The Power of the `OCCURS` Clause

In Cobol, what modern languages call an "array" or a "list" is referred to as a table. A table is simply a repeating data item or group of items. You create a table using the OCCURS clause, which specifies how many times an item should be repeated.

For our high-score list, we need a list of numbers. We can define this in WORKING-STORAGE as follows:


       01  WS-HIGH-SCORE-DATA.
           05  WS-SCORE-COUNT        PIC 9(04) COMP.
           05  WS-SCORES-TABLE.
               10  WS-SCORE          PIC 9(06) OCCURS 1 TO 100 TIMES
                                     DEPENDING ON WS-SCORE-COUNT.

In this example, WS-SCORES-TABLE contains WS-SCORE, which OCCURS up to 100 times. The DEPENDING ON WS-SCORE-COUNT clause makes the table size dynamic up to the maximum limit, which is a powerful feature for handling lists of varying lengths. Accessing an element is done using an index in parentheses, like WS-SCORE (3) to get the third score.


Why is Sorting Crucial for a High Score List?

The core of our task is to identify the "best" scores. This inherently means we need to establish an order. A raw, unsorted list of scores is just a collection of numbers; it doesn't tell us which one is the highest or what the top three are without inspecting every single element. Sorting brings order to this chaos.

Introducing the Cobol `SORT` Verb

Cobol includes a highly optimized and powerful built-in utility for sorting: the SORT verb. This is not a simple library function; it's a core language feature designed for high-performance batch processing, capable of handling massive datasets that won't even fit into memory by using temporary work files.

The SORT verb is declarative. You don't tell Cobol how to sort (e.g., bubble sort, quicksort); you simply tell it what to sort, on which keys, and what to do with the result. This makes the code cleaner and far more efficient than writing a manual sorting algorithm.

A typical SORT statement looks like this:


   SORT SD-WORK-FILE
       ON DESCENDING KEY SD-SCORE-VALUE
       USING INPUT-FILE
       GIVING OUTPUT-FILE.

For our high-score list, we will adapt this to sort a table from WORKING-STORAGE. The DESCENDING KEY clause is vital, as it ensures the highest scores appear at the top of the sorted list, making it trivial to pick out the personal best and the top three.

ASCII Logic Diagram: The `SORT` Verb Flow

Here is a conceptual flow of how the SORT verb helps us find the top scores. It takes an unordered list, sorts it from highest to lowest, and then we can easily extract the top elements.

    ● Start with Unordered Scores
    │  [100, 40, 250, 180]
    │
    ▼
  ┌─────────────────────────┐
  │   Execute Cobol SORT    │
  │  (ON DESCENDING KEY)    │
  └───────────┬─────────────┘
              │
              ▼
    ● Sorted Score List
    │  [250, 180, 100, 40]
    │
    ▼
  ┌─────────────────────────┐
  │ Extract Top N Elements  │
  │ (e.g., Top 1 or Top 3)  │
  └───────────┬─────────────┘
              │
              ▼
    ● Final Result
       [250] or [250, 180, 100]

How to Implement the High Score Logic: The Complete Code Solution

Now, let's combine these concepts into a complete Cobol program. This program is structured as a subprogram with multiple entry points, a common design pattern in Cobol for creating reusable modules. Each entry point corresponds to one of our required functions: getting the latest score, the personal best, and the top three.

The Full Cobol Source Code

Below is the complete, well-commented source code from the kodikra.com learning path. It demonstrates the setup of data structures and the procedural logic required to manage the high scores.


      ******************************************************************
      * kodikra.com Cobol Learning Path
      * Module: High Scores
      *
      * This program manages a list of game scores. It can return:
      * 1. The last score added to the list.
      * 2. The highest score (personal best) from the list.
      * 3. The top three highest scores from the list.
      ******************************************************************
       IDENTIFICATION DIVISION.
       PROGRAM-ID. HighScores.
       AUTHOR. Kodikra.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
      * The SORT verb requires a work file defined here.
           SELECT SD-SORT-WORK-FILE ASSIGN TO "sortwork.tmp".

       DATA DIVISION.
       FILE SECTION.
      * SD defines a Sort Description file, used by the SORT verb.
       SD  SD-SORT-WORK-FILE.
       01  SD-SORT-RECORD.
           05 SD-SCORE              PIC 9(06).

       WORKING-STORAGE SECTION.
      * Defines the maximum number of scores we can handle.
       01  WS-CONSTANTS.
           05 MAX-SCORES            PIC 9(04) VALUE 100.

      * This is the structure for the sorted list of scores.
       01  WS-SORTED-SCORES.
           05 WS-SORTED-SCORE       PIC 9(06) OCCURS 100 TIMES
                                    INDEXED BY IDX-SORTED.

      * Variables to hold the final results passed back to the caller.
       01  WS-LATEST-SCORE          PIC 9(06).
       01  WS-PERSONAL-BEST         PIC 9(06).
       01  WS-TOP-THREE-SCORES.
           05 WS-TOP-SCORE          PIC 9(06) OCCURS 3 TIMES.

      * Internal work variables.
       01  WS-WORK-VARIABLES.
           05 I                     PIC 9(04).
           05 J                     PIC 9(04).

      * The LINKAGE SECTION maps data from the calling program.
       LINKAGE SECTION.
       01  LS-SCORES-IN-COUNT       PIC 9(04).
       01  LS-SCORES-IN.
           05 LS-SCORE              PIC 9(06) OCCURS 100 TIMES.

       01  LS-LATEST-SCORE          PIC 9(06).
       01  LS-PERSONAL-BEST         PIC 9(06).
       01  LS-TOP-THREE-SCORES.
           05 LS-TOP-SCORE          PIC 9(06) OCCURS 3 TIMES.

       PROCEDURE DIVISION.
      * This is the main entry point, but we use specific ENTRYs below.
           GOBACK.

      ******************************************************************
      * ENTRY "get-latest-score"
      * Returns the last score added to the list.
      ******************************************************************
       ENTRY "get-latest-score" USING LS-SCORES-IN-COUNT, LS-SCORES-IN,
                                      LS-LATEST-SCORE.
      * The last score is at the index equal to the count.
           MOVE LS-SCORE(LS-SCORES-IN-COUNT) TO LS-LATEST-SCORE.
           GOBACK.

      ******************************************************************
      * ENTRY "get-personal-best"
      * Returns the single highest score from the list.
      ******************************************************************
       ENTRY "get-personal-best" USING LS-SCORES-IN-COUNT, LS-SCORES-IN,
                                       LS-PERSONAL-BEST.
      * First, perform the sort.
           PERFORM SORT-THE-SCORES.
      * The highest score is now the first element in the sorted table.
           MOVE WS-SORTED-SCORE(1) TO LS-PERSONAL-BEST.
           GOBACK.

      ******************************************************************
      * ENTRY "get-top-three"
      * Returns the three highest scores from the list.
      ******************************************************************
       ENTRY "get-top-three" USING LS-SCORES-IN-COUNT, LS-SCORES-IN,
                                   LS-TOP-THREE-SCORES.
      * First, perform the sort.
           PERFORM SORT-THE-SCORES.
      * Initialize the output table to zeros.
           INITIALIZE LS-TOP-THREE-SCORES.
      * Move the top 3 scores from the sorted list to the output.
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 3
               IF I <= LS-SCORES-IN-COUNT
                   MOVE WS-SORTED-SCORE(I) TO LS-TOP-SCORE(I)
               END-IF
           END-PERFORM.
           GOBACK.

      ******************************************************************
      * PARAGRAPH "SORT-THE-SCORES"
      * A reusable paragraph that sorts the input scores in descending
      * order and stores them in WS-SORTED-SCORES.
      ******************************************************************
       SORT-THE-SCORES.
           SORT SD-SORT-WORK-FILE
               ON DESCENDING KEY SD-SCORE
               INPUT PROCEDURE IS POPULATE-SORT-FILE
               GIVING WS-SORTED-SCORES.

       POPULATE-SORT-FILE.
      * This procedure feeds the data from our input table into the
      * sort utility.
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > LS-SCORES-IN-COUNT
               MOVE LS-SCORE(I) TO SD-SCORE
               RELEASE SD-SORT-RECORD
           END-PERFORM.

Detailed Code Walkthrough

Let's break down the program section by section to understand its inner workings.

1. `IDENTIFICATION` and `ENVIRONMENT` Divisions

The IDENTIFICATION DIVISION is straightforward; it names our program HighScores. The ENVIRONMENT DIVISION is more technical. Here, we use FILE-CONTROL to declare a logical file named SD-SORT-WORK-FILE and assign it to a physical temporary file on disk. The Cobol SORT verb requires this "work file" to perform its operations, especially for large datasets.

2. `DATA DIVISION`

This is where all our data is defined.

  • `FILE SECTION`: We define the structure of a single record in our sort work file (SD-SORT-WORK-FILE). The SD level indicator marks it as a Sort Description.
  • `WORKING-STORAGE SECTION`: This holds our program's internal data. WS-SORTED-SCORES is a table that will receive the output from the SORT verb. WS-LATEST-SCORE, WS-PERSONAL-BEST, and WS-TOP-THREE-SCORES are variables to hold the results.
  • `LINKAGE SECTION`: This is crucial for subprograms. It defines the data structures that are passed into the program from a calling program. It acts as a function signature or API contract. LS-SCORES-IN is the input list, and the other variables are pointers to where we should place our results.

3. `PROCEDURE DIVISION`

This is where the logic resides. Instead of one continuous flow, we use the ENTRY statement to create multiple entry points.

  • ENTRY "get-latest-score": This is the simplest function. It directly accesses the input table LS-SCORES-IN using the count LS-SCORES-IN-COUNT as the index. This works because the last item added is always at the end of the list.
  • ENTRY "get-personal-best": This logic first calls the SORT-THE-SCORES paragraph. After the sort is complete, the highest score is guaranteed to be at the first position of the WS-SORTED-SCORES table, so we just move WS-SORTED-SCORE(1) to the output.
  • ENTRY "get-top-three": Similar to the personal best, it starts by sorting. It then uses a PERFORM VARYING loop to copy the first three elements from the sorted table into the output table. It includes a check (IF I <= LS-SCORES-IN-COUNT) to handle cases where the input list has fewer than three scores.

4. The `SORT-THE-SCORES` Paragraph

This is the heart of the sorting logic.

  • SORT SD-SORT-WORK-FILE ON DESCENDING KEY SD-SCORE: This tells Cobol to sort the work file, ordering the records so that the SD-SCORE field is in descending (highest to lowest) order.
  • INPUT PROCEDURE IS POPULATE-SORT-FILE: Instead of using a physical input file, we tell the SORT verb to get its data from a procedure (a paragraph) named POPULATE-SORT-FILE.
  • GIVING WS-SORTED-SCORES: This tells the SORT verb to write the sorted output not to a file, but directly into our WORKING-STORAGE table, WS-SORTED-SCORES. This is incredibly convenient for in-memory sorting.
  • POPULATE-SORT-FILE: This paragraph loops through our input table from the LINKAGE SECTION (LS-SCORES-IN) and, for each score, uses the RELEASE verb to pass it to the sort utility. RELEASE is the counterpart to WRITE when using an INPUT PROCEDURE.

Where is this Pattern Used in the Real World?

While managing game scores is a fun example, the underlying pattern of sorting records to find top performers is a cornerstone of enterprise computing, especially on mainframes where Cobol thrives. This exact logic is applied in countless real-world scenarios:

  • Financial Reporting: Generating a report of the top 10 sales representatives for the quarter.
  • Banking: Identifying the largest transactions in a day for fraud detection or auditing.
  • Insurance: Calculating the highest-risk policies based on claim history.
  • Inventory Management: Listing the top-selling products to inform restocking decisions.

In all these cases, a batch program reads a large dataset, uses the SORT utility to order it by a specific key (sales amount, transaction value, etc.), and then processes the top N records to generate a report or feed another system. The efficiency of Cobol's `SORT` makes it ideal for these large-scale data processing tasks.


Alternative Approaches & Performance Considerations

The built-in SORT verb is almost always the best choice. However, for academic purposes or to understand fundamental algorithms, it's useful to know how you could sort a table manually in Cobol.

Manual Sorting with `PERFORM VARYING` (Bubble Sort)

You could implement a classic sorting algorithm like a Bubble Sort using nested loops. The logic involves repeatedly stepping through the list, comparing each pair of adjacent items, and swapping them if they are in the wrong order.


       PERFORM VARYING I FROM 1 BY 1 UNTIL I > WS-SCORE-COUNT - 1
           PERFORM VARYING J FROM 1 BY 1 UNTIL J > WS-SCORE-COUNT - I
               IF WS-SCORE(J) < WS-SCORE(J + 1)
      *            Swap the elements
                   MOVE WS-SCORE(J) TO WS-TEMP-SCORE
                   MOVE WS-SCORE(J + 1) TO WS-SCORE(J)
                   MOVE WS-TEMP-SCORE TO WS-SCORE(J + 1)
               END-IF
           END-PERFORM
       END-PERFORM.

ASCII Logic Diagram: Bubble Sort Flow

The flow of a manual sort is much more granular and iterative. The program must manage every comparison and swap itself, which is far less efficient than the highly optimized internal `SORT` utility.

    ● Start with Unordered List
    │
    ▼
  ┌────────────────────────┐
  │ Loop 1 (Outer Pass)    │
  └──────────┬─────────────┘
             │
             ▼
       ┌───────────────────┐
       │ Loop 2 (Inner)    │
       │ Compare adjacent  │
       └─────────┬─────────┘
                 │
                 ▼
            ◆ A > B ?
           ╱         ╲
      Yes (Swap)      No (Continue)
       │               │
       ▼               │
  ┌──────────┐         │
  │ Swap A, B│         │
  └──────────┘         │
       ╲               ╱
        └──────┬──────┘
               │
               ▼
        ◆ Inner Loop Done?
       ╱                  ╲
      No ----------------- (Back to Inner Loop)
     ╱
   Yes
    │
    ▼
 ◆ Outer Loop Done?
╱                  ╲
No ----------------- (Back to Outer Pass)
╱
Yes
│
▼
● Sorted List

Pros and Cons: `SORT` Verb vs. Manual Sorting

Aspect Cobol `SORT` Verb Manual Sorting (e.g., Bubble Sort)
Performance Highly optimized, extremely fast. Uses efficient algorithms and can offload to disk for huge datasets. Very slow, especially for large lists (O(n²) complexity for bubble sort). Inefficient.
Readability High. The code is declarative and clearly states the intent ("sort this data"). Low. The logic is complex, with nested loops and swap variables, obscuring the primary goal.
Development Time Fast. Writing a `SORT` statement is quick and standardized. Slow. Requires writing, testing, and debugging a complex algorithm from scratch.
Robustness Extremely robust and reliable. A core, heavily tested feature of the language. Prone to off-by-one errors and other logical bugs.
Use Case The standard for nearly all sorting tasks in professional Cobol development. Primarily for educational purposes or very small, specific in-memory sorting tasks where `SORT` might be overkill (rare).

Frequently Asked Questions (FAQ)

1. What is a `TABLE` in Cobol?

A TABLE in Cobol is the equivalent of an array or list in modern programming languages. It is defined using the OCCURS clause on a data item in the DATA DIVISION, which specifies a fixed or variable number of times the item repeats.

2. How does the `SORT` verb work in Cobol?

The SORT verb is a powerful, high-level command that sorts a file or, through procedures, an in-memory table. You specify the data to be sorted, the key(s) to sort on (ascending or descending), and where the output should go. It uses highly optimized system routines to perform the sort efficiently.

3. Why use `DESCENDING KEY` for high scores?

We use DESCENDING KEY because we want the highest scores to appear first in the sorted list. Sorting in descending order arranges the numbers from largest to smallest, making it easy to find the "top" scores by simply taking the first few elements.

4. What is the `LINKAGE SECTION` for?

The LINKAGE SECTION is used in subprograms to define the layout of data that is passed from a calling program. It doesn't allocate memory itself; instead, it provides a map or template that overlays the memory of the arguments passed during a CALL, allowing the subprogram to access and modify them.

5. Can Cobol handle a list if I don't know the exact size beforehand?

Yes. While you must specify a maximum size for a table, you can use the OCCURS... DEPENDING ON... clause. This links the actual size of the table to a variable, allowing it to handle a variable number of elements up to the defined maximum, which is how our solution is designed.

6. Is Cobol still relevant for tasks like data sorting?

Absolutely. For the domains where Cobol operates—primarily mainframe-based batch processing in finance, insurance, and government—its ability to process and sort massive files with extreme efficiency is a key reason for its continued relevance. The SORT utility is a prime example of its strengths.


Conclusion: Timeless Logic in a Classic Language

Successfully building a high-score management component in Cobol is a fantastic achievement that bridges the gap between classic gaming logic and enterprise programming techniques. Throughout this guide, we've deconstructed the problem, explored the fundamentals of Cobol's DATA DIVISION, and harnessed the immense power of the built-in SORT verb. You've learned that despite its age and verbosity, Cobol provides robust, efficient, and surprisingly readable solutions for complex data manipulation tasks.

The key takeaways are clear: proper data definition is paramount, and leveraging built-in features like SORT over manual implementations is crucial for performance and maintainability. This foundational knowledge is not just for solving puzzles; it's directly applicable to the real-world batch processing and reporting tasks that keep global industries running.

Disclaimer: The code and concepts presented are based on standard GnuCOBOL or IBM Enterprise COBOL. Syntax and feature availability may vary slightly between different Cobol compilers and versions. Always consult your specific compiler's documentation.

Ready to tackle your next challenge? Continue your journey on the Cobol 4 learning roadmap or explore our complete collection of tutorials on the main Kodikra Cobol page.


Published by Kodikra — Your trusted Cobol learning resource.