Jump to content
  • Advertisement
Sign in to follow this  
Cool_Program_Guy

Connect Four Help

This topic is 4172 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey All I'm making a connect four game. What I need help is to drop an x or o into the grid and get it to update the grid. - i cant think how to program it. I've used an array and struct to create the grid. The grid is 7 by 7. Thank for any help. The code i have is the follow :-
#include <iostream>
using namespace std;

struct player 
{
	char counter; // 'O' or 'X'
	char name[20]; // player 1 and player 2 name
	int  won; // counts how many time player 1 or 2 has won 
	int lost; // counts how many times player 1 and 2 has lost
	int draw; //counts how many time player 1 or 2 has draw 
};

struct column 
{
	char rows[7]; // arrays 7 row on the grid
	int count; // 
};

column frame[7]; // used for the frame

void players_details()
{
  system("cls");
  
  player player1; 
  player player2; 

  player1.counter = 'X';
  player2.counter = 'O';

  cout<<"Player 1 Please Enter Your First Name\n";
  cout<<endl;
  cin >> player1.name;
  cout<<endl;
  
  cout<<"Player 2 Please Enter Your First Name\n";
  cout<<endl;
  cin>>player2.name;
  cout<<endl;
  
  cout<<player1.name <<" Counter Is "<<player1.counter<<endl;
  cout<<endl;
  cout<<player2.name <<" Counter Is "<<player2.counter<<endl;
  cout<<endl;
  cout<<player1.name <<" Vs "<<player2.name<<endl;
  cout<<endl;
}

void clearGrid()
{
	for (int i=0;i<7;i++) {
		for (int j=0; j<7; j++)
		{         
			frame.rows[j] = ' ';
		}
		frame.count = 0;
	}
}

void drawGrid()
{
  system("cls");
  cout<<endl;
	for (int i=6; i>= 0; i--) { 
		for (int j=0; j<7; j++)
		{         
			cout << "|" << frame.rows[j]; 
		}
		cout << "|";
		cout << endl;
	}
	cout<<endl;
}

void drawCounterGrid() -The is the function to draw an x or o which i need help
{
  
}

int main()
{
 system("cls");
 int choice;

 cout<<"Connect Four Version 1.0\n";
 cout<<endl;
 
 cout<<"Menu\n";
 cout<<endl;
 cout<<"1) Start A Game\n";
 cout<<"2) Manual How To Play The Game\n"; // TODO
 cout<<"3) Top 20 High Players\n"; // TODO
 cout<<"4) Quit Game\n"<<endl;
 cout<<"Please Select 1 To 4:\n";
 cout<<endl;
 cin>>choice;
 cout<<endl; 
 switch(choice)
 {
	 case 1:
        players_details();
        drawGrid();
        clearGrid();
        drawCounterGrid();
 }
 return choice;
}

[Edited by - Cool_Program_Guy on March 9, 2007 4:47:39 PM]

Share this post


Link to post
Share on other sites
Advertisement
I might have misunderstood what you're asking for here but this is my shot anyway:

First off: you're really missing a game loop [which I'd say is the basic component of any game]. You *could* carry on doing it as you have it set up by adding most of your game logic to the drawCounterGrid() function but there really is a better way of organizing this. What I would do is go to your initial menu [in your main() function] and have case 1: call a new function to init your game info [this gets the players details and clears/draws the grid] then you jump into your main game loop:

Within the game loop what happens each time would be something along the lines of:

1] Ask player 1 where he wants to place his counter [simple cin cout stuff all he needs to say is the column he wants to place the counter in]
2] Check if there is space in that column to place a counter
3] If the column is full: ask for input again [1]
4] If the column is not full: place the counter in the appropriate row in that column [loop through the column until you either hit the bottom or find a non-empty slot, then place your counter in the slot above it]
5] Redraw the grid with the new counter in place.
6] Check for a win condition [Have some algorithm that checks if there are 3 connected counters - I would probably just check the positions adjacent to the newly placed counter instead of looping through the whole grid]
7] If the player won : end the game [quit the game loop , increment the player's win stat : display any end messages/menu etc]
8] If the player did not win - are there any other endgame scenarios? [check for them and end appropriately]
9] Switch players and start at [1] for the next player

hope this helps.

Share this post


Link to post
Share on other sites
Xqwzts seemed to put it pretty good I thought. It isn't as simple as just calling a function, though that doesn't mean it's difficult.

based on what you have so far, you would need to loop through the elements of the appropriate column to find the location of the lower-most square.


//frame = array of columns
//choice = chosen column to place marker in
//current_marker = current player's marker. (X or O)

if(frame[choice].rows[6] != ' '){
//THIS ROW IS FULL, ASK AGAIN
}else{
for(int i = 5; i >= -1; i--){ //start at the top, and work down.
if(frame[choice].rows != ' ' || i == -1){
//FOUND FIRST EMPTY SPOT
frame[choice].rows[(i+1)] = current_marker;
break;
}
}
}





I'm sure it could be done much better, including removing all the magic numbers, not to mention the loop is kindof ugly. But the basic idea is there.

Share this post


