Chat
Search
Ithy Logo

Tennis Score Calculator in C#

Een uitgebreide toepassing om de tenniswedstrijdscore bij te houden

tennis court equipment

Belangrijkste inzichten

  • Volledige tennis scoring: De applicatie houdt niet alleen individuele punten bij, maar berekent ook de game- en setscore volgens de officiële tennisregels.
  • Speciale regels geïmplementeerd: Scenarios zoals Deuce, Advantage en het vereiste verschil van twee games voor het winnen van een set worden op een nauwkeurige en gebruiksvriendelijke wijze afgehandeld.
  • Eenvoudige en uitbreidbare structuur: De code is modulair opgebouwd, zodat deze gemakkelijk aangepast kan worden aan extra vereisten zoals meerdere sets of een grafische gebruikersinterface.

Inleiding

Tennis heeft een uniek scoresysteem dat afwijkt van veel andere sporten. Naast het bijhouden van individuele punten met termen als "Love", "15", "30" en "40", dienen ook speciale spelregels zoals "Deuce" (gelijkspel vanaf 40-40) en "Advantage" (voorsprong nadat de spelers deuce hebben gehad) in acht te worden genomen. Daarnaast wordt een wedstrijd meestal opgesplitst in games en sets, waarbij een speler een game wint door het behalen van een voorsprong van twee punten en een set door het winnen van minimaal zes games (met een verschil van twee games).

In deze handleiding presenteren we een uitgebreide C# implementatie die door een scheidsrechter kan worden gebruikt om de score van een tenniswedstrijd nauwkeurig bij te houden. De applicatie maakt het mogelijk om de puntenscore, game score en setscore te tracken. Onderstaande code richt zich op de basismechanismen en kan later worden uitgebreid met extra functionaliteiten, zoals een grafische interface of ondersteuning voor meerdere sets.

Overzicht van de implementatie

De oplossing bestaat uit drie hoofdcomponenten:

  • Game Score Tracker: Deze module houdt de punten binnen een enkele game bij en verwerkt de overgang van standaard puntentelling ("Love", "15", "30", "40") naar speciale toestanden zoals Deuce en Advantage.
  • Set Score Manager: Deze module verzamelt game-resultaten en houdt de score van een set bij. Een set is gewonnen als een speler ten minste zes games wint met een verschil van twee.
  • Match Controller: Deze combineert alle game- en set informatie tot een volledige wedstrijd. Dit kan worden uitgebreid tot best-of-3 of best-of-5 sets, afhankelijk van de wedstrijdopzet.

De code is zo ontworpen dat een scheidsrechter via een console-applicatie of een grafische interface punten kan invoeren voor elk gewonnen punt. De score wordt automatisch geüpdatet conform de tennisregels.

Tennispunttabel

Hieronder vindt u een tabel die de standaard tennis punttermen weergeeft:

Punten geteld Tennis Term
0 Love
1 15
2 30
3 40

Technische uitleg en structuur

Game Score Logic

In een tenniswedstrijd wordt een game gewonnen door het behalen van een voorsprong van minstens twee punten, mits beide spelers al op 40 punten (oftewel 3 punten) zitten. Als beide spelers 40 punten hebben, ontstaat de situatie "Deuce". Zodra een speler daarna een punt haalt, krijgt die speler "Advantage". Als dezelfde speler het volgende punt scoort, wint die speler de game. Indien de tegenstander het punt wint wanneer de andere speler Advantage heeft, komt de score terug op Deuce.

Belangrijkste methoden in de Game module

  • PointWonBy(Player player): Verhoogt het puntentotaal van de betreffende speler en controleert of er een game gewonnen is.
  • GetScore: Retourneert de actuele score als string. Hierbij wordt speciale logica toegepast voor situaties als Deuce en Advantage.

Set en Match Logic

Een set bestaat uit meerdere games. In de standaard tennisregels wordt een set gewonnen door de speler die als eerste zes games wint, met minstens twee games verschil. De matchcontroller houdt vervolgens de sets bij en bepaalt uiteindelijk de winnaar van de hele wedstrijd wanneer een speler het vereiste aantal sets heeft behaald (bijvoorbeeld twee sets in een best-of-three wedstrijd).

De matchcontroller combineert de uitslag van elke game en update de setscore. Deze structuur maakt de code overzichtelijk en zorgt ervoor dat elke laag (game, set, match) verantwoordelijk is voor een specifiek aspect van de scoreverwerking.


