OPP Design For my Solution

I am working on a problem for which i have already developed a solution, but i am new to OPP prgramming and started learning recently.
Would request OPP Gurus to provide suggestions for the better designs, keeping scalability, extendability of (course readability) in mind.

Also,I would like to extend the the current program for mutiple random players and winner is decided based on max number of votes.
But there are rules:

1)Currently i have 6 players, out of which any number of players might contest(taken from std::input or cmd args)
2)Contestants are not aware of other contestants.
3)Each contestant has to send a message to other players,other players will give support to the contestant only if the sent message has that particular player symbol in it.( as done in findSymbol function).
4)Contestants are not allowed to give support , and other players will give support on FCFS basis.
5)Currently i have six players,if 3 pplayers wants to contest then three players will send 5 messages to other players, so 3*5 = 15 messages total.
6)There will a umpire who picks 6 messages(because currently only 6 players) and gives to all players based on message(because message has player name in it, can be found in createSecretMessage)
7)In case of two/more players get same votes then contest should be held for those players, till one gets majority or no one gets majority.
As message is choosen randomly there is a possibility that no one gets majority,then there wont be any winner, thats possible.

Its a mid size prgram , request to bear with me and provide your valueable suggestions, thanks in advance..

The below program does above steps but for only one player, so there wont be any ties etc..


since , the program is of little big in size I have divided into multiple posts:
below are related links:
http://www.cplusplus.com/forum/general/266968/
http://www.cplusplus.com/forum/general/266967/
Last edited on
@ravss2,

Your code may be too much for one POST, but for goodness' sake, please DELETE YOUR OTHER THREADS AND PUT IT ALL AS CONSECUTIVE POSTS IN THIS ONE !!!!

You've created about FOUR (at last count) separate THREADS for this problem! As people reply to other threads they will get scattered everywhere.
Last edited on
main.cpp
========

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 

    #include "Player.h"
    #include "Winner.h"
    #include <time.h>
    std::vector<Player> ListOfPlayer;
    
    int main()
    {
        srand(time(0)); 
        
        Player AAA("AAA","Apple","MrA","I");
        Player BBB("BBB","Banana","MrB","I");
        Player CCC("CCC","Cherry","MrC","I");
        Player DDD("DDD","Durain","MrD","I");
        Player EEE("EEE","Eggfruit","MrE","I");
        Player FFF("FFF","FarkelBerry","MrF","I");
        
        ListOfPlayer.push_back(AAA);
        ListOfPlayer.push_back(BBB);
        ListOfPlayer.push_back(CCC);
        ListOfPlayer.push_back(DDD);
        ListOfPlayer.push_back(EEE);
        ListOfPlayer.push_back(FFF);    
        
        Winner Gamer;
        Gamer.createSecretMessage(ListOfPlayer);
        Gamer.DisplayStoredMessages();
        Gamer.ProcessMessageForVotes();
        Gamer.DisplayStoredMessages();
        
        std::cout<<std::endl;
        
        std::cout<<"Winner of Game?"<<std::endl;
        Gamer.GetWinner();
    
        std::cout<<std::endl;
        
        std::cout<<"Supporters of Player?"<<std::endl;
        Gamer.GetSupporters();
        
        return 0;
    }


player.h
----------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

    #ifndef __PLAYER__
    #define __PLAYER__
    #include <string>
    #include <iostream>
    
    class Winner;
    class Player{
    private:
        std::string placeOfPlayer;
        std::string symbolName;
        std::string nameOfPlayer;
        std::string WSI;//Winner,Supporter,Idle
        
    public:
        std::string getPlaceOfPlayer() const;
        std::string getSymbolOfPlayer() const;
        std::string getNameOfPlayer() const;
        std::string getStatusOfPlayer() const;
        
        void setPlaceOfPlayer(const std::string&);
        void setSymbolOfPlayer(const std::string&);
        void setNameOfPlayer(const std::string&); 
        void setStatusOfPlayer(const std::string&);  
        
        bool operator <(const Player&) const;
     
        Player();
        ~Player();
        Player(std::string place,std::string symbol,std::string name,std::string state);        
        friend std::ostream & operator << (std::ostream &out, const Player &p);
    };
    #endif 


