d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > [C++] Pong Project > Ascii Art Game
Prev1456789Next
Add Reply New Topic New Poll
Member
Posts: 11,637
Joined: Feb 2 2004
Gold: 434.84
Oct 2 2009 03:28pm
Quote (Muted @ Fri, Oct 2 2009, 05:07pm)
You should have edited your post instead of posting twice - at anyrate...!
Somebody who knows and uses C/C++ often, and uses object oriented design (or the object oriented paradigm), could you explain to me how the program I wrote (Pong) is "bad?"
I created an object, and I initialized it, and I used it in a loop, which is proper as far as I know. There's nothing "wrong" about it, as it obviously compiles it. It is ineffecient but not "that" ineffecient I didn't think.

Could you modify it and post a more "proper" version of Pong...? With the exception of the colors?
Or I could post the SetColor/PlaceCursor functions for you.

Thanks. :)

EDIT: As much fun as this/the other discussion is, it's off-topic and I'd like my answer from the original posts!


Just creating "an object" is not Object Oriented programming. There is a design mind behind it. One major concept in OO that people often get wrong is the "Tell, Don't Ask" idiom. Here is a great explanation of it:

http://www.pragprog.com/articles/tell-dont-ask

(By the way, every self-respecting programmer should own a copy of "The Pragmatic Programmer" ;) )

This of course is just one small idiom in OO. There are many others and until you understand how they work for you, you won't get it and use it properly.

Member
Posts: 6,953
Joined: Sep 27 2003
Gold: 518.50
Oct 2 2009 03:30pm
Quote (Muted @ Fri, Oct 2 2009, 04:28pm)
Could you modify it and post a more "proper" version of Pong...? With the exception of the colors?
Or I could post the SetColor/PlaceCursor functions for you.

I could look at it, but I need TextControl.h
Member
Posts: 31,680
Joined: Nov 10 2007
Gold: 1.00
Oct 2 2009 03:31pm
Quote
Procedural code gets information then makes decisions. Object-oriented code tells objects to do things.
— Alec Sharp


From the beginning of that already, I agree with that.
The idea of.. It's incomprehendable and illogical in my eyes.


Quote (ASBands @ Fri, 2 Oct 2009, 16:30)
I could look at it, but I need TextControl.h


I'll post what's relevant from it - as there's a lot I've added to that library. :)

Code
/* Colors defined for SetColor(int) */
enum {
   BLACK       = 0,
   DARK_BLUE   = 1,
   DARK_GREEN  = 2,
   TEAL        = 3,
   DARK_RED    = 4,
   DARK_PURPLE = 5,
   GOLD        = 6,
   GREY        = 7,
   DARK_WHITE  = 8,
   BLUE        = 9,
   GREEN       = 10,
   CYAN        = 11,
   RED         = 12,
   PURPLE      = 13,
   YELLOW      = 14,
   WHITE       = 15
};

...

void SetColor(const int foreground) {

   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
   SetConsoleTextAttribute(hConsole, foreground);

   return;
}

void SetColor(const int foreground, const int background) {

   int Color = foreground + (background * 16);
   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
   SetConsoleTextAttribute(hConsole, Color);

   return;
}

...

void PlaceCursor(const int x, const int y) {

   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

   COORD PlaceCursorHere;
   PlaceCursorHere.X = x;
   PlaceCursorHere.Y = y;

   SetConsoleCursorPosition(hConsole, PlaceCursorHere);
   return;
}

...

void ClearConsole(const int foreground, const int background) {

   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

   COORD coordScreen = { 0, 0 };
   DWORD cCharsWritten;
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   DWORD dwConSize;

   if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) { return; }
   dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

   SetColor(foreground, background);
   if (!FillConsoleOutputCharacter(hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten)) { return; }
   if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) { return; }
   if (!FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten)) { return; }

   return;
}

...

void RemoveCursor() {

   /* Remove the cursor (does not work in full screen) */
   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
   CONSOLE_CURSOR_INFO CursoInfo;
   CursoInfo.dwSize = 1;         /* The size of caret */
   CursoInfo.bVisible = false;   /* Caret is visible? */
   SetConsoleCursorInfo(hConsole, &CursoInfo);

   return;
}

...

