Recent

Author Topic: Limitations of case statements and poor code structure  (Read 710 times)

TBMan

  • Sr. Member
  • ****
  • Posts: 281
Limitations of case statements and poor code structure
« on: October 03, 2025, 10:40:10 pm »
I had decided to have a couple of solitaire playing card  game apps where each app had a number of solitaire games. I created two apps because the games used different size screens.  (I'm using PTCGraph - old time hobby coder).

Then I consolidated the two apps by using different size viewports with an initial overall larger viewport.

But, then I had to manage a lot of games in the code (up to 24 now). I use an icon for each game and then a case statement to process the game index chosen from the icons on the screen.  To do this I had to maintain a name list and change code for the case statement to include the new game and its screensize info. This was working fine when I had 10 games or so, but then when I added the games from the other app I had coded, I gave up on inserting names in alphabetical order and just threw them at the end. Being a little fussy, about things like that it had bothered me.  So what I did instead was create a method of adding the games to a list, then sort the list (simple bubble sort).

I used this record type:
Code: Pascal  [Select][+][-]
  1. GamePlay = record
  2.         Name:string;
  3.         Id:integer;   // ended up not using this
  4.         ScreenSize:integer;
  5.         RunGame:PlayGameProc;
  6.         GameStats:GameStatsProc;
  7.    end;                  
  8.  

I then use an array to hold the game info above. Now the icons pass the index of the item selected. The screensize is set before calling the rungame procedure. The gamestats procedure is used to get the game stats of each individual game for
display in the "main" app.

No more huge case statement.  Now when I want to add a new game to the app, I just tweak the selection screen layout, if needed, for an additional game. Here's my current code for adding all the games into the main app:

Code: Pascal  [Select][+][-]
  1. procedure SetUpGames;
  2. begin
  3.  Initgames;
  4.    AddGame('Alaska',smallview,@PlayAlaska,@alaskau.gamestats);
  5.    AddGame('Athena',smallview,@PlayAthena,@athenav2u.gamestats);
  6.    AddGame('Baker''s 12',smallview,@playBakersdozen,@bakersdozen.gamestats);
  7.    AddGame('Canfield',smallview,@PlayCanfield,@canfieldU.gamestats);
  8.    Addgame('Castle SS',smallview,@playCastleselectivesort,@castleselectivesortu.gamestats);
  9.    Addgame('Circle 8',smallview,@PlayCircle8,@circle8u.gamestats);
  10.    AddGame('Freecell',smallview,@PlayFreeCell,@freecellu.gamestats);
  11.    Addgame('Golf',smallview,@PlayGolf,@golfu.gamestats);
  12.    Addgame('Klondike',Largeview,@PlayKlondike,@klonu.gamestats);
  13.    addgame('Lady B',smallview,@PlayLadyBetty,@ladybettyv2u.gamestats);
  14.    Addgame('TriPeaks',largeview,@PlayTriPeaks,@tripeaksu.gamestats);
  15.    Addgame('2 Queens',smallview,@PlayTwins,@twinqueensu.gamestats);
  16.    Addgame('Agnes B',superview,@PlayAgnesB,@agnesbernaueru.gamestats);
  17.    Addgame('Agnes S',superview, @PlayAgnesS,@agnessorelu.gamestats );
  18.    Addgame('Ali Baba',largeview,@playAliBaba,@AlibabaU.gamestats);
  19.    Addgame('Assembly',Largeview,@PlayAssembly,@assemblyu.gamestats);
  20.    Addgame('Bunker',largeview,@PlayBunker,@bunkeru.gamestats);
  21.    addgame('40 Thieves',superview,@PlayFortyThieves,@fortythievesu.gamestats);
  22.    addgame('La Belle',superview,@playLabelle,@Labelle.gamestats);
  23.    addgame('Montana',largeview,@playMontana,@montanau.gamestats);
  24.    Addgame('Spider',Superview,@PlaySpider,@spiderU.gamestats);
  25.    addgame('CornerS',Superview,@PlayCornerSuite,@cornersuiteU.gamestats);
  26.    Addgame('Cruel',superview,@playcruel,@cruelu.gamestats);
  27.    Addgame('La Easy',superview,@playLabelleEasy,@LabelleEasy.gamestats);
  28.  
  29.   sortgames;
  30. end;                      
  31.  

Then the section for running a game is consolidated to this, omitting the main loop and menu button event handler:
Code: Pascal  [Select][+][-]
  1.  gameselected := false;
  2.     getmousestate(mx,my,mb);
  3.     event := 0;
  4.     event := processbuttons(mx,my);
  5.     for gamesearch := 1 to maxgameIndex do
  6.       begin
  7.           if positioninrect(mx,my,gameicons[gamesearch].rect) and lpressed then
  8.             begin
  9.               gameselected := true;
  10.               gameindex := gamesearch;
  11.               while lpressed do begin end;
  12.               break;
  13.             end;
  14.       end;
  15.  
  16.     if gameselected then
  17.       begin
  18.           clearmaxscreen;
  19.           with games[gameindex] do
  20.            begin
  21.             setgameview(games[gameindex].screensize);
  22.             games[gameindex].RunGame;
  23.            end;
  24.           setgameview(superview);
  25.           buildmenu;
  26.           screen1display;
  27.     end;                            
  28.  
  29.  
  30.  
  31.  



So, I had to do some housekeeping to have a getmousestate that allowed for different viewports as well as New GetmaxX and GetMaxy functions (I used the names MaxGetX and MaxGetY to make replacement simple). That all worked out well.

So now I can probably have around 60 games in the current screen mode I'm using. Each game is a separate unit and the
deck is a common unit. The deck images are in separate units that are "seen" only by one unit. That unit draws the images as needed.  That image drawing procedure uses a large case statement to determine which deck is used to draw the image requested.  I can probably do something similar to do away with the case statement in that procedure as well, but that isn't broken so I'm hesitant to fix it :)  I only have to insert new deck code at the end of the case statement so there's that.
« Last Edit: October 04, 2025, 02:41:06 pm by TBMan »
I love programming.