player.cpp
========

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

    #include <iostream>
    #include <map>
    #include <vector>
    #include "winner.h"
    #include "player.h"
    Player::Player()
    {
        // std::cout<<"Default Ctor invoked"<<std::endl;
        // numOfPlayers++;
    }
    
    Player::Player(std::string place,std::string symbol,std::string name,std::string state):
    placeOfPlayer(place),symbolName(symbol),nameOfPlayer(name),WSI(state)
    {
       // std::cout<<"Param Ctor invoked"<<std::endl;
       //  numOfPlayers++;
    }
    
    Player::~Player()
    {
        //std::cout<<"Dtor invoked for "<<nameOfPlayer<<numOfPlayers<<std::endl;
      //  numOfPlayers--;
    }
    
    void Display_Mapper(std::map<std::string,Player> Mapper)
    {
        std::cout<<"Mapper"<<std::endl;
        for(auto &m:Mapper) {
           std::cout<<"{"<<m.first<<","<<m.second<<"},"<<std::endl;
       }
    }
    
    void Display_Player_Vector(std::vector<Player> aPlayer)
    {
        std::cout<<"aPlayer vecor"<<std::endl;
        for(auto &k:aPlayer) {
           std::cout<<k<<std::endl;
       }
    }
    std::ostream &operator << (std::ostream &out,const Player &p)
    {
        std::cout <<p.placeOfPlayer<<" "<<p.symbolName<<" "<<p.nameOfPlayer<<" "<<p.WSI;
    }
    
    std::string Player::getNameOfPlayer() const {
        return this->nameOfPlayer;
    }
    
    std::string Player:: getSymbolOfPlayer() const {
        return this->symbolName;
    }
    
    std::string Player::getStatusOfPlayer() const{
        return this->WSI;
    }
    
    std::string Player::getPlaceOfPlayer() const{
        return this->placeOfPlayer;
    }
    void Player::setStatusOfPlayer(const std::string& status){
        this->WSI = status;
    }
    
    bool Player:: operator <(const Player& g) const{
        return (g.nameOfPlayer > this->nameOfPlayer);
    }


winner.h
========
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

    #include "player.h"
    #include <string>
    #include <map>
    #include <vector>
    
    class Player;
    class Winner{
    private:
        std::string playername;
        int numOfvotes;
    public:
        void createSecretMessage(std::vector<Player>);
        void StoreMessage(std::string msg,Player receiver);
        void DisplayStoredMessages();
        void ProcessMessageForVotes();
        int checkSymbolIntheMessage(std::string msg,std::string symbol);
        int check_for_symbol( int base_message_count[], std::string symbol);
        int check_is_vote_ok(std::string msg,std::string symbol);
        void GetWinner();
        void GetSupporters();
        bool findSymbol( std::string string_to_be_made, std::string given_chars );
        Winner();
        ~Winner();
    };