void DrawBox(const int Width, const int Height, const int PlaceX, const int PlaceY) {

   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

   /* Horizontal lines */
   for (int x = 0; x < Height; x++) { PlaceCursor(PlaceX, PlaceY + x); WriteConsole(hConsole, "º", 1, 0, NULL); }
   for (int x = 0; x < Height; x++) { PlaceCursor(PlaceX + Width - 1, PlaceY + x); WriteConsole(hConsole, "º", 1, 0, NULL); }

   /* Vertical lines */
   for (int x = 0; x < Width; x++) { PlaceCursor(PlaceX + x, PlaceY); WriteConsole(hConsole, "Í", 1, 0, NULL); }
   for (int x = 0; x < Width; x++) { PlaceCursor(PlaceX + x, PlaceY + Height - 1); WriteConsole(hConsole, "Í", 1, 0, NULL); }

   PlaceCursor(PlaceX, PlaceY); WriteConsole(hConsole, "É", 1, 0, NULL);                          /* Upper left corner   */
   PlaceCursor(PlaceX + Width - 1, PlaceY); WriteConsole(hConsole, "»", 1, 0, NULL);              /* Upper right corner  */
   PlaceCursor(PlaceX, PlaceY + Height - 1); WriteConsole(hConsole, "È", 1, 0, NULL);             /* Bottom left corner  */
   PlaceCursor(PlaceX + Width - 1, PlaceY + Height - 1); WriteConsole(hConsole, "¼", 1, 0, NULL); /* Bottom right corner */

   return;
}

void DrawBox(const int Color, const int Width, const int Height, const int PlaceX, const int PlaceY) {

   HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
   SetConsoleTextAttribute(hConsole, Color);

   /* Horizontal lines */
   for (int x = 0; x < Height; x++) { PlaceCursor(PlaceX, PlaceY + x); WriteConsole(hConsole, "º", 1, 0, NULL); }
   for (int x = 0; x < Height; x++) { PlaceCursor(PlaceX + Width - 1, PlaceY + x); WriteConsole(hConsole, "º", 1, 0, NULL); }

   /* Vertical lines */
   for (int x = 0; x < Width; x++) { PlaceCursor(PlaceX + x, PlaceY); WriteConsole(hConsole, "Í", 1, 0, NULL); }
   for (int x = 0; x < Width; x++) { PlaceCursor(PlaceX + x, PlaceY + Height - 1); WriteConsole(hConsole, "Í", 1, 0, NULL); }

   PlaceCursor(PlaceX, PlaceY); WriteConsole(hConsole, "É", 1, 0, NULL);                          /* Upper left corner   */
   PlaceCursor(PlaceX + Width - 1, PlaceY); WriteConsole(hConsole, "»", 1, 0, NULL);              /* Upper right corner  */
   PlaceCursor(PlaceX, PlaceY + Height - 1); WriteConsole(hConsole, "È", 1, 0, NULL);             /* Bottom left corner  */
   PlaceCursor(PlaceX + Width - 1, PlaceY + Height - 1); WriteConsole(hConsole, "¼", 1, 0, NULL); /* Bottom right corner */

   return;
}


That's everything that's relevant I believe.
If I'm missing something, let me know!

Thanks for looking at it. :D

This post was edited by Muted on Oct 2 2009 03:46pm
Member
Posts: 6,953
Joined: Sep 27 2003
Gold: 518.50
Oct 2 2009 03:42pm
Quote (Muted @ Fri, Oct 2 2009, 04:31pm)
That's everything that's relevant I believe.
If I'm missing something, let me know!

Thanks for looking at it. :D

You're missing DrawBox. Also, it doesn't matter, since you only have one main file, but you should never include function definitions in a header file. If you ever add multiple header files or cpp files, this will become an issue.

Basically, a header file is meant to tell your compiler that there is a definition of it somewhere. So, instead of:
Code
void PlaceCursor(const int x, const int y) {

  HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

  COORD PlaceCursorHere;
  PlaceCursorHere.X = x;
  PlaceCursorHere.Y = y;

  SetConsoleCursorPosition(hConsole, PlaceCursorHere);
  return;
}

Do:
Code
void PlaceCursor(const int x, const int y);

in your header file and the implementation of PlaceCursor in another .cpp file. This will ensure that there is only ONE implementation of the function and it will be resolved at link-time. Also, you always want to include multi-include protectors, like #pragma once or #ifdef protectors, this ensures that a headed file is only included once.
Member
Posts: 31,680
Joined: Nov 10 2007
Gold: 1.00
Oct 2 2009 03:47pm
Quote (ASBands @ Fri, 2 Oct 2009, 16:42)
You're missing DrawBox.  Also, it doesn't matter, since you only have one main file, but you should never include function definitions in a header file.  If you ever add multiple header files or cpp files, this will become an issue.

Basically, a header file is meant to tell your compiler that there is a definition of it somewhere.  So, instead of:

Do:
in your header file and the implementation of PlaceCursor in another .cpp file.  This will ensure that there is only ONE implementation of the function and it will be resolved at link-time.  Also, you always want to include multi-include protectors, like #pragma once or #ifdef protectors, this ensures that a headed file is only included once.


I thought that's what the #ifndef HEADERFILE_H and #endif were for in header files...?
I've never quite understood the logic behind having to have a project to compile everything.
... Plus there's like a bunny trail/tree of 20,000 header files in iostream/windows alone.

I posted the DrawBox functions FYI (edited them). Sorry I forgot about them.