Link to post
Share on other sites
I would suggest using a pointer to the current player for getting input. This way you only have one loop with one section of code to get input and check if there is a game over situation. As for knowing when to stop, just check if the board is full, and check to see if the last move made any win situations (by checking in lines going away from the last move).

Share this post


Link to post
Share on other sites
First of all, I wanted to clarify that you are making a console project (which is why it's black and white). Console projects don't use graphics, only text. If you stick with programming you will learn that you can also make Win32 applications, but those require you to use something like OpenGL or Direct3D for graphics, and a bunch of windows API code. In other words, that is a HUGE HUGE step, but you are on the right track by learning the basics with a console/text game. I just want you to realize that you won't be making Halo 2 next week, this stuff takes A LOT of practice, patience, and persistence. :)

You should try to get in the mindset of writing functions to accomplish things. So, when you ask the question "how am I going to check for a win?" You should start thinking how you could make a function that knows nothing about your project, other than how to check if there was a win last turn, and simply return the results. In order to do this, what would your function need access to? Well, it needs the grid, correct? Since you are using it as a global variable you don't need to pass it in to the function so you're good. The other thing I would suggest is giving access to is the last square on the grid somebody moved to, so I will make that as two parameters for the row and column of that given square.

Here is the general idea you should shoot for. This code isn't tested and it most definitely isn't optimized. If I were writing it for that I woulda probably made the algorithm in one for-loop, but this was just a quick mock up to give you an idea of what you should be trying to do.



bool CheckWin(const int last_move_row, const int last_move_col)
{
const char check_for = frame[last_move_col].rows[last_move_row];
int in_a_row = 0;

/* since your grid is only 7x7 you might as well check the entire
row and the entire column the last move lied on, because if the
player went right in the middle it could be a win on either side */


/* check the row */
for(int col = 0; col < 7; ++col)
{
if(frame[col].rows[last_move_row] == check_for)
++in_a_row;
else
in_a_row = 0;

if(in_a_row == 4)
return true;
}

in_a_row = 0;

/* check the column */
for(int row = 0; row < 7; ++row)
{
if(frame[last_move_col].rows[row] == check_for)
++in_a_row;
else
in_a_row = 0;

if(in_a_row == 4)
return true;
}

in_a_row = 0;

/* this would normally be - 3, but I didn't want to check
in the for loop if I did a continue... */

int current_col = last_move_col - 4;

/* check one of the diagnols */
for(int row = last_move_row - 3; row < 7; ++row)
{
++current_col;

/* make sure to only check on the grid... */
if(row < 0 || current_col < 0 || current_col >= 7)
continue;

if(frame[current_col].rows[row] == check_for)
++in_a_row;
else
in_a_row = 0;

if(in_a_row == 4)
return true;
}

in_a_row = 0;
current_col = last_move_col + 4; /* normally 3, same as above */

/* check the other diagnol */
for(int row = last_move_row - 3; row < 7; ++row)
{
--current_col;

/* make sure to only check on the grid... */
if(row < 0 || current_col < 0 || current_col >= 7)
continue;

if(frame[current_col].rows[row] == check_for)
++in_a_row;
else
in_a_row = 0;

if(in_a_row == 4)
return true;
}

return false;
}




I hope this helps! Good luck!

[Edited by - Nvii on April 7, 2007 2:01:30 PM]

Share this post


Link to post
Share on other sites
Hey thanks, yeh I done bit of background reading on c++ I do have a book on c++ but its not the best (might buy a new 1)

Thanks for the code :) What I'll do is use your code and then do as you suggested.

Anyway thanks again mate :)


Share this post


Link to post
Share on other sites
Hey, I just testing bit that code you used and it giving an error saying:-

Error 1 error C2660: 'CheckWin' : function does not take 0 arguments


if (move = 1) {
do {
do {
cout<<player1.name<<" Please Enter A Column 1 To 7\n";
cout<<endl;
cin>>choice;
choice--;
} while ((choice <0) ||(choice >7));
} while (frame[choice].count ==7);
}
{ drawGrid();
CheckWin();
addCounter(player1.counter,choice);
move++;
}



I assume you put the CheckWin() before you allow the user to put a peice into the grid??

The only thing I changed with the code you gave was an
int num_in_a_row; 

as that was declared anywhere.

Would I be right thinking its somthing to with the bool in it??

Share this post


Link to post
Share on other sites
The "CheckWin" function he posted takes 2 integers, the row of the last move and the column of the last move. When you call it in your code, you just have "CheckWin()". You need to send it those two numbers for it to compile correctly.

CheckWin(rownum, columnnum);

Share this post


Link to post
Share on other sites
Quote:
Original post by Cool_Program_Guy
if (move = 1) {...}

"Put the value 1 into variable move." The result of this assignment is 1, which is interpreted as true. Are you sure this is what you want?

To compare two integer expressions, you must use the "==" operator.

Share this post


Link to post
Share on other sites
Hmm,still doest wrk, does it need a pointer?

Error 1 error C2065: 'last_move_row' : undeclared identifier
Error 2 error C2065: 'last_move_col' : undeclared identifier


const int last_move_row, const int last_move_col)
addCounter(player2.counter,choice);


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!