winner.cpp
========

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

    #include "player.h"
    #include <string>
    #include <map>
    #include <vector>
    
    class Player;

    #include "msgs.h"
    #include "winner.h"
    #include <map>
    #include <cctype>
    #include <cstring>
    #include <limits>
    
    std::map<Player,std::string> Game;
    // Map key is always constant, so modifying the values is not possible.
    
    Winner::Winner()
    {
        playername = "MrC";
        numOfvotes = 0;
    }
    
    Winner::~Winner(){
        
    }
    
    int getARandomNumber()
    {
        //std::cout<<"N Messages:"<<Messages.size();
        return ( rand() % Messages.size());
    }
    
    void Winner::createSecretMessage(std::vector<Player> player){
        for(auto &p:player){
            if(p.getPlaceOfPlayer() != "CCC") {
            std::string msg = p.getPlaceOfPlayer() +","+Messages.at(getARandomNumber());
            StoreMessage(msg,p);
            //std::cout<<msg<<std::endl;
            }
        }
    }
    
    void Winner::StoreMessage(std::string msg,Player player)
    {
        Game.insert(std::make_pair(player,msg));
    }
    
    void Winner::DisplayStoredMessages()
    {
        std::cout<<"stored messages"<<std::endl;
        
        for(auto &m:Game)
            std::cout<<"{"<<m.first<<" "<<m.second<<"}"<<std::endl;
        
        std::cout<<"numOfvotes:"<<numOfvotes<<std::endl;
    }
    
    void Winner::ProcessMessageForVotes(){
        bool retVal = false;
        std::string Ally("S");   
        decltype(Game) m;
        for (std::pair<Player, std::string> p: Game) {
          // this can be used for second solution,please ignore from here
          if(p.first.getStatusOfPlayer() == "C") 
              std::cout<<"Receiver is already a contender"<<std::endl;
          else if(p.first.getStatusOfPlayer() == "A")
               std::cout<<"Receiver is already an Ally"<<std::endl;
          //till here
          else {
              retVal = checkSymbolIntheMessage(p.second,p.first.getSymbolOfPlayer());        
              if(retVal == true){
                p.first.setStatusOfPlayer(Ally);
                m.insert(p);
                numOfvotes++;
                }else{
                m.insert(p);
            }
        }
        }
        Game = m;
    }
    
    int Winner ::checkSymbolIntheMessage(std::string msg,std::string symbol)
    {
        std::string message {0};
        unsigned int i{0};
        
        for(char c:msg){
        if (c == ',')
            break;
        i++;
        }
        message = msg.substr(i+1,msg.size()-(i+1));
        
       // std::cout<<"mess ="<<message<<std::endl;
        
        if(findSymbol(symbol,msg) == true)
            {
                return true;
            }
        return false;
    }
    
    bool Winner :: findSymbol( std::string symbol, std::string message )
    {
        constexpr std::size_t MAX_DISTINCT_CHAR_VALUES = std::numeric_limits<unsigned char>::max() + 1 ;
        std::size_t freq_count[MAX_DISTINCT_CHAR_VALUES] = {0} ; // initialise to all zeroes
        
        for( unsigned char u : message ) 
            ++freq_count[tolower(u)] ;
        
        for( unsigned char u : symbol ) // for each character
        {
            if( freq_count[tolower(u)] > 0 ) 
                --freq_count[tolower(u)] ;
            else 
                return false ;
        }
    
        return true ;
    }
    
    void Winner::GetWinner()
    {
        if(numOfvotes >= 2)
            std::cout<<"Winner "<<playername<<std::endl;
        else
            std::cout<<"none"<<std::endl;
    }
    
    void Winner::GetSupporters()
    {
       if(numOfvotes >= 2) { 
        for(auto &m:Game) {
                if(m.first.getStatusOfPlayer() == "S")
                    std::cout<<m.first.getNameOfPlayer()<<std::endl;
        }
        }else{
            std::cout<<"None"<<std::endl;
        }
    }


    class Winner{
    private:
        std::string playername;
        int numOfvotes;
    public:
        void createSecretMessage(std::vector<Player>);
        void StoreMessage(std::string msg,Player receiver);
        void DisplayStoredMessages();
        void ProcessMessageForVotes();
        int checkSymbolIntheMessage(std::string msg,std::string symbol);
        int check_for_symbol( int base_message_count[], std::string symbol);
        int check_is_vote_ok(std::string msg,std::string symbol);
        void GetWinner();
        void GetSupporters();
        bool findSymbol( std::string string_to_be_made, std::string given_chars );
        Winner();
        ~Winner();
    };



