Skip to main content
GameDev.net gamedev.net
🔒 Locked

Move over Sid Meyer...

Started by Silicon Viking May 5, 2008 at 11:54 AM 30 replies 4.6k views
Original Post
Silicon Viking
Silicon Viking
...cuz thar's a new sheriff in town! I JUST FINISHED MY FIRST GAME!!! Yes, it is just a console-based (or whatever you call that command-line doo-hicky) tic-tac-toe game, the code is a mockery of the C++ language, and it could use a LOT of polish, but, by Odin, it's A PLAYABLE (at least sorta) GAME!!! Now on to make my super-cool Quake clone with thousands of weapons! ;)
----------------------------From the fury of the Northmen, O Lord, deliver us!
Cromulent
Cromulent
Good job :). I'm sure it has just increased your desire to do more programming so keep at it.

I know that is what I am trying to do.
Silicon Viking
Silicon Viking
Quote:
Original post by Cromulent
I'm sure it has just increased your desire to do more programming so keep at it.

It has and I will!

I'm related to the great Nolan Bushnell, father of the video game. This is in my blood! I cannot waver! I cannot let up!

EDIT
Quote:
Original post by Cromulent
I know that is what I am trying to do.

May you have much luck in your efforts!
----------------------------From the fury of the Northmen, O Lord, deliver us!
Kalten
Kalten
If you wanted some critique on your code it might pay to put it up somewhere and invite people to have a look... it might help find some messy parts of your coding, which will assist you in not making the same nasty code later.
Silicon Viking
Silicon Viking
Quote:
Original post by Kalten
If you wanted some critique on your code it might pay to put it up somewhere and invite people to have a look... it might help find some messy parts of your coding, which will assist you in not making the same nasty code later.

I'll do that, but after I polish it up a bit. There are some design mistakes of which I'm already aware, so I'll fix those before I post any code.
----------------------------From the fury of the Northmen, O Lord, deliver us!
thre3dee
thre3dee
post the game itself?
Silicon Viking
Silicon Viking
Quote:
Original post by thre3dee
post the game itself?