C# Implementatie

Hieronder vindt u de volledige C# code voor een tennis score calculator. Deze code is ontworpen als een console-applicatie, zodat een scheidsrechter eenvoudig punten kan invoeren en op elk moment de huidige score kan opvragen. Het programma integreert zowel de game scoring-logica als de set- en matchbeheerfuncties.

C# Code:


// TennisScoreCalculator.cs
using System;

namespace TennisScoreApp
{
    // Enumeratie voor de spelers
    public enum Player
    {
        Player1,
        Player2
    }

    // Klasse die de puntentelling binnen één game bijhoudt
    public class Game
    {
        private int player1Points = 0;
        private int player2Points = 0;
        private readonly string[] scoreTerms = { "Love", "15", "30", "40" };
        private bool deuce = false;
        private string advantagePlayer = string.Empty;
        
        public bool IsGameCompleted { get; private set; } = false;
        public Player GameWinner { get; private set; }

        // Methode voor het registreren van een gewonnen punt
        public void PointWonBy(Player player)
        {
            // Als de game al is beslist, geen verdere punt updates
            if (IsGameCompleted) return;

            if (player == Player.Player1)
            {
                player1Points++;
            }
            else if (player == Player.Player2)
            {
                player2Points++;
            }
            UpdateScore();
        }

        // Methode die de score controleert en de winconditie vaststelt
        private void UpdateScore()
        {
            // Controleer of beide spelers op 40 (3 punten) of hoger zitten
            if (player1Points >= 3 && player2Points >= 3)
            {
                // Indien de scores gelijk zijn, is de score Deuce
                if (player1Points == player2Points)
                {
                    deuce = true;
                    advantagePlayer = string.Empty;
                }
                else
                {
                    deuce = false;
                    // Als een speler één punt voor staat, krijgt die speler Advantage
                    if (player1Points - player2Points == 1)
                    {
                        advantagePlayer = "Player 1";
                    }
                    else if (player2Points - player1Points == 1)
                    {
                        advantagePlayer = "Player 2";
                    }
                    // Als een speler met twee punten voor staat, wordt de game gewonnen
                    else if (player1Points - player2Points >= 2)
                    {
                        IsGameCompleted = true;
                        GameWinner = Player.Player1;
                    }
                    else if (player2Points - player1Points >= 2)
                    {
                        IsGameCompleted = true;
                        GameWinner = Player.Player2;
                    }
                }
            }
            else
            {
                // Indien een speler 4 punten bereikt (zonder dat de tegenstander op 3 staat), wint de speler de game
                if (player1Points >= 4)
                {
                    IsGameCompleted = true;
                    GameWinner = Player.Player1;
                }
                else if (player2Points >= 4)
                {
                    IsGameCompleted = true;
                    GameWinner = Player.Player2;
                }
            }
        }

        // Methode om de huidige game score als tekst te retourneren
        public string GetScore()
        {
            if (IsGameCompleted)
            {
                return $"Game gewonnen door {(GameWinner == Player.Player1 ? "Player 1" : "Player 2")}";
            }

            // Verwerk de speciale situaties: Deuce en Advantage
            if (player1Points >= 3 && player2Points >= 3)
            {
                if (player1Points == player2Points)
                {
                    return "Deuce";
                }
                if (!string.IsNullOrEmpty(advantagePlayer))
                {
                    return $"Advantage {advantagePlayer}";
                }
            }

            // Indien het geen Deuce- of Advantage situatie betreft, gebruik de standaard tennis termen
            string scorePlayer1 = scoreTerms[Math.Min(player1Points, 3)];
            string scorePlayer2 = scoreTerms[Math.Min(player2Points, 3)];
            return $"{scorePlayer1} - {scorePlayer2}";
        }

        // Reset de punten voor een nieuwe game
        public void Reset()
        {
            player1Points = 0;
            player2Points = 0;
            deuce = false;
            advantagePlayer = string.Empty;
            IsGameCompleted = false;
        }
    }

    // Klasse voor het beheren van de set, bestaande uit meerdere games.
    public class Set
    {
        public int Player1Games { get; private set; } = 0;
        public int Player2Games { get; private set; } = 0;
        private readonly int gamesToWinSet = 6;
        public bool IsSetCompleted { get; private set; } = false;
        public Player SetWinner { get; private set; }