msgs.h
=======

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

    #include<vector>
    #include<string>
    
    std::vector<std::string> Messages = {   
    
            "DuraineggfruitfrakelBerrydefghijaklbananacherryapplelbbnopqrstunvwoxyz",
            "DuraineggfruitfrakelBerrydefghijaklbananacherryapplelbbnopqrstunvwoxyz",
            "DuraineggfruitfrakelBerrydefghijaklbananacherryapplelbbnopqrstunvwoxyz",
            "abnbobacdefghijklbbpoqrstuvwxyz",
            "DuraineggfruitfrakelBerryabnopdefghijklbbqorstuvwxyz",
            "cdefghijklbbbnabaopoqrstuvwxyz",
            "cdefgDuraineggfruitfrakelBerryadefghijklbbbnopqorstuvwxyzhijklbbbnl",
            "efgDuraineggfruitfrakelBerrytoctbpadefgushijkoclpsubbLetjkadolwrl",
            "DuraineggfruitfrakelBerrydabefghijklbbnopqrstouvwxyz",
            "DuraineggfruitfrakelBerrydeafghijklbnobabpqrstuovwoxyz:",
            "GoDuraineggfruitfrakelBerrydefghijklabbbnopqrsltuvwoxyz.",
            "DuraineggfruitfrakelBerrydefghijklbbabnoyopqrstuvwxz.",
            "DuraineggfruitfrakelBerrydefghijklbbbanopqrstuvwxyzo.",
            "fghijklbbboocpalndaaatusspaireowl",
            "fghijklbbboocpstluandaaapaireowl!",
            "DuraineggfruitfrakelBerrydefghijklbbblnaopqrstuvwxyz.o",
            "defghijkolbbbalbcnoapqrstuvwxyzes.",
            "DuraineggfruitfrakelBerrydefghijkollbbbnoapqrstuvwxyz.",
            "DuraineggfruitfrakelBerrydefghijkolbbblnoapqrstuvwxyz",
            };                                   


Last edited on
@lastchange, done. Thank you
right off, you should probably have messages be in a text file, and not limit to any specific number of anything (use a container that can be any size you need).

i see C's time.h (c++ uses <ctime>)
Main has data that looks like it should have been in a file
you probably should not be including or using cstring
map is included twice

I am struggling a little with winner class. Is a winner just a player who won the game? What does it represent? Is it misnamed? Does it represent the human player and the others are computer players ?

are your rules for the game well defined? have you played out the game by hand some and looked for issues?

You have a fair bit of code to be looking to start designing now. Are you looking to re-do it, improve it, or just learn what to do next time? Try to design before coding next time, as doing it this way leads to rework or trying to fit code and design together instead of designing and coding to fit that.
Last edited on
>> right off, you should probably have messages be in a text file,
This I understand, instead of using a header file to store messages I should store all the messages in a file, so that I need not to recompile if my number of messages changes, is that the purpose?

But again, I cannot read my messages randomly as I am doing now, I will have to open the file and store the messages in data structure for as long as the program is running.

>>and not limit to any specific number of anything
I don't get this, I feel I am not limiting anything here, can you please point me out what I am limiting here?

(use a container that can be any size you need).
I am currently using std::vector<std::string> , for storing my messages, is that not good, vector can be increased dynamically,is there other better container for storing my messages?

c header files , and other repeated files are taken care.

>>Main has data that looks like it should have been in a file

This one i need a suggestion please, currently i am creating Player & Winner objects inside main, so that i don't get any access issue. I can create a function like startGame() and put all that content in the function, but that's not i really want.

I should move Player to player.cpp and Winner to winner.cpp , but i should be able to access all the Players inside Winner,so i might need an interface in Player to that calls Winner functions or vice versa.

I want to do things little organized way here, my Winner class is operating on Player class, and player class does not need to know about Winner class so how do we do things here, is that way of storing all players to vectors std::vector<Player> ListOfPlayer good or any other better way we have, this is the area where i need your suggestions.

>>I am struggling a little with winner class. Is a winner just a player who won the game? What does it represent? Is it misnamed? Does it represent the human player and the others are computer players ?

I think its misnamed, you can think it as Contestant/Contender who wants to contest, that can be anybody in the list of Players, I Choose MrC and sent messages to all other players, and all are human players.

