Posts: 1,553
Threads: 77
Joined: May 2011
03-10-2014, 07:49 PM
(This post was last modified: 03-10-2014, 07:53 PM by A-Man.)
Hello everyone!
So I have been facing a lot of problem with communicating my code to other fella programmers. Mainly because I was never concerned about how my code looks as long as it works which, I admit, has always been a mistake from my side. General notes I've got from others are:
1-You work with headers like a noob.
2-Comment more.
3-Comment less (and that is when I actually try to "comment more" in my code).
4-You're suffering from longlinegitis; the lines of codes are too long.
1-I don't quite understand what they mean there. The way everyone does it is weirder in my opinion. In my case, I've got a .cpp file for my main. The rest are .h files because they are just function definitions which are used in the main. Others seem to have both a .h AND a .cpp file for almost everything. .h are made to store the function parameters, while the cpp contains the definitions. I just can't get why do they do this. Don't know, but perhaps, can this be something to do with how a programmer should read other sources? Would be interested to know if there is a pattern, as I often can't get what file in the source should I start from (the main).
2-I have to admit that it is mostly me being lazy there.
3-And this happened when I tried commenting. People said I am explaining obvious things there:
http://pastebin.com/sQj4nMja
In general, what kind of lines do I need to comment? I mean, I can't know the level of the programmer who's going to read my code, can I? People vary in their abilities to read a piece of code.
4-The problem is, I sometimes just NEED to call a function with so many parameters, which in turn leads to such long liners. A solution to this problem is to simply store all the parameters in an array, and using it as the parameter instead. But what if I have all the parameters of different data types? Is there a way I can pack such things together? Or is it something I just have to avoid? Any tips on how I can manage length of a line of a code?
P.S: When I call a function and use a certain class's object as a parameter, will this involve copying the whole object to be used? Now what if I use a pointer to the object; will this mean I will only be pushing the 8-digit address and that is it?
I've also noticed that a debugger usually gets stuck when you try to find the value of something like this:
Code: class1->arrayofobjects[class1->someindexint]->an_int_arrayinclass[class2->someindexint]
Now that had my wondering whether it is because this kind of call is a bit expensive memory-wise (is it?). I am always questioning when it comes to low level processes such as the above. In general, low-level is supposed to be faster. But is that true in the above case?
I would really, REALLY appreciate any advice that would help me write in a better way. Thanks in advance!
Edit: A source by me:
http://pastebin.com/PkLxyQEB
http://pastebin.com/pzQVXfUT
http://pastebin.com/vbj1MCFn
http://pastebin.com/ig4pkQfw
Thanks given by:
Posts: 1,020
Threads: 61
Joined: Mar 2008
1) Yes, the general pattern is each class has its own .cpp and .h file. This keeps everything tidy. So:
Code: class Eval{
private:
int temp1, temp3;
std::string temp2;
public:
Eval(std::string);
std::string POWER(std::string);
std::string DIVIDE(std::string);
std::string MULTIPLY(std::string);
std::string ADD(std::string);
std::string SUBTRACT(std::string);
std::string ADDORSUBTRACT(std::string);
std::string MULTIPLYORDIVIDE(std::string);
std::string IntToStr(float);
std::string operation;
bool BEval(std::string);
std::string ISEQUAL(std::string);
std::string ISNOTEQUAL(std::string);
std::string ISGREATER(std::string);
std::string ISSMALLER(std::string);
std::string ISGREATERE(std::string);
std::string ISSMALLERE(std::string);
std::string AND(std::string);
std::string OR(std::string);
};
would be in the .h file and the Eval::BEval would go into the .cpp file.
2 & 3) This is a topic which is debated a lot. Usually only comment at the top of the function explaining the parameters & return values. Don't include comments inside your function unless it's a "hacky" solution to a problem which you couldn't solve nicely.
4) In the past, people used to limit their line length to 80 characters. Now days it's more like 120 characters. If it's more than that, make a new line.
So: Code: void Graphics::renderTexture(
TextureId texture,
const SDL_Rect* sourceRect,
const SDL_Rect* destinationRect) const
{
//render image to render target at destination rectangle
SDL_RenderCopy(renderer, texture, sourceRect, destinationRect);
}
};
instead of Code: void Graphics::renderTexture(TextureId texture,const SDL_Rect* sourceRect,const SDL_Rect* destinationRect) const
{
SDL_RenderCopy(renderer, texture, sourceRect, destinationRect);
}
Some comments:
1) You should use a different naming convention. All caps for function names is annoying to read, and not widely used. Common practice is:
*) camelCase for functions
*) ALLCAPS for constants
*) Classes with CamelCase (first letter capitalized)
*) members belonging to variables are prepended/appended with _ (so _x or x_ if you had a class with a member x)
2) Your function names are non obvious "std:  tring Evaluayh(std:  tring strvalue)" I read that and I have no idea what the hell Evaluayh means.
3) You need to split up your program more, separate the logic into more classes. Have a "Graphics" class, used for drawing. Have a "Sprite" class that can be used to store texture information, and input class to manage input etc etc.
4) Indentation, you need to do this properly! Most editors should do this automatically!
Code: std::string larg,rarg;
std::string a=asdf;
int ilarg, irarg;
std::string exceptionss=":?~[]{}&$^";
That is NEVER acceptable!
5) Do not leave "commented out" code in your source files. Learn to use git or svn or something. Use that to manage your code rather than comments.
Posts: 2,343
Threads: 79
Joined: Mar 2008
HAH! Since I never collaborate with others when it comes to programming or scripting I am a 100% guilty of always writing badly formatted code. Silvas eyes shall bleed forever.
Anyway. I still do understand why people criticize you on 2, 3 and 4 (no experience with 1). And also why you should try to get it right (if you are working in a team at least - or planning to make work easier for your future self if you ever intend to look at your old rubbish again).
Let's go!
(03-10-2014, 07:49 PM)A-MAN Wrote: 3-Comment less (and that is when I actually try to "comment more" in my code).
3-And this happened when I tried commenting. People said I am explaining obvious things there:
http://pastebin.com/sQj4nMja
In general, what kind of lines do I need to comment? I mean, I can't know the level of the programmer who's going to read my code, can I? People vary in their abilities to read a piece of code. Ever heard of KISS? This concept applies to commenting too. First of all you are making all comments unnecessarily long. They are supposed to be straight forward comments, not lyrics or prose.
Turn "//the key position values and the real position of the pic" into "//key position values, real position of pic".
Turn "//Renders textures into the screen" into "//render textures".
Turn "//stores the whole text in system.a" into "//store whole text in system.a".
Also you have to stick to writing comments that can help understand the code faster. Don't repeat the same "stores xy" comment over several lines. Everyone capable of reading the code in the first place will see that you have a bunch lines with the same command right there. Your comments should never overpower your code and make it harder to read.
This explains it better than I can: http://stackoverflow.com/questions/11156...ment-ratio
(03-10-2014, 07:49 PM)A-MAN Wrote: 4-You're suffering from longlinegitis; the lines of codes are too long.
4-The problem is, I sometimes just NEED to call a function with so many parameters, which in turn leads to such long liners. A solution to this problem is to simply store all the parameters in an array, and using it as the parameter instead. But what if I have all the parameters of different data types? Is there a way I can pack such things together? Or is it something I just have to avoid? Any tips on how I can manage length of a line of a code? Break lines. It'll be a hell lot easier to read, modify and comment long parameter/condition lists that way.
Posts: 746
Threads: 55
Joined: Apr 2008
(03-10-2014, 07:49 PM)A-MAN Wrote: Hello everyone!
So I have been facing a lot of problem with communicating my code to other fella programmers. Mainly because I was never concerned about how my code looks as long as it works which, I admit, has always been a mistake from my side. General notes I've got from others are:
1-You work with headers like a noob.
2-Comment more.
3-Comment less (and that is when I actually try to "comment more" in my code).
4-You're suffering from longlinegitis; the lines of codes are too long. I'll try to answer these questions to the best of my ability.
(03-10-2014, 07:49 PM)A-MAN Wrote: 1-I don't quite understand what they mean there. The way everyone does it is weirder in my opinion. In my case, I've got a .cpp file for my main. The rest are .h files because they are just function definitions which are used in the main. Others seem to have both a .h AND a .cpp file for almost everything. .h are made to store the function parameters, while the cpp contains the definitions. I just can't get why do they do this. Don't know, but perhaps, can this be something to do with how a programmer should read other sources? Would be interested to know if there is a pattern, as I often can't get what file in the source should I start from (the main). The Compiler compiled (translates) ".cpp" files into computer readable code (assembly), and the code is then placed in what is called an object file (which is basically computer readable code with names associated with it (called symbols), and probably some other stuff) usually with the extension ".obj".
Then the Linker takes these files and combines them into an executable file, or a library.
Whenever you use "#include" it is essentially the same as copying and pasting the contents of the included file into the current file, and thus there will only be one object file after your project has been compiled, which will mean that if you make ANY change in ANY file, then every file has to be recompiled.
If you instead have the actual code in separate .cpp files, and you make a change to a file, only that one file has to be recompiled.
It is also just nicer to look at for other programmers, because they don't have to bother with what is inside a function, and thus it is easier to get an overview.
(03-10-2014, 07:49 PM)A-MAN Wrote: 2-I have to admit that it is mostly me being lazy there. Well, you are not the only one :p I suck at this too :D
(03-10-2014, 07:49 PM)A-MAN Wrote: 3-And this happened when I tried commenting. People said I am explaining obvious things there:
http://pastebin.com/sQj4nMja
In general, what kind of lines do I need to comment? I mean, I can't know the level of the programmer who's going to read my code, can I? People vary in their abilities to read a piece of code. It is a very tricky thing, and as a general reminder, if you are unsure whether or not to add a comment, then add it anyway.
That said stuff that is contained in the name of a class, or variable generally doesn't need a comment (coordinates for example).
I find myself commenting stuff that looks counter intuitive such as:
C++-Code:
if(Something) DoSomething();
{//int Temp should be temporary, has nothing to do with previous if-statement
int Temp = GetSomeInteger();
DoSomethingWithInteger();
}//int Temp goes out of scope
|
If the comments weren't there a lot of people would thing the if-statement was connected to the block, or they wouldn't know why all of a sudden there is a block in the code.
Also whenever you are using the goto-keyword, a lot of people get confused, and pointing out the intention is pretty useful.
(03-10-2014, 07:49 PM)A-MAN Wrote: 4-The problem is, I sometimes just NEED to call a function with so many parameters, which in turn leads to such long liners. A solution to this problem is to simply store all the parameters in an array, and using it as the parameter instead. But what if I have all the parameters of different data types? Is there a way I can pack such things together? Or is it something I just have to avoid? Any tips on how I can manage length of a line of a code? There are a few options for this.
One thing you can do is to split the function parameters across multiple lines like:
GML-Code:
d3d_set_projection_ext(x,y,z,
x+sin(dir*pi/180)*cos(zdir*pi/180),y+cos(dir*pi/180)*cos(zdir*pi/180),z+sin(zdir),
0,0,1,angle,window_get_width()/window_get_height(),znear,zfar);
|
This is what I tend to do, but sometimes this can get completely overwhelming (or tiresome for the cpu since it passes a lot of bytes to the function)
In this case you can use a structure to store the values like:
C++-Code:
typedef struct {
double xfrom;
double yfrom;
double zfrom;
double xto;
double yto;
double zto;
double xup;
double yup;
double zup;
unsigned int angle;
float aspect;
unsigned int znear;
unsigned int zfar;
} ProjectStruct;
//...
ProjectStruct Projection;
Projection.xfrom = x;
//...
d3d_set_projection_ext(&Projection);
|
(03-10-2014, 07:49 PM)A-MAN Wrote: P.S: When I call a function and use a certain class's object as a parameter, will this involve copying the whole object to be used? Now what if I use a pointer to the object; will this mean I will only be pushing the 8-digit address and that is it? Yes.
Another method is passing it as a reference (which the compiler handles the same way but looks a lot nicer, and is generally safer):
C++-Code:
//passing as pointer
d3d_set_projection_ext(const ProjectStruct *Projection);
//...
d3d_set_projection_ext(&Projection);
//passing as reference
d3d_set_projection_ext(const ProjectStruct &Projection);
//...
d3d_set_projection_ext(Projection);
|
The above will compile to exactly the same code, so it really depends on what syntax you prefer.
(03-10-2014, 07:49 PM)A-MAN Wrote: I've also noticed that a debugger usually gets stuck when you try to find the value of something like this:
Code: class1->arrayofobjects[class1->someindexint]->an_int_arrayinclass[class2->someindexint]
Now that had my wondering whether it is because this kind of call is a bit expensive memory-wise (is it?). I am always questioning when it comes to low level processes such as the above. I'm not sure why the debugger fails the above. I'm not too experienced with such things.
(03-10-2014, 07:49 PM)A-MAN Wrote: In general, low-level is supposed to be faster. But is that true in the above case? Faster compared to what?
In general low-level code doesn't mean faster.
Most high level code such as C++ gets compiled into assembly, which is low level code, and the Compiler does its best to make it as fast as possible, so in many cases the difference between code written in C++ and code written fully in assembly is marginal at best, and the assembly easily turns out completely riddled with bugs, because there are so many things that can go wrong if you don't keep track of everything.
If you write the above code and have optimization turned on, generally the compiler will optimize it well enough for you.
When it comes to debuggers, I think the way it works, is that the compiler stores the names of variables and such things in the executable when you make a debug build of your program, and then the debugger can access this data and find out what the code looks like, and access the values of variables and such. It isn't nearly as fast as compiled code though, since the debugger has to access this during runtime of the program.
And I know I'm double :ninja:'d but whatever...
Age ratings for movies and games (and similar) have never been a good idea.
One can learn a lot from reinventing wheels.
An unsound argument is not the same as an invalid one.
volatile in C++ does not mean thread-safe.
Do not make APIs unnecessarily asynchronous.
Make C++ operator > again
Trump is an idiot.
Posts: 1,553
Threads: 77
Joined: May 2011
03-11-2014, 07:09 PM
(This post was last modified: 03-11-2014, 07:10 PM by A-Man.)
@Silva: Woh! Never knew there was such a thing as a "line length limit". 120 lines it is.
Regarding the headings: Something strange I've also noticed is the usage of Preprocessor commands like "#define" "#ifdef" before importing headers. I mean there isn't a chance the computer would accidentally include a header twice (supposing that's the purpose of using them; the preprocessor conditionals), is there?
Really thanks for all that! I am going to look into Git in a second.
@YinYin: lol. Your AI codes seems really neat in fact. Thanks!!
@Someone else: OOh I see now! Now for that example code you posted; did that pair of brackets actually opened a local scope?! That's AWESOME!! The perfect way to do processes with temporary variables!
I don't quite like the goto key word honestly :/. It destroys what object oriented programming is all about.
Awesome usage of typedef there! Never actually thought of doing that.
I always pass large class parameters as pointers just like you did there. It seems that was the only thing I was doing right XD.
Thanks for all that info!
Another question:
There is this function I stole from the internet:
C++-Code:
SDL_Color translate_color(Uint32 int_color)
{
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
SDL_Color color={(int_color & 0x00ff0000)/0x10000,(int_color &
0x0000ff00)/0x100,(int_color & 0x000000ff),0};
#else
SDL_Color color={(int_color & 0x000000ff),(int_color &
0x0000ff00)/0x100,(int_color & 0x00ff0000)/0x10000,0};
#endif
return color;
}
|
He/She used the preprocessor conditionals instead of the normal if (?).
Now when is it better to use such methods?
Thanks given by:
Posts: 746
Threads: 55
Joined: Apr 2008
03-11-2014, 07:47 PM
(This post was last modified: 03-11-2014, 10:09 PM by Som1Lse.)
(03-11-2014, 07:09 PM)A-MAN Wrote: @Silva: Woh! Never knew there was such a thing as a "line length limit". 120 lines it is.
Regarding the headings: Something strange I've also noticed is the usage of Preprocessor commands like "#define" "#ifdef" before importing headers. I mean there isn't a chance the computer would accidentally include a header twice (supposing that's the purpose of using them; the preprocessor conditionals), is there? Not exactly sure what you mean with this.
Are you talking about this:
C++-Code:
#ifndef _FILE_H_
#define _FILE_H_
//some code
#endif // _FILE_H_
|
If you are then the reason is to avoid including the same file multiple times, as that might cause problems (like declaring the same thing twice).
This isn't generally an issue, but when you have cross dependencies (for example two functions that call each other) then this can be necessary.
(03-11-2014, 07:09 PM)A-MAN Wrote: @Someone else: OOh I see now! Now for that example code you posted; did that pair of brackets actually opened a local scope?! That's AWESOME!! The perfect way to do processes with temporary variables! It works like that yes.
(03-11-2014, 07:09 PM)A-MAN Wrote: I don't quite like the goto key word honestly :/. It destroys what object oriented programming is all about. Nope.
Object Oriented programming is using stuff like classes and the stuff you can do with them (polymorphism etc.).
The goto keyword is a completely different thing.
For example it can be used to break out of two loops at once:
C++-Code:
for(int i = 0;i<something;++i){
for(int j = 0;j<something;++j){
if(condition) goto after_loops;//break can't do this
//do something
}
}
after_loops:
//more code
|
Another question:
There is this function I stole from the internet:
C++-Code:
SDL_Color translate_color(Uint32 int_color)
{
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
SDL_Color color={(int_color & 0x00ff0000)/0x10000,(int_color &
0x0000ff00)/0x100,(int_color & 0x000000ff),0};
#else
SDL_Color color={(int_color & 0x000000ff),(int_color &
0x0000ff00)/0x100,(int_color & 0x00ff0000)/0x10000,0};
#endif
return color;
}
|
He/She used the preprocessor conditionals instead of the normal if (?).
Now when is it better to use such methods?
[/quote]
The "#if"-thing only works if the values are known when the Preprocessor is run (which is before the Compiler).
This means that if SDL_BYTEORDER == SDL_BIG_ENDIAN is true, then the previous code will be:
C++-Code:
SDL_Color translate_color(Uint32 int_color)
{
SDL_Color color={(int_color & 0x00ff0000)/0x10000,(int_color &
0x0000ff00)/0x100,(int_color & 0x000000ff),0};
return color;
}
|
Which is what the compiler will see, and thus it won't include the other code in the program which will never execute anyway.
If you were to use the if-statement, then SDL_BYTEORDER and SDL_BIG_ENDIAN would be replaced with numbers like:
C++-Code:
SDL_Color translate_color(Uint32 int_color)
{
if(1234 == 4321){
SDL_Color color={(int_color & 0x00ff0000)/0x10000,(int_color &
0x0000ff00)/0x100,(int_color & 0x000000ff),0};
return color;
}else{
SDL_Color color={(int_color & 0x000000ff),(int_color &
0x0000ff00)/0x100,(int_color & 0x00ff0000)/0x10000,0};
return color;
}
}
|
And then the Compiler would compile the above code, which may put code that won't execute in the program.
That said 99% of Compilers will recognize that the statement 1234 == 4321 is always false, and will only include the second part of the code, so in the end it comes down to what you prefer, and the given situation.
In the above example notice how I moved the return statement inside the if-statement, as otherwise the variable "color" would go out of scope before the return statement was reached.
Age ratings for movies and games (and similar) have never been a good idea.
One can learn a lot from reinventing wheels.
An unsound argument is not the same as an invalid one.
volatile in C++ does not mean thread-safe.
Do not make APIs unnecessarily asynchronous.
Make C++ operator > again
Trump is an idiot.
Posts: 1,020
Threads: 61
Joined: Mar 2008
I think you misunderstood. I meant 120 characters per line. not 120 lines per file.
http://stackoverflow.com/questions/90375...th-in-code
The linux kernel still sets the limit at 80:
https://www.kernel.org/doc/Documentation/CodingStyle
10 ʏᴇᴀʀs sɪɴᴄᴇ ɪʀᴄ ɢᴏᴏᴅ.ɪ ᴡᴀʟᴋ ᴛʜʀᴏᴜɢʜ ᴛʜᴇ ᴇᴍᴘᴛʏ sᴛʀᴇᴇᴛs ᴛʀʏɪɴɢ ᴛᴏ ᴛʜɪɴᴋ ᴏғ sᴏᴍᴇᴛʜɪɴɢ ᴇʟsᴇ ʙᴜᴛ ᴍʏ ᴘᴀᴛʜ ᴀʟᴡᴀʏs ʟᴇᴀᴅs ᴛᴏ ᴛʜᴇ ɪʀᴄ. ɪ sᴛᴀʀᴇ ᴀᴛ ᴛʜᴇ sᴄʀᴇᴇɴ ғᴏʀ ʜᴏᴜʀs ᴀɴᴅ ᴛʀʏ ᴛᴏ sᴜᴍᴍᴏɴ ᴛʜᴇ ɢᴏᴏᴅ ɪʀᴄ. ɪ ᴡᴀᴛᴄʜ ᴏᴛʜᴇʀ ɪʀᴄ ᴄʜᴀɴɴᴇʟs ʙᴜᴛ ɪᴛ ɪs ɴᴏ ɢᴏᴏᴅ. ɪ ᴘᴇsᴛᴇʀ ᴢᴏʀᴛ ᴀɴᴅ ᴛʀʏ ᴛᴏ ʀᴇsɪsᴛ ʜɪs sᴇxɪɴᴇss ʙᴜᴛ ɪᴛ ɪs ᴀʟʟ ᴍᴇᴀɴɪɴɢʟᴇss. ᴛʜᴇ ᴇɴᴅ ɪs ɴᴇᴀʀ.ɪ ᴛʜᴇɴ ᴜsᴜᴀʟʟʏ ʀᴇᴀᴅ sᴏᴍᴇ ᴏʟᴅ ɪʀᴄ ʟᴏɢs ᴀɴᴅ ᴄʀʏ ᴍʏsᴇʟғ ᴛᴏ sʟᴇᴇᴘ.
Thanks given by:
Posts: 1,553
Threads: 77
Joined: May 2011
@Someone else: Cool! That's a smart use of goto. And thanks for all the explanation.
@Silva: Not really; that was just a typo :P The kernel code style documentation thing you linked to is worth a read though.
Thanks y'all!!!
Thanks given by:
Posts: 1,020
Threads: 61
Joined: Mar 2008
@Gad: There are are many ( http://en.wikipedia.org/wiki/Indent_style ) different indention styles :P.
From my experience, the one you use is common with Java programmers. C/C++ code is usually written with the bottom style (from the code I've seen anyway).
10 ʏᴇᴀʀs sɪɴᴄᴇ ɪʀᴄ ɢᴏᴏᴅ.ɪ ᴡᴀʟᴋ ᴛʜʀᴏᴜɢʜ ᴛʜᴇ ᴇᴍᴘᴛʏ sᴛʀᴇᴇᴛs ᴛʀʏɪɴɢ ᴛᴏ ᴛʜɪɴᴋ ᴏғ sᴏᴍᴇᴛʜɪɴɢ ᴇʟsᴇ ʙᴜᴛ ᴍʏ ᴘᴀᴛʜ ᴀʟᴡᴀʏs ʟᴇᴀᴅs ᴛᴏ ᴛʜᴇ ɪʀᴄ. ɪ sᴛᴀʀᴇ ᴀᴛ ᴛʜᴇ sᴄʀᴇᴇɴ ғᴏʀ ʜᴏᴜʀs ᴀɴᴅ ᴛʀʏ ᴛᴏ sᴜᴍᴍᴏɴ ᴛʜᴇ ɢᴏᴏᴅ ɪʀᴄ. ɪ ᴡᴀᴛᴄʜ ᴏᴛʜᴇʀ ɪʀᴄ ᴄʜᴀɴɴᴇʟs ʙᴜᴛ ɪᴛ ɪs ɴᴏ ɢᴏᴏᴅ. ɪ ᴘᴇsᴛᴇʀ ᴢᴏʀᴛ ᴀɴᴅ ᴛʀʏ ᴛᴏ ʀᴇsɪsᴛ ʜɪs sᴇxɪɴᴇss ʙᴜᴛ ɪᴛ ɪs ᴀʟʟ ᴍᴇᴀɴɪɴɢʟᴇss. ᴛʜᴇ ᴇɴᴅ ɪs ɴᴇᴀʀ.ɪ ᴛʜᴇɴ ᴜsᴜᴀʟʟʏ ʀᴇᴀᴅ sᴏᴍᴇ ᴏʟᴅ ɪʀᴄ ʟᴏɢs ᴀɴᴅ ᴄʀʏ ᴍʏsᴇʟғ ᴛᴏ sʟᴇᴇᴘ.
Thanks given by:
Posts: 341
Threads: 10
Joined: Oct 2012
like this ?????
Code: #include<iostream>
#include<sstream>
#include<conio.h>
#include<windows.h>
using namespace std;
int GEN;
/************************************CLASS*OF*CELL*FOR*GETTING*AND*SETTING*ALIVE*CELL***********************************/
class Cell
{
private:
bool Cell_Check;
public:
bool Cell_Get()const
{
return(Cell_Check);
}
void Cell_Set(bool Stats)
{
Cell_Check = Stats;
}
};
int main()
{
system("color 0A");
int cell_x, cell_y;
char choice;
/***************************************BASIC*GRID*INPUT*****************************************************/
cout << "Enter dimensions of your cell \20\20\20" << endl;
cin >> cell_x >> cell_y;
Cell Grid[cell_y][cell_x], Dead[cell_y + 2][cell_x + 2], Next_Grid[cell_y][cell_x];
for(int i = 0; i < cell_y + 2; i++)
{
for(int j = 0; j < cell_x + 2; j++)
{
Dead[i][j].Cell_Set(false);
}
}
for(int i = 0; i < cell_y; i++)
{
for(int j = 0; j < cell_x; j++)
{
Grid[i][j].Cell_Set(false);
Next_Grid[i][j].Cell_Set(false);
}
}
cout << "Do you want to give input through coordinates(c) or you want to try navigation input system(n) \20\20\20" << endl;
cin >> choice;
fflush(stdin);
/***********************************************************************************************************************8/
/************************************************INPUT*THROUGH*COORDINATES********************************************************************/
if(choice == 'c')
{
int co_x, co_y;
char ch_a;
for(int i = 0; ; i++)
{
cout << "Enter the coordinates \20\20\20 " << endl;
cin >> co_x >> co_y;
Grid[co_y][co_x].Cell_Set(true);
cout << "Do you want to add more \20\20\20" << endl;
cin >> ch_a;
if(ch_a == 'n')
break;
}
/**********************************************************************************************************************/
/****************************************OUTPUT*OF*USER'S*INPUT************************************************/
cout << "Your input is \20\20\20" << endl;
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if(Grid[y][x].Cell_Get() == false)
cout << " . ";
else if(Grid[y][x].Cell_Get() == true)
cout << " * ";
}
cout << endl << endl;
}
}
/*****************************************************************************************************************/
/*****************************************NAVIGATOR SYSTEM*******************************************************/
else if(choice == 'n')
{
cout << "Use W,A,S,D keys to navigate and press K to make the cell alive" << endl;
char key_Arrow;
int move_A = 0, move_B = 0;
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if((x == move_A) && (y == move_B))
cout << " <> ";
else
{
if(Grid[y][x].Cell_Get() == false)
cout << " . ";
if(Grid[y][x].Cell_Get() == true)
cout << " * ";
}
}
cout << endl << endl;
}
/*************************************BASIC*KEY*NAVIGATION*********************************************************/
for(int inf = 0; ; inf++)
{
key_Arrow = getch();
if(key_Arrow == 'w') //UP
move_B--;
if(key_Arrow == 's') //DOWN
move_B++;
if(key_Arrow == 'a') //LEFT
move_A--;
if(key_Arrow == 'd') //RIGHT
move_A++;
if(key_Arrow == 'k') //ALIVE
Grid[move_B][move_A].Cell_Set(true);
if(key_Arrow == 13)
break;
system("cls");
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if((x == move_A) && (y == move_B))
cout << " <> ";
else
{
if(Grid[y][x].Cell_Get() == false)
cout << " . ";
if(Grid[y][x].Cell_Get() == true)
cout << " * ";
}
}
cout << endl << endl;
}
}
/******************************************************************************************************/
/*******************************OUTPUT*OF*USER'S*INPUT***********************************************/
cout << "Your input is \20\20\20" << endl;
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if(Grid[y][x].Cell_Get() == false)
cout << " . ";
else if(Grid[y][x].Cell_Get() == true)
cout << " * ";
}
cout << endl << endl;
}
}
/**************************************************************************************************************/
/*********************************MAIN GAME OF LIFE************************************************************/
int flag = 0;
char Gen, G = 'y';
cout << "Do you want to view all generations(a) one by one or a specific generation(s) \20\20\20 " << endl;
cin >> Gen;
fflush(stdin);
if(Gen == 's')
{
cout << "Enter generation e.g. 25 for 25 generation \20\20\20 ";
cin >> GEN;
}
for(int k = 0; ; k++)
{
for(int j = 1; j <= cell_y; j++)
{
for(int i = 1; i <= cell_x; i++)
{
Dead[j][i].Cell_Set(Grid[j - 1][i - 1].Cell_Get());
}
}
int c = 0;
for(int i = 1; i <= cell_y; i++)
{
for(int j = 1; j <= cell_x; j++)
{
if(Dead[i][j + 1].Cell_Get() == true)
c++;
if(Dead[i][j - 1].Cell_Get() == true)
c++;
if(Dead[i + 1][j].Cell_Get() == true)
c++;
if(Dead[i + 1][j + 1].Cell_Get() == true)
c++;
if(Dead[i + 1][j - 1].Cell_Get() == true)
c++;
if(Dead[i - 1][j].Cell_Get() == true)
c++;
if(Dead[i - 1][j + 1].Cell_Get() == true)
c++;
if(Dead[i - 1][j - 1].Cell_Get() == true)
c++;
if(c < 2)
Next_Grid[i - 1][j - 1].Cell_Set(false);
if(c == 3 && Dead[i][j].Cell_Get() == false)
Next_Grid[i - 1][j - 1].Cell_Set(true);
if((c == 2 || c == 3) && Dead[i][j].Cell_Get() == true)
Next_Grid[i - 1][j - 1].Cell_Set(true);
c = 0;
}
}
if(Gen == 's')
{
if(k == GEN)
break;
}
/*************************************CHECKS*FURTHER*GENERATIONS*ARE*SAME*******************************************/
flag = 0;
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if(Grid[y][x].Cell_Get() != Next_Grid[y][x].Cell_Get())
flag = 1;
}
}
if(flag == 0)
{
cout << "further generations are all same";
break;
}
/*****************************************************************************************************************/
/***********************************ALL*GENERATIONS*******************************************************/
if(Gen == 'a')
{
if(G == 'y')
{
cout << "Generation #" << k + 1 << " \20\20\20" << endl;
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if(Grid[y][x].Cell_Get() == false)
cout << " . ";
else if(Grid[y][x].Cell_Get() == true)
cout << " * ";
}
cout << endl << endl;
}
}
else
break;
G == getch();
}
for(int j = 0; j < cell_y; j++)
{
for(int i = 0; i < cell_x; i++)
{
Grid[j][i].Cell_Set(Next_Grid[j][i].Cell_Get());
Next_Grid[j][i].Cell_Set(false);
}
}
for(int j = 0; j < cell_y + 2; j++)
{
for(int i = 0; i < cell_x + 2; i++)
{
Dead[j][i].Cell_Set(false);
}
}
}
/**********************************************************************************************************/
/*******************************************N*GENERATION*************************************************************/
if(Gen == 's')
{
cout << "Generation # " << GEN << " \20\20\20" << endl;
for(int y = 0; y < cell_y; y++)
{
for(int x = 0; x < cell_x; x++)
{
if(Grid[y][x].Cell_Get() == false)
cout << " . ";
else if(Grid[y][x].Cell_Get() == true)
cout << " * ";
}
cout << endl << endl;
}
}
/**********************************************************************************************************/
system("pause");
}
Thanks given by:
|