        // Werk de setscore bij na het winnen van een game
        public void GameWonBy(Player player)
        {
            if (IsSetCompleted) return;

            if (player == Player.Player1)
            {
                Player1Games++;
            }
            else if (player == Player.Player2)
            {
                Player2Games++;
            }
            CheckSetWinner();
        }

        // Controleer of een speler de set heeft gewonnen 
        private void CheckSetWinner()
        {
            // Een set is gewonnen als een speler minimaal zes games wint met een verschil van twee
            if ((Player1Games >= gamesToWinSet || Player2Games >= gamesToWinSet) &&
                Math.Abs(Player1Games - Player2Games) >= 2)
            {
                IsSetCompleted = true;
                SetWinner = (Player1Games > Player2Games) ? Player.Player1 : Player.Player2;
            }
        }

        // Retourneer de huidige set score
        public string GetScore()
        {
            return $"Set: {Player1Games} - {Player2Games}";
        }

        // Reset de setstatus voor een nieuwe set
        public void Reset()
        {
            Player1Games = 0;
            Player2Games = 0;
            IsSetCompleted = false;
        }
    }

    // Hoofdklasse die de gehele wedstrijd beheert
    public class Match
    {
        public int Player1Sets { get; private set; } = 0;
        public int Player2Sets { get; private set; } = 0;
        public int SetsToWinMatch { get; private set; }
        public bool IsMatchCompleted { get; private set; } = false;
        public Player MatchWinner { get; private set; }

        private Set currentSet;
        private Game currentGame;

        public Match(int setsToWin)
        {
            SetsToWinMatch = setsToWin;
            currentSet = new Set();
            currentGame = new Game();
        }

        // Registreer een punt voor een speler en update de game-, set- en matchscore
        public void PointWonBy(Player player)
        {
            // Als de wedstrijd al beslist is, geef melding
            if (IsMatchCompleted)
            {
                Console.WriteLine("De wedstrijd is reeds beslist.");
                return;
            }

            currentGame.PointWonBy(player);
            Console.WriteLine("Game score: " + currentGame.GetScore());

            // Als de game is gewonnen, update dan de setscore
            if (currentGame.IsGameCompleted)
            {
                Console.WriteLine("Game gewonnen door: " + (currentGame.GameWinner == Player.Player1 ? "Player 1" : "Player 2"));
                currentSet.GameWonBy(currentGame.GameWinner);
                Console.WriteLine("Huidige " + currentSet.GetScore());

                // Reset de game voor de volgende ronde
                currentGame.Reset();

                // Als de set is gewonnen, werk dan de setscore bij en controleer de match winconditie
                if (currentSet.IsSetCompleted)
                {
                    if (currentSet.SetWinner == Player.Player1)
                        Player1Sets++;
                    else
                        Player2Sets++;

                    Console.WriteLine("Set gewonnen door: " + (currentSet.SetWinner == Player.Player1 ? "Player 1" : "Player 2"));
                    Console.WriteLine($"Sets: Player 1: {Player1Sets} | Player 2: {Player2Sets}");

                    if (Player1Sets == SetsToWinMatch || Player2Sets == SetsToWinMatch)
                    {
                        IsMatchCompleted = true;
                        MatchWinner = (Player1Sets > Player2Sets) ? Player.Player1 : Player.Player2;
                        Console.WriteLine("Wedstrijd gewonnen door: " + (MatchWinner == Player.Player1 ? "Player 1" : "Player 2"));
                    }
                    else
                    {
                        // Begin een nieuwe set indien de match nog niet beslist is
                        currentSet.Reset();
                    }
                }
            }
        }

        // Toon de volledige wedstrijdstatus
        public void ShowMatchScore()
        {
            Console.WriteLine("-----------------------------------------------------");
            Console.WriteLine("Huidige set score: " + currentSet.GetScore());
            Console.WriteLine("Sets gewonnen: Player 1: " + Player1Sets + " - Player 2: " + Player2Sets);
            if (IsMatchCompleted)
            {
                Console.WriteLine("Wedstrijd winnaar: " + (MatchWinner == Player.Player1 ? "Player 1" : "Player 2"));
            }
            Console.WriteLine("-----------------------------------------------------");
        }
    }

    // Console applicatie om de tennis score calculator te testen
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Welkom bij de Tennis Score Calculator");
            Console.WriteLine("Voer '1' in voor een punt voor Player 1, '2' voor een punt voor Player 2, 's' om de score te tonen, of 'q' om te stoppen.");