>>are your rules for the game well defined? have you played out the game by hand some and looked for issues?

Yes, the program i shared is exactly the way it should be, do you see any problems?

And for your last point,

Given the Player & Winner(Contestant/Contender) problem is, this is my way of solving the problem, that may not be well designed.

My request here is, Its not just about the correctness of the program or getting correct output, it should be about well designed, considering the advantages that language has to offer like scalable, readable and manageable etc...

So I am ok to re-do it , learn and implement next time properly, I believe people like you here have better hands on than me.
Last edited on
yes, its so you can change it without a re-compile and scale it as well.
you can read a binary file randomly, but that is a bit of trouble. You can also do as you said and read file to a container, and randomize that. I would not use binary unless you plan to support millions of entries.

You are limited in main.

THIS is a limitation:
Player AAA("AAA","Apple","MrA","I");
Player BBB("BBB","Banana","MrB","I");
Player CCC("CCC","Cherry","MrC","I");
Player DDD("DDD","Durain","MrD","I");
Player EEE("EEE","Eggfruit","MrE","I");
Player FFF("FFF","FarkelBerry","MrF","I");

and this gets rid of it:
vector<Player> players;
… for everything in file, push_back players read in from file..

don't know if vector of players is best, think it through.

vectors are great. They are the first choice for most anything and you pick something else when the limitations of a vector or the perks of something else gain you something (this is why its good to know the other containers, there are times when vector isn't ideal, think about your data structures class … what are the weakness of an array, or a list, etc?)
Last edited on
To cut to the chase.

This is an undisciplined attempt at OOP. It is built like a camel and continues to have more humps and bumps added to cover the latest contingency.

The best advice, whether it comes from me or somebody else, is to plan your project. Currently it is bogged down in functional rubbish.

UML is ideal, but a simple pen and paper exercise defining the objects, their attributes and methods will go a long way to getting out of this multi-thread labyrinth.

If you write a line of code before you plan out your 'system' you are wasting your time.

Your naming conventions, as already mentioned by others, are redundant, silly in fact. eg A Player has a name. It's that simple. nameOfPlayer is nonsense.

Anyone with an ounce of experience with OOP knows a line like Gamer.ProcessMessageForVotes();, while not being wrong is a flag that something is seriously wrong. Methods already 'do' something so Process is redundant and vague, then it goes on talking about Messages and Votes which are probably object arguments to the method.

There isn't even a problem definition that clearly states the problem. One that enables a clear analysis and translation to OOP goes a long way, and believe me, this one is outstandingly bad. It should be set out properly, clearly and succinctly. Currently, it reads like the wrong side of the Rosetta Stone.

I know this will sound harsh, its not intended as a demotivator, but somebody needs to tell you.
Here are a few suggestions; this is for just a small part of this program; it covers only these:

> 1)Currently i have 6 players, out of which any number of players might contest
> I would like to extend the the current program for multiple random players

> 2)Contestants are not aware of other contestants.

> 3)Each contestant has to send a message to other players, other players will give support
> to the contestant only if the sent message has that particular player symbol in it.

Add to these, the requirements that there may be more than one contest and that there must be some object-oriented elements in the design.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <string>
#include <map>
#include <regex>
#include <functional>
#include <iomanip>

// abstract player: base class for all players
// (we need an abstract entity to be able to claim that our design is 'object-oriented')
struct abstract_player // pure interface
{
    virtual ~abstract_player() = default ;

    // every player has a unique symbol which identifies the player
    virtual std::string symbol() const = 0 ;

    virtual std::string name() const = 0 ;

    // players can recv messages from other players
    virtual void recv_message( const std::string& msg_text, const abstract_player& sender ) = 0 ;
};

// 2)Contestants are not aware of other contestants.
// 3)Each contestant has to send a message to other players,
// other players will give support to the contestant only if
// the sent message has that particular player symbol in it.