Some things I've done using PTCgraph:

NFL Retro Football (almost finished):
https://www.youtube.com/watch?v=78mTtsd7ppk


Solitaire games:
https://www.youtube.com/watch?v=zmtxI7FdWuQ&list=PLa4BPpFl34iVhFwX1JZwVm3vE5ay_i3R2

creaothceann

  • Full Member
  • ***
  • Posts: 204
Re: Limitations of case statements and poor code structure
« Reply #1 on: October 04, 2025, 01:26:39 am »
Code: Pascal  [Select][+][-]
  1. procedure SetUpGames;
  2. begin
  3.  Initgames;
  4.   //...
  5.   sortgames;
  6. end;                      
  7.  

Can't understand why so many people leave their code unaligned...

Code: Pascal  [Select][+][-]
  1. procedure SetUpGames;
  2. begin
  3.         InitGames;
  4.         AddGame('Alaska'     , View_Small, @PlayAlaska             , @AlaskaU             .GameStats);
  5.         AddGame('Athena'     , View_Small, @PlayAthena             , @AthenaV2U           .GameStats);
  6.         AddGame('Baker''s 12', View_Small, @playBakersDozen        , @BakersDozen         .GameStats);
  7.         AddGame('Canfield'   , View_Small, @PlayCanfield           , @CanfieldU           .GameStats);
  8.         AddGame('Castle SS'  , View_Small, @playCastleSelectiveSort, @CastleSelectiveSortU.GameStats);
  9.         AddGame('Circle 8'   , View_Small, @PlayCircle8            , @Circle8U            .GameStats);
  10.         AddGame('Freecell'   , View_Small, @PlayFreeCell           , @FreecellU           .GameStats);
  11.         AddGame('Golf'       , View_Small, @PlayGolf               , @GolfU               .GameStats);
  12.         AddGame('Klondike'   , View_Large, @PlayKlondike           , @KlonU               .GameStats);
  13.         AddGame('Lady B'     , View_Small, @PlayLadyBetty          , @LadybettyV2U        .GameStats);
  14.         AddGame('TriPeaks'   , View_Large, @PlayTriPeaks           , @TriPeaksU           .GameStats);
  15.         AddGame('2 Queens'   , View_Small, @PlayTwins              , @TwinQueensU         .GameStats);
  16.         AddGame('Agnes B'    , View_Super, @PlayAgnesB             , @AgnesBernauerU      .GameStats);
  17.         AddGame('Agnes S'    , View_Super, @PlayAgnesS             , @AgnesSorelU         .GameStats);
  18.         AddGame('Ali Baba'   , View_Large, @playAliBaba            , @AliBabaU            .GameStats);
  19.         AddGame('Assembly'   , View_Large, @PlayAssembly           , @AssemblyU           .GameStats);
  20.         AddGame('Bunker'     , View_Large, @PlayBunker             , @BunkerU             .GameStats);
  21.         AddGame('40 Thieves' , View_Super, @PlayFortyThieves       , @FortythievesU       .GameStats);
  22.         AddGame('La Belle'   , View_Super, @PlayLabelle            , @Labelle             .GameStats);
  23.         AddGame('Montana'    , View_Large, @PlayMontana            , @MontanaU            .GameStats);
  24.         AddGame('Spider'     , View_Super, @PlaySpider             , @SpiderU             .GameStats);
  25.         AddGame('CornerS'    , View_Super, @PlayCornerSuite        , @CornersuiteU        .GameStats);
  26.         AddGame('Cruel'      , View_Super, @PlayCruel              , @CruelU              .GameStats);
  27.         AddGame('La Easy'    , View_Super, @PlayLabelleEasy        , @LabelleEasy         .GameStats);
  28.         SortGames;
  29. end;                      
  30.  
_ _ _

You could also compile all the different games as libraries (e.g. *.dll), put them into a subdirectory and let the application load them dynamically at runtime. This would make the applcation much more general.
Quote from: Thaddy
And don't start an argument, I am right.
Quote from: Thaddy
You have a thorough misunderstanding of what I wrote. Can you provide an example this time? I doubt it. (because you never do out of incompentence)