            // Voor deze implementatie is het een best-of-3 sets wedstrijd, dus 2 sets zijn nodig om te winnen
            Match match = new Match(2);

            bool doorgaan = true;
            while (doorgaan)
            {
                Console.Write("Maak een keuze: ");
                string input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        match.PointWonBy(Player.Player1);
                        break;
                    case "2":
                        match.PointWonBy(Player.Player2);
                        break;
                    case "s":
                        match.ShowMatchScore();
                        break;
                    case "q":
                        doorgaan = false;
                        break;
                    default:
                        Console.WriteLine("Ongeldige invoer. Voer '1', '2', 's' of 'q' in.");
                        break;
                }
            }
            Console.WriteLine("De wedstrijd is beëindigd. Druk op een toets om af te sluiten.");
            Console.ReadKey();
        }
    }
}
  

Analyse van de implementatie

De bovenstaande code biedt een complete oplossing voor het tracken van een tenniswedstrijd. De belangrijkste aspecten van de implementatie zijn als volgt:

1. Game Management

De class Game beheert de puntentelling binnen één game. Elke keer wanneer een punt wordt gescoord door een speler, wordt de interne puntenteller voor die speler verhoogd. Er wordt gecontroleerd of beide spelers ten minste 3 punten hebben, zodat we speciale situaties als Deuce en Advantage kunnen herkennen. Wanneer de score tijdens een dergelijke situatie voldoende verschil vertoont (minimaal twee punten), wordt de game als gewonnen beschouwd. De methode GetScore retourneert de huidige score, die direct wordt weergegeven in de console.

2. Set Monitoring

De class Set houdt per set bij hoeveel games iedere speler heeft gewonnen. Nadat een game is beslist, wordt de setscore aangepast. Als één van de spelers ten minste zes games heeft gewonnen met een verschil van twee games, wordt de set als gewonnen bestempeld. Hierdoor wordt de match verder opgebouwd door de individuele game-uitkomsten samen te nemen.

3. Match Controle

De Match class combineert de resultaten van de sets om de winnaar van de gehele wedstrijd te bepalen. In deze implementatie wordt een best-of-3 sets wedstrijd voorzien, wat betekent dat de eerste speler die twee sets wint de match wint. De matchcontroller verbaliseert tussentijdse scores en geeft bij elke validatie direct feedback aan de gebruiker. De console-interactie zorgt ervoor dat de scheidsrechter eenvoudig punten kan registreren en de huidige score kan opvragen.

De modulair opgebouwde structuur van de code maakt het eenvoudig om de applicatie uit te breiden. Bijvoorbeeld, mocht men in de toekomst een grafische gebruikersinterface (GUI) willen toevoegen, dan kan de kernlogica in de classes zonder veel aanpassingen worden hergebruikt.

Testen en uitbreidingen

Naast de standaard functionaliteiten kan de score calculator verder worden uitgebreid met unit tests om de betrouwbaarheid van elke module te garanderen. De testmethoden zorgen ervoor dat alle mogelijke scenario's worden gevalideerd, van standaard puntentellingen tot de specifieke situaties van Deuce en Advantage.

Ontwikkelaars kunnen de code aan hun wensen aanpassen, bijvoorbeeld:

  • Het toevoegen van een GUI voor een meer visuele representatie van de score.
  • Het implementeren van meerdere speelformaten, zoals best-of-5 sets of tie-breaks in de laatste set.
  • Het integreren van logging-functionaliteit om de scorehistorie van presentaties of belangrijke wedstrijden bij te houden.

Conclusie

In deze guide is uitvoerig beschreven hoe u een tennis score calculator in C# kunt implementeren. Er is aandacht besteed aan het nauwkeurig bijhouden van de score binnen games, sets en uiteindelijk de volledige match. Speciale situaties zoals Deuce en Advantage worden op een correcte en overzichtelijke manier afgehandeld. De modulaire opzet van de code stelt u in staat om in de toekomst gemakkelijk uitbreidingen door te voeren, zoals een grafische interface of extra functies voor andere speelformaten.

Deze aanpak biedt scheidsrechters en ontwikkelaars een robuust en flexibel hulpmiddel om tenniswedstrijden te volgen en de score eenvoudig te beheren. Met een heldere structuur en uitgebreide documentatie is deze oplossing ideaal voor zowel kleine toepassingen als integratie in grotere tennismanagementsystemen.


Referenties

Meer


Last updated February 18, 2025
Ask Ithy AI
Export Article
Delete Article