// helper function to check if the message text contains a player symbol
bool contains_symbol( const std::string& message_text, const std::string& player_symbol )
{
   // for simplicity, we assume that player symbols do not contain special characters like ., + etc.
   // regex: non-alphanumeric or beginning of text, player symbol (ignoring case),
   // non-alphanumeric or end of text
   // https://en.cppreference.com/w/cpp/regex
   // (you may want to adjust this regex depending on the structure of your actual messages)
   const std::regex symbol_re( "(?:\\W|^)" + player_symbol + "(?:\\W|$)", std::regex_constants::icase ) ;

   // return true if there is a match for the regex somewhere in the text
   // https://en.cppreference.com/w/cpp/regex/regex_search
   return std::regex_search( message_text, symbol_re ) ;
}

// 2)Contestants are not aware of other contestants.
// we use an observer pattern:
// https://en.wikipedia.org/wiki/Observer_pattern#What_problems_can_the_Observer_design_pattern_solve?

struct contest // the contest also acts as the observer
{
    explicit contest( std::string name ) : name( std::move(name) ) {}

    // map of contestants
    // key: player symbol (TO DO? : make it case-insensitive)
    // mapped data: wrapped reference to player
    // https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
    std::map< std::string, std::reference_wrapper<abstract_player> > contestants ;

    // add a player to the contest; return true if the player was added
    // (a player - identified by the unique symbol - can't be added more than once in a contest)
    bool add_player( abstract_player& player )
    {
        // https://en.cppreference.com/w/cpp/container/map/emplace
        return contestants.emplace( player.symbol(), player ).second ;
    }

    void remove_player( const std::string& player_symbol )
    { contestants.erase(player_symbol) ; }

    void publish_message( const std::string& message_text, const abstract_player& sender )
    {
        // check if the sender is in the contest
        const auto iter = contestants.find( sender.symbol() ) ;
        if( iter != contestants.end() ) // if sender was found in this contest
        {
            std::cout << "\n----------------------\ncontest: " << std::quoted(name)
                      << "\n----------------------\n" ;
            // propagate the message to all players whose symbols are part of the message text
            for( const auto& pair : contestants )
            {
                auto& player = pair.second.get() ; // get a reference to the player
                if(
                       contains_symbol( message_text, player.symbol() )
                       // (uncomment the next line if a player is not allowed to send a message to self)
                       // && player.symbol() != sender.symbol() // check for message to self
                  )
                {
                    player.recv_message( message_text, sender ) ;
                }
            }
        }
    }

    std::string name ; // name of the contest
};

// a concrete player class
struct player : abstract_player
{
     std::string symbol_ ;
     std::string name_ ;
     // etc.

     player( std::string symbol, std::string name )
         : symbol_( std::move(symbol) ), name_( std::move(name) ) {}

    virtual std::string symbol() const override { return symbol_ ; }
    virtual std::string name() const override { return name_ ; }

    // players can recv messages from other players
    virtual void recv_message( const std::string& msg_text, const abstract_player& sender ) override
    {
        // this is just a stub (prints out the information for now)
        std::cout << "player " << std::quoted( symbol() ) << " (" << name() << ')'
                  << "  recd a message from player " << std::quoted( sender.symbol() ) << " (" << sender.name() << ')'
                  << "\n    message text: " << std::quoted( msg_text ) << "\n\n" ;
    }

    // send message to participants in contest c
    void send_message( const std::string& msg_text, contest& c )
    { c.publish_message( msg_text, *this ) ; }
};

int main() // a toy illustration of the using the above in a program
{
    // create four players
    player a{ "aaa", "player_a" }, b{ "bbb", "player_b" }, c{ "ccc", "player_c" }, d{ "ddd", "player_d" } ;


    // the folowing part will go into a game class later on.

    // create a contest nd add some players to it
    contest test_contest{ "this is a test contest" } ;
    test_contest.add_player(a) ;
    test_contest.add_player(b) ;
    test_contest.add_player(c) ;

    // publish a message from a to other participants in test_contest
    // note that "ddd" won't get this message ("ddd" has not entered this contest)
    a.send_message( "hello bbb, ccc, ddd", test_contest ) ;

    // add d, remove c and repeat (in this case, a also sends a message to self)
    test_contest.add_player(d) ;
    test_contest.remove_player( c.symbol() ) ;
    a.send_message( "aaa says: hello again bbb, ccc, ddd", test_contest ) ;
}