This post was edited by Muted on Oct 2 2009 03:48pm
Member
Posts: 6,953
Joined: Sep 27 2003
Gold: 518.50
Oct 2 2009 03:56pm
Quote (Muted @ Fri, Oct 2 2009, 04:47pm)
I thought that's what the #ifndef HEADERFILE_H and #endif were for in header files...?
I've never quite understood the logic behind having to have a project to compile everything.
... Plus there's like a bunny trail/tree of 20,000 header files in iostream/windows alone.

I posted the DrawBox functions FYI (edited them). Sorry I forgot about them.

I thought what you sent the header file and all the definitions were in it, as it's a really common mistake. In not, ignore.

TextControl.h:
Code
#pragma once

enum
{
  BLACK       = 0,
  DARK_BLUE   = 1,
  DARK_GREEN  = 2,
  TEAL        = 3,
  DARK_RED    = 4,
  DARK_PURPLE = 5,
  GOLD        = 6,
  GREY        = 7,
  DARK_WHITE  = 8,
  BLUE        = 9,
  GREEN       = 10,
  CYAN        = 11,
  RED         = 12,
  PURPLE      = 13,
  YELLOW      = 14,
  WHITE       = 15
};

void SetColor(const int foreground);

void SetColor(const int foreground, const int background);

void PlaceCursor(const int x, const int y);

void ClearConsole(const int foreground, const int background);

void RemoveCursor();

void DrawBox(const int Color, const int Width, const int Height, const int PlaceX, const int PlaceY);

I prefer the #pragma once syntax, since it is prettier and the compiler can actually do it faster (your definitions can be #undefed, so the file has to be opened on each include, whereas a pragma directive cannot be undone).
Member
Posts: 31,680
Joined: Nov 10 2007
Gold: 1.00
Oct 2 2009 03:58pm
And where would I define all the functions at? TextControl.cpp
While we're on that note: I'd simply include the TextControl.h as usual...?

EDIT: Still waiting on the modified version of the program, no offense! I'm rather curious how it'll look... :)

This post was edited by Muted on Oct 2 2009 04:00pm
Member
Posts: 6,953
Joined: Sep 27 2003
Gold: 518.50
Oct 2 2009 04:15pm
Quote (Muted @ Fri, Oct 2 2009, 04:58pm)
And where would I define all the functions at? TextControl.cpp
While we're on that note: I'd simply include the TextControl.h as usual...?

Right, you put the actual definitions in in a TextControl.cpp file, which will look like your old header file. Basically, this make iterative building happen much faster than before. When a .cpp is compiled, it generated an intermediate, unlinked format version in a .o file. Any good compiler keeps the unlinked .o files around before the link stage (where the .o files are combined into the machine code). So, if you change the implementation of TextControl.cpp but no other part of the project, the compiler will re-compile the .o file for TextControl.cpp, but re-use all the cached .o files. Compilation is slow and expensive, so you can imagine how well this would translate up to larger projects.

Quote (Muted @ Fri, Oct 2 2009, 04:58pm)
EDIT: Still waiting on the modified version of the program, no offense! I'm rather curious how it'll look... :)

You should start a Google Code project, because I split your project into 10 source files...

This post was edited by ASBands on Oct 2 2009 04:15pm
Member
Posts: 31,680
Joined: Nov 10 2007
Gold: 1.00
Oct 2 2009 04:17pm
Quote (ASBands @ Fri, 2 Oct 2009, 17:15)
You should start a Google Code project, because I split your project into 10 source files...


Translation: I posted the code in expectation of you keeping your word (or at least what I interpreted as being "your word"), and you just /denied it.
That's fine, thanks anyways. I was hoping to see your opinion of how it should've been. For a game as simple and small as Pong, it shouldn't take that long to modify/write.

Oh, maybe I mis interpreted what you'd said.. Something about google project --> Feel free to e-mail me it all if you don't want to post it here.
Digital.Goddess@yahoo.com is my e-mail address I use.

This post was edited by Muted on Oct 2 2009 04:19pm
Member
Posts: 6,953
Joined: Sep 27 2003
Gold: 518.50
Oct 2 2009 04:25pm
Quote (Muted @ Fri, Oct 2 2009, 05:17pm)
Translation: I posted the code in expectation of you keeping your word (or at least what I interpreted as being "your word"), and you just /denied it.
That's fine, thanks anyways. I was hoping to see your opinion of how it should've been. For a game as simple and small as Pong, it shouldn't take that long to modify/write.

Oh, maybe I mis interpreted what you'd said.. Something about google project --> Feel free to e-mail me it all if you don't want to post it here.
Digital.Goddess@yahoo.com is my e-mail address I use.


Patience, I'm doing a minor refactor. Don't worry, it will come to you ;)
Go Back To Programming & Development Topic List
Prev1456789Next
Add Reply New Topic New Poll