440bx

  • Hero Member
  • *****
  • Posts: 5819
Re: Limitations of case statements and poor code structure
« Reply #2 on: October 04, 2025, 04:13:36 am »
Can't understand why so many people leave their code unaligned...
I've often wondered that too.  It's so much easier to read and see mistakes when the code is aligned.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

TBMan

  • Sr. Member
  • ****
  • Posts: 281
Re: Limitations of case statements and poor code structure
« Reply #3 on: October 04, 2025, 04:28:31 am »
Good pointers, thanks.
I love programming.

Some things I've done using PTCgraph:

NFL Retro Football (almost finished):
https://www.youtube.com/watch?v=78mTtsd7ppk


Solitaire games:
https://www.youtube.com/watch?v=zmtxI7FdWuQ&list=PLa4BPpFl34iVhFwX1JZwVm3vE5ay_i3R2

Thaddy

  • Hero Member
  • *****
  • Posts: 18356
  • Here stood a man who saw the Elbe and jumped it.
Re: Limitations of case statements and poor code structure
« Reply #4 on: October 04, 2025, 08:03:53 am »
@TBMan I would do it using the sorted collection from objects:
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode tp}{$H-}{$endif}
  2. uses
  3.   objects;
  4. type
  5.  TPlayGameProc  = procedure;(* dummy *)
  6.  TGameStatsProc = procedure;(* dummy *)
  7.  
  8.  PGamePlay = ^TGamePlay;
  9.  TGamePlay = record
  10.     Name:string[80];
  11.     Id:integer;  
  12.     ScreenSize:integer;
  13.     RunGame:TPlayGameProc;
  14.     GameStats:TGameStatsProc;
  15.   end;  
  16.          
  17.   TGamePlayCollection = object (TSortedCollection)
  18.     constructor init;
  19.     Function Compare (Key1,Key2 : Pointer): Sw_integer; virtual;
  20.   end;
  21.  
  22. constructor TGamePlayCollection.init;
  23. begin
  24.   inherited init(100,10);
  25.   Duplicates := false;
  26. end;
  27.  
  28. function TGamePlayCollection.Compare (Key1,Key2 : Pointer) :sw_integer;
  29. begin
  30.   Compare := ShortCompareText (PGamePlay(Key1)^.Name, PGamePlay(Key2)^.Name )
  31. end;
  32.  
  33. begin
  34. end.
After all we are old school  :D That's how I would do it in the olden days.

For others: in this case the collection is actually a sorted list and has little to do with classes.TCollection.
« Last Edit: October 04, 2025, 09:23:54 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

cdbc

  • Hero Member
  • *****
  • Posts: 2467
    • http://www.cdbc.dk
Re: Limitations of case statements and poor code structure
« Reply #5 on: October 04, 2025, 10:49:56 am »
Hi
@TBMan: I think I've got just the 'Container' you need for this...
At the moment I'm putting the finishing touches on the newest addition to my IContainers library, namely the new snappy /IHashMaps/ which employs some /IBucketLists/ internally, these bucketlists offers the posibility to add items sorted and gives you access via a 'Find' method...
You should have a 'LookSee', I'm still working on the hashmap-integration in IContainers, but the bucketlists are finished (hashmaps too, but not yet integrated)  8-)
You could say, you'll get a sneak preview  ;D
Regards Benny
« Last Edit: October 04, 2025, 10:52:59 am by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6 -> FPC 3.2.2 -> Lazarus 4.0 up until Jan 2025 from then on it's both above &: KDE6/QT6 -> FPC 3.3.1 -> Lazarus 4.99

Thaddy

  • Hero Member
  • *****
  • Posts: 18356
  • Here stood a man who saw the Elbe and jumped it.
Re: Limitations of case statements and poor code structure
« Reply #6 on: October 04, 2025, 03:26:39 pm »
@cdbc
Benny, he uses TP code, so objects, not classes. Everything old school.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

cdbc

  • Hero Member
  • *****
  • Posts: 2467
    • http://www.cdbc.dk
Re: Limitations of case statements and poor code structure
« Reply #7 on: October 04, 2025, 03:38:22 pm »
Hi
Okidoki, no worries...  ;D
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6 -> FPC 3.2.2 -> Lazarus 4.0 up until Jan 2025 from then on it's both above &: KDE6/QT6 -> FPC 3.3.1 -> Lazarus 4.99

TBMan

  • Sr. Member
  • ****
  • Posts: 281
Re: Limitations of case statements and poor code structure
« Reply #8 on: October 04, 2025, 04:00:43 pm »
@cdbc
Benny, he uses TP code, so objects, not classes. Everything old school.

Lol, I did manage to make another file open dialog using a class. It works! :)
I love programming.

Some things I've done using PTCgraph:

NFL Retro Football (almost finished):
https://www.youtube.com/watch?v=78mTtsd7ppk


Solitaire games:
https://www.youtube.com/watch?v=zmtxI7FdWuQ&list=PLa4BPpFl34iVhFwX1JZwVm3vE5ay_i3R2

 

TinyPortal © 2005-2018