http://coliru.stacked-crooked.com/a/46c0705d306d7ec8
https://rextester.com/KXVZ62363
againtry, I take every word of yours positively, because that's the way it is.
As you very much understood me clearly, I am a C programmer, so I am used to solve problems in functional way, OOP way of solving problems not entirely new to me , but I rarely do. So I kind of mixed-up in both Functional and OOP.

That's the main reason ,I requested people to have a look at my C solution.

As you pointed out , about my naming conventions I will keep in mind to use properly.

Please keep giving such positive feedback.

JLBorges, I think you will never disappoint any one once you enter the scene.

Your every line , supported with comments/reference..., its simply awesome.
Now, I will have look into your code and learn some new constructs...
Cheers @ravss2.
A couple of observations you may be aware of, especially after looking at this first-pass (ie a few announced limitations) on the OO approach:

1. If you remove the commentary and explanations, you are left with about 94 lines of code - and that includes main and test data. That is how powerful OO is, and that's not to get drawn into arguments about C vs C++ vs OO vs functional programming, most of which seems to me more often than not ego-driven know-all rubbish. (Edit: To remove any unintended ambiguity there, I'm not pointing at anyone on this thread of that.)

2. The reason the code flows the way it does is partially because it makes sense intuitively. And each method only comprises a couple of lines. More than that and a multi-function camel is being created.

3. Combine all that with better naming, and comments are almost unnecessary.

4. Teams are alluded to as a next-generation improvement. It is an almost obvious, certainly intuitively correct, abstraction to add.

5. Another class/struct could equally be Message.

6. While being as boring as batshit (as they say) why not have some meaningful test data that reflects real-world.

Last edited on
So , I will start re-designing/developing keeping all suggestions in mind.
But first, I am going to change my limited object creation to file based reading and creating objects from it and put them in a container like this std::map< std::string, std::reference_wrapper<abstract_player> >

I am also working on few similar problems that i will try to do better way


JLBorges, I am little confused about below,

Why you used struct instead of class?

Also, if i have to update any member in player how can i do it? because all it has only virtual interfaces?

i guesss we can override a set/update method in player right?
> Why you used struct instead of class?

The class keys struct and class are indistinguishable in C++, except that the default access mode and default inheritance mode are public if class declaration uses the struct class-key and private if the class declaration uses the class class-key. Both class and struct can be used in a class definition.

https://en.cppreference.com/w/cpp/language/classes


> i guesss we can override a set/update method in player right?

Yes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// TODO const, &, * 

#include <iostream>
#include <string>
#include <vector>

class Person
{
protected:
    std::string name = "*** Guess who? ***";
    
public:
    Person(){};
    Person(std::string aName){ name = aName; }
    ~Person(){}
    void setName(std::string aName){ name = aName; }
    std::string getName(){ return name; }
};

class Player: public Person
{
private:
    int score = 0; // TODO set & get & winner? blah, blah
    std::string symbol; // TODO set & get blah, blah
    
public:
    Player(){};
    Player(std::string aName){ this->setName(aName); }
    
    bool operator==(const Player aPlayer)
    {
        if(this->name == aPlayer.name)
            return true;
        else
            return false;
    }
};

class Team
{
private:
    std::vector<Player> team;
    std::vector<Player>::iterator it;
    std::string name;
    
public:
    Team(std::string aName){ name = aName; }
    ~Team(){}
    void addPlayer(Player aPlayer){ team.push_back(aPlayer); }
    
    void listPlayers()
    {
        std::cout << name << " team players:\n";
        for(auto it:team)
            std::cout << it.getName() << '\n';
        
        std::cout << '\n';
    }
    