I can't access the computer on which the game is. I'll post the game and source tomorrow (it's 8:51 PM at my location).

EDIT: Fixed dangled preposition
----------------------------From the fury of the Northmen, O Lord, deliver us!
Silicon Viking
Silicon Viking
Here it is.
#include <cstdlib>#include <iostream>#include <vector>using namespace std;vector<char> board;const char X = 'X';const char O = 'O';const char TIE = 'T';const char NO_WIN = 'N';const char INVALID = 'I';const char EMPTY = ' ';char winner;char playerPiece;char computerPiece;char turn = 'X';const int WINNING_ROWS[8][3] = {{0,1,2},                                {3,4,5},                                {6,7,8},                                {0,3,6},                                {1,4,7},                                {2,5,8},                                {0,4,8},                                {2,4,6}};void display();char checkWin();void getPlayerMove();void AIMove();char swapPiece(char piece);void initBoard();void initBoard(){    for(int i = 0; i < 9; ++i)    {        board.push_back(EMPTY);    }}void display(){       cout << board[0] << "|" << board[1] << "|" << board[2] << endl;    cout << "-----" << endl;    cout << board[3] << "|" << board[4] << "|" << board[5] << endl;    cout << "-----" << endl;    cout << board[6] << "|" << board[7] << "|" << board[8] << endl;}char swapPiece(char piece){    if(piece == X)        return O;    else if(piece == O)        return X;        return INVALID;}void getPlayerMove(){    cout << "Where do you want to put your " << playerPiece << "?" << endl;    cout << "0|1|2\n";    cout << "-----\n";    cout << "3|4|5\n";    cout << "-----\n";    cout << "6|7|8\n";    int choice = -1;    while(choice < 0 || choice > 8)    {        cout << "Enter a number (0-8): ";        cin >> choice;        if(choice < 0 || choice > 8)        {            continue;            cout << "INVALID NUMBER\n";        }        if(board[choice] != EMPTY)        {            cout << "That space is already taken.\n";            choice = -1;        }    }    board[choice] = playerPiece;}void AIMove(){    for(int i = 0; i < 8; ++i)    {        if(board == EMPTY)        {            board = computerPiece;            if(checkWin() == computerPiece) return;            board = EMPTY;        }    }        for(int i = 0; i < 8; ++i)    {        if(board == EMPTY)        {            board = playerPiece;            if(checkWin() == playerPiece)            {                board = computerPiece;                return;            }            board = EMPTY;        }    }        for(int i = 0; i < 8; ++i)    {        if(board == EMPTY)        {            board = computerPiece;            return;        }    }}char checkWin(){    for(int i = 0; i < 8; ++i)    {        if(board[WINNING_ROWS[0]] != EMPTY && board[WINNING_ROWS[0]] == board[WINNING_ROWS[1]] && board[WINNING_ROWS[1]] == board[WINNING_ROWS[2]])        {            return board[WINNING_ROWS[0]];        }    }    if(count(board.begin(), board.end(), EMPTY) == 0) return TIE;    return NO_WIN;}int main(int argc, char *argv[]){    initBoard();    // ask the player which piece he/she wants    while(playerPiece != X && playerPiece != O)    {        cout << "Which piece do you want? (X/O)";        cin >> playerPiece;        playerPiece = toupper(playerPiece);    }    // assign the other piece to the computer    computerPiece = swapPiece(playerPiece);    // while there is no winner    while(1)    {        // display the         display();        // if turn equals playerPiece        if(turn == playerPiece)        {            cout << "It's your turn.\n";            // ask the player where he/she wants to put the piece            getPlayerMove();        }        else // if turn doesn't equal playerPiece        {            // have the computer place a piece            cout << "It's the computer's turn.\n";            system("PAUSE");            AIMove();        }        // switch the turn        turn = swapPiece(turn);        // check for a winner        winner = checkWin();        if(winner != NO_WIN) break;    }    // display the win/lose/tie message    display();    if(winner == playerPiece)        cout << "You win!\n";    else if(winner == computerPiece)        cout << "You lost.\n";    else        cout << "The game was a tie.\n";    system("PAUSE");    return EXIT_SUCCESS;}
----------------------------From the fury of the Northmen, O Lord, deliver us!
Silicon Viking
Silicon Viking
I take the silence to mean that I have not failed miserably. What should I do next? I'm thinking about doing something sort of like Alter Ego, only simpler of course. Maybe I should play with conio or curses and make a mini roguelike.
----------------------------From the fury of the Northmen, O Lord, deliver us!
Crehl
Crehl
Hah, that code brings back memories. Both of the version I wrote on my calculator (I can't remember if I fully finished Connect 4 - it took a few seconds to check for wins), and one I wrote in VB (Yes, a long time ago..).

Congrats on getting it finished, I can't really comment on the code, as I'm not sure what the best way to program it is. From what I can see though, it looks quite good. There are a few minor things I'd personally change, however.

Have you tried something such as Pong, or maybe Breakout?
Thaumaturge
Thaumaturge
[edit] My apologies for forgetting to say it, but congratulations on your first game! ^_^ [/edit]

If you're interested in curses and Roguelike mechanics, may I suggest an old game of mine as a new project?

It's called, quite simply, "Kill the Monster", and involves... well, killing the monster, while avoiding being killed by the monster. As basic as it sounds (and it is, I would say), I think that it could be a good start, and it should be possible to expand it to Roguelike gameplay, I think.

Simply put, you use the keyboard to direct a character, and attempt to shoot a monster that is attempting to shoot you. Points are gained by shooting the monster, and lost by being shot by the monster, both of which result in the randomisation of the positions of the character and the monster. Ammunition may be implemented, in which case it is collected by running over "ammunition crates" that appear at random on the play-field. Finally, high-score tables and difficulty levels may be implemented.

The steps that I'd suggest (although feel free to chart your own course, of, well, course! ^_^) are as follows:


  • Draw a character to the screen at a particular x and y. I'm partial to the ASCII smiley-face, personally.

  • Read key input and use that to move the character around, ensuring that the character's prior position is cleared.

    • Note that the program shouldn't wait for key input, but keep running. ;)

  • Introduce a monster (represented by another character, of course) that attempts to move towards the player, but not get too close.

  • Allow the player to fire a bullet (again represented by yet another character).
    • Test the bullet's/bullets' position(s) against that of the monster
      • If a hit is detected, randomise the positions of the characters, and add one to a score variable. Note that you may want to be careful with your resulting locations, specifically avoiding the pair appearing too close together.

    • (Whether you allow for more than one bullet on the screen at a time depends on your knowledge and preferences, I imagine.)

  • Allow the monster to shoot back. If the player is hit, subtract a point from the player's score and randomise the characters' positions. gain, you may want to take care with the resulting positions.

  • Introduce ammunition, both as a limited resource for the player and as something for the player to collect.

  • Create a high-score table; when the player quits, ask for their name and append their name and score to a file.

  • Introduce difficulty levels (the simplest variation is probably to have this affect the monster's speed, but other variations, such as ammunition availability, might be considered).

MWAHAHAHAHAHAHA!!! My Twitter Account: @EbornIan
Silicon Viking
Silicon Viking
How would I make the game continue running? The getch() function pauses the program.
----------------------------From the fury of the Northmen, O Lord, deliver us!
fastcall22
fastcall22
Use kbhit().

while ( true ){	if ( _kbhit() && _getch() == 'q' )		break;}
Silicon Viking
Silicon Viking
Ah! Many thanks to ye all!
----------------------------From the fury of the Northmen, O Lord, deliver us!
Thaumaturge
Thaumaturge
[edit] Nevermind - _fastcall, aptly named, provided the answer, it seems. ^_^

My part was my pleasure - I'm glad to have been, I hope, of service. ^_^[/edit]
MWAHAHAHAHAHAHA!!! My Twitter Account: @EbornIan
Silicon Viking
Silicon Viking
Quote:
Original post by Thaumaturge
I'm glad to have been, I hope, of service.

Aye! Ye have!

----------------------------From the fury of the Northmen, O Lord, deliver us!
Mybowlcut
Mybowlcut
Can I criticise this? :D

Overload checkWin as something like:
char checkWin(char c, int i)
Then you can just pass in the check and the index and let checkWin take care of it (and still use the version with no parameters). That way you can relieve AIMove of the duty of setting elements in the array back to EMPTY and what not.

Also, don't use globals... if you're up to the stage of classes, use one instead.

Pretty good for a first game!

thre3dee
thre3dee
A lot of games and applications employ the 'Application' class to remove global methods.

class Application{public:	// this might load the menu objects and textures and create the renderer	bool Init ();	// this is typically function that does a logic loop	void Run ();	// tells Run() to stop... running	void Exit ();	// destroys the application objects	void Close ();	// gets the objects	Renderer* GetRenderer ();	GameObject* GetObject (const char* name);private:	Renderer renderer;	List <GameObject> objects;	List <LogicController> logic;	List <Texture> textures;	bool running;};// In our main function we create an Application object and run itint main (){	Application app;	if (!app.Init ()) {		MessageBox (0, "Error initialising application!", "App", MB_ICONERROR);		return 1;	}	app.Run ();	app.Close ();	return 0;}
Chrono1081
Chrono1081
Quote:
I'm related to the great Nolan Bushnell, father of the video game.


Actually, not to rain on your parade but Ralph Baer is usually considered the father of the video game. (Even though there were people who made games before him)
DevFred
DevFred
Quote:
Original post by Silicon Viking
I take the silence to mean that I have not failed miserably.

continue immediately jumps to the next iteration, so anything after continue will not be executed:
if(choice < 0 || choice > 8){    continue;    cout << "INVALID NUMBER\n"; // <--- never executes}


You can make the swapPiece method more compact if you don't need the INVALID-case (and I don't think you do):
char swapPiece(char piece){    return O + X - piece;}


On your overall design: I wouldn't use characters to store game state, but for a small game like this I guess it's ok.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.