    void deletePlayer(Player aPlayer)
    {
        it = find (team.begin(), team.end(), aPlayer);
        
        if (it != team.end())
            team.erase(it);
        else
            std::cout << "Element not found\n";
    }
};

class Message
{
private:
    std::string contents;
    Person sender;
    Person receiver;
    
public:
    Message(Person aSender, Person aReceiver, std::string aContent)
    {
        contents = aContent;
        sender = aSender;
        receiver = aReceiver;
    }
    
    ~Message(){}
    std::string getSender() { return sender.getName(); }
    std::string getReceiver() { return receiver.getName(); }
    std::string getContents(){ return contents; }
    // TODO check/find symbol blah blah
};

class Message_Server
{
private:
    std::vector<Message> vec_message;
    std::string name = "What server?";
    
public:
    Message_Server(){}
    Message_Server(std::string aName){ name = aName; }
    ~Message_Server(){}
    std::string getName(){ return name; }
    
    void sendMessage(Message aMessage)
    {
        vec_message.push_back(aMessage);
        std::cout << "Message sent ...\n";
    }
    
    void receivedMessages(Player aPlayer)
    {
        std::cout
        << "List of messages received by " << aPlayer.getName() << ":\n";
        
        for(auto it: vec_message)
        {
            if( it.getReceiver() == aPlayer.getName() )
            {
                std::cout
                << "   FROM: " << it.getSender() << '\n'
                << "MESSAGE: " << it.getContents() << '\n';
            }
        }
        std::cout << '\n';
    }
};

int main()
{
    // TEST PLAYER
    Player noname;
    std::cout << "Player: " << noname.getName() << '\n';
    
    Player member_1("Ted");
    Player member_2("Bob");
    Player member_3("Carol");
    Player member_4("Alice");
    std::cout << "Player: " << member_1.getName() << '\n';
    
    // TEST TEAM
    Team tigers("Tiger Cats");
    
    tigers.addPlayer(member_1);
    tigers.addPlayer(member_2);
    tigers.addPlayer(member_3);
    tigers.addPlayer(member_4);
    
    tigers.listPlayers();
    
    tigers.deletePlayer(member_3);
    tigers.addPlayer(noname);
    tigers.listPlayers();
    
    // TEST MESSAGE SERVER & MESSAGE
    Message_Server unknown_server;
    std::cout << "Message server: " << unknown_server.getName() << '\n';
    
    Message_Server msg_server("Hotmail");
    std::cout << "Message server: " << msg_server.getName() << '\n';
    
    Message msg_1{member_1, member_2, "To Bob, Test of message. Ted:)"};
    msg_server.sendMessage(msg_1);
    
    Message msg_2{member_1, member_4, "To Alice, Test of message. Ted:)"};
    msg_server.sendMessage(msg_2);
    
    Message msg_3{member_1, member_3, "To Carol, Test of message. Ted:)"};
    msg_server.sendMessage(msg_3);
    
    Message msg_4{member_4, member_3, "To Carol, Test of message. Alice:)"};
    msg_server.sendMessage(msg_4);
    msg_server.receivedMessages(member_3);
    
    unknown_server.sendMessage(msg_3);
    unknown_server.receivedMessages(msg_3.getReceiver());
    
    return 0;
}


Player: *** Guess who? ***
Player: Ted
Tiger Cats team players:
Ted
Bob
Carol
Alice

Tiger Cats team players:
Ted
Bob
Alice
*** Guess who? ***

Message server: What server?
Message server: Hotmail
Message sent ...
Message sent ...
Message sent ...
Message sent ...
List of messages received by Carol:
   FROM: Ted
MESSAGE: To Carol, Test of message. Ted:)
   FROM: Alice
MESSAGE: To Carol, Test of message. Alice:)

Message sent ...
List of messages received by Carol:
   FROM: Ted
MESSAGE: To Carol, Test of message. Ted:)

Program ended with exit code: 0
Topic archived. No new replies allowed.