• 0

[C++] Tic Tac Toe with Variable Size Board


Question

We've just started learning arrays and the what-not in my C++ class. Our assignment is to create a tic tac toe program that has a user-set variable size board (3x3, 4x4, 9x9, etc). He gave us an example 3x3 tic tac toe program listed below a week back or so and told us to play around with it to make it multi-sized. I've started playing with it slightly, but for the most part, am I just going to change the constant values of 3 to variables? I thought you could not set an array to size variable?

#include <stdio.h>
#include <stdlib.h>

char matrix[3][3];  /* the tic tac toe matrix */

char check(void);
void init_matrix(void);
void get_player_move(void);
void get_computer_move(void);
void disp_matrix(void);

int main(void)
{
  char done;

  printf("This is the game of Tic Tac Toe.\n");
  printf("You will be playing against the computer.\n");

  done =  ' ';
  init_matrix();

  do {
	disp_matrix();
	get_player_move();
	done = check(); /* see if winner */
	if(done!= ' ') break; /* winner!*/
	get_computer_move();
	done = check(); /* see if winner */
  } while(done== ' ');

  if(done=='X') printf("You won!\n");
  else printf("I won!!!!\n");
  disp_matrix(); /* show final positions */

  return 0;
}

/* Initialize the matrix. */
void init_matrix(void)
{
  int i, j;

  for(i=0; i<3; i++)
	for(j=0; j<3; j++) matrix[i][j] =  ' ';
}

/* Get a player's move. */
void get_player_move(void)
{
  int x, y;

  printf("Enter X,Y coordinates for your move: ");
  scanf("%d%*c%d", &x, &y);

  x--; y--;

  if(matrix[x][y]!= ' '){
	printf("Invalid move, try again.\n");
	get_player_move();
  }
  else matrix[x][y] = 'X';
}

/* Get a move from the computer. */
void get_computer_move(void)
{
  int i, j;
  for(i=0; i<3; i++){
	for(j=0; j<3; j++)
	  if(matrix[i][j]==' ') break;
	if(matrix[i][j]==' ') break;
  }

  if(i*j==9)  {
	printf("draw\n");
	exit(0);
  }
  else
	matrix[i][j] = 'O';
}

/* Display the matrix on the screen. */
void disp_matrix(void)
{
  int t;

  for(t=0; t<3; t++) {
	printf(" %c | %c | %c ",matrix[t][0],
			matrix[t][1], matrix [t][2]);
	if(t!=2) printf("\n---|---|---\n");
  }
  printf("\n");
}

/* See if there is a winner. */
char check(void)
{
  int i;

  for(i=0; i<3; i++)  /* check rows */
	if(matrix[i][0]==matrix[i][1] &&
	   matrix[i][0]==matrix[i][2]) return matrix[i][0];

  for(i=0; i<3; i++)  /* check columns */
	if(matrix[0][i]==matrix[1][i] &&
	   matrix[0][i]==matrix[2][i]) return matrix[0][i];

  /* test diagonals */
  if(matrix[0][0]==matrix[1][1] &&
	 matrix[1][1]==matrix[2][2])
	   return matrix[0][0];

  if(matrix[0][2]==matrix[1][1] &&
	 matrix[1][1]==matrix[2][0])
	   return matrix[0][2];

  return ' ';
}

9 answers to this question

Recommended Posts

  • 0

Yes, you could start with a maximum size matrix and the jsut replace the 3's by a variable N (which would be the size)

also you'll need a double loop in

for(i=0; i<3; i++)  /* check rows */
	if(matrix[i][0]==matrix[i][1] &&
	   matrix[i][0]==matrix[i][2]) return matrix[i][0];

  for(i=0; i<3; i++)  /* check columns */
	if(matrix[0][i]==matrix[1][i] &&
	   matrix[0][i]==matrix[2][i]) return matrix[0][i];

  /* test diagonals */
  if(matrix[0][0]==matrix[1][1] &&
	 matrix[1][1]==matrix[2][2])
	   return matrix[0][0];

  if(matrix[0][2]==matrix[1][1] &&
	 matrix[1][1]==matrix[2][0])
	   return matrix[0][2];

which will allow you to check the entire row or column

  • 0

You could also use the STL (standard template library) vector class for a dynamic array size based on user input. There's plenty of examples online (cplusplus.com for instance). Consider it if you absolutely have to have a dynamic size board that could be any size - otherwise, the past comments about a max size would work too and probably be more familiar to you.

  • 0
  rpgfan said:
Or if you feel experienced enough, you could always create it dynamically yourself... Just remember that the amount of memory available is finite. In other words, don't forget to delete[] what you allocate! ^_^

Good tip! :) It is very important to take care of the garbage collection functionality (e.g. cleanup any unneeded resources). It is a good habit to get into.

Also, for this task couldn't you simply create a variable called "rows" and a variable called "columns" and have the user enter the number for each? Then, if I am correct, you would simply pass the array that you create the values that were entered.

Edited by winlonghorn
  • 0

Thanks for all the replies guys...considering my experience and the scope of the course, I believe I'll stick with setting a constant for the matrix. Now I'm trying to actually get the matrix to display correctly.

char matrix[26][26];  // the tic tac toe matrix

char check(void);
void init_matrix(int BOARD_SIZE);
void get_player_move(void);
void get_computer_move(void);
void disp_matrix(int BOARD_SIZE);
void get_player2_move(void);
void get_computer2_move(void);

/* Initialize the matrix. */
void init_matrix(int BOARD_SIZE)
{
  int i, j;

  for(i=0; i<BOARD_SIZE; i++)
	for(j=0; j<BOARD_SIZE; j++) matrix[i][j] =  ' ';
}

//Display the matrix
void disp_matrix(int BOARD_SIZE)
{
int t; int u;
//Cosmetic bar above |---|---|---|
	printf("|");
	for (t=0; t<BOARD_SIZE; t++)
	do{
	if (t != BOARD_SIZE) printf("---|");}
	while(t>BOARD_SIZE);

//Bar t
	printf("\n|");
	do{
	for (u=0; u<BOARD_SIZE; u++)
	printf(" %c |", matrix [0][u]);
	}while(u>BOARD_SIZE);


//Cosmetic bar below |---|---|---|
	printf("\n|");
	for (t=0; t<BOARD_SIZE; t++)
	do{
	if (t != BOARD_SIZE) printf("---|");}
	while(t>BOARD_SIZE);
	printf("\n");

}

I'm slowly getting it. This will display only one vertical bar, but with the correct amount of spaces horizontally. I believe I just need to add another for loop....for (t=0, t<BOARD_SIZE; t++)....is this correct?

Edited by entropypl
  • 0

Take the habit of typing your loops in full, it'll save you a lot of subtle bugs. Later when you feel very confident and are working alone on a project, you can do one-line loops with no brackets.

When you write a for loop, for instance, start by writing :

for ([initialization]; [break condition]; [increment]) {

}

Next, write what's inside the loop :

for ([initialization]; [break condition]; [increment]) {
	[statement 1];
	[statement 2];
	....
}

The same goes for if statements, functions, classes, while loops, anything that has a body. Except maybe individual cases in a switch statement.

I say this because your code is pretty hard to understand as it is, and it could break the minute you do any kind of modification to it. Take for instance this :

  for(i=0; i&lt;BOARD_SIZE; i++)
	for(j=0; j&lt;BOARD_SIZE; j++) matrix[i][j] =  ' ';

Let's say you have a second matrix, overlayed upon the first, which you'll want to initialize in the same spot. You might want to write :

  for(i=0; i&lt;BOARD_SIZE; i++)
	for(j=0; j&lt;BOARD_SIZE; j++) matrix1[i][j] =  ' '; matrix2[i][j] = ' ';

If this compiles, it will not do what you want. Can you tell why? Actually, the compiler will save you there, but it can't do the guesswork all the time. Just write the loops properly :

for(i=0; i&lt;BOARD_SIZE; i++) {
	for(j=0; j&lt;BOARD_SIZE; j++) { 
		matrix1[i][j] =  ' ';
		matrix2[i][j] = ' ';
	}
}

  • 0
  Dr_Asik said:
Take the habit of typing your loops in full, it'll save you a lot of subtle bugs. Later when you feel very confident and are working alone on a project, you can do one-line loops with no brackets.

I understand. Sometimes I guess I get excited and get ahead of myself :rolleyes:. I also need to start practicing proper indentation much more. I'll go through my project and clean it up after this post.

  Quote
We will play on a variable-size board. Your program should define the following integer constants:

BOARD_SIZE

determines both the width and height of the game board (which is always square)

WIN_LENGTH

determines the number of Xs or Os in a row (either horizontally, vertically, or diagonally) that a player needs in order to win

so that the game can be played on different size boards simply by changing these values.

I've completed my disp_matrix function and it works flawlessly, now onto the hardest part, checking for a winner with a variable sized board AND variable sized WIN_LENGTH. Will a double loop work for the check() function? I was thinking I would have to totally butcher it and start anew.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Hundreds of printer models with weak password algorithms exposed, no firmware patch possible by Usama Jawad Many people don't think or care about it, but printer security is a pretty important avenue when it comes to evaluating your cybersecurity posture. Last month, it was found that the companion software for Procolored printers was distributing malware. Now, it has been revealed that hundreds of printer models all over the globe are susceptible to attacks targeting their admin credentials. Bleeping Computer has reported that CVE-2024-51978 is a one of the eight printer vulnerabilities recently discovered by security researchers. Combined, these allow authenticated and unauthenticated attackers to discover the default admin password, perform remote code execution (RCE), crash the printer, and leak other sensitive information. Severity ratings go from a score of 5.3 (medium) to 9.8 (critical), indicating that these are pretty severe vulnerabilities. The most dangerous vulnerability in there exposes the default admin password, and primarily affects Brother printers. This is because Brother utilizes a rather weak password generation algorithm that is highly dependent upon the device's serial number and a static salt table. Analysis of the code revealed that the first 16 characters of the serial number are appended with eight bytes from a static salt table, with the results being hashed with SHA256 and Base64-encoded. Finally, the first eight characters are then taken and some of them are replaced with special characters to form the password. The static nature of the password generation algorithm means that an attacker can chain various existing vulnerabilities to get access to your serial number and eventually your default admin password. It is important to note that not all printer models are affected by all of these flaws, but the default admin password exposure does affect 695 models. The breakdown for the number of printer model affected by the eight vulnerabilities is as follows: Brother: 689 Fujifilm: 46 Konica Minolta: 6 Ricoh: 5 Toshiba: 2 Brother has informed the security researchers that it cannot fully remediate the password generation vulnerability through a firmware patch. It can only fix the issue in its next printer models by patching the problem during the manufacturing process. This makes it crucial for customers of affected models to change their default admin password as soon as possible, which is good practice anyway.
    • Win11 being 2.3x faster than Win10, so that means without changing any hardware, Doom Eternal will run at over 2x the framerate? Or that any computational stuff will be done 2x faster just because of OS? Press X for doubt. I wonder where they pulled these metrics out of coz they make no sense. Not to mention my laptop with Ryzen 2500U that used to run Windows 11 simply CAN'T anymore because of BS arbitrary requirements Microsoft has imposed in Win11 that weren't there intiially. So, that laptop is now running Ubuntu or Fedora and runs at 1000000000000000000000x faster speeds because Windows 11 just doesn't work at all so it gets DNF.
    • “Ask Photos” is coming to more Google Photos users in the US by Paul Hill Google has announced several improvements to a Gemini-powered Google Photos feature called Ask Photos. The feature launched last year in early access and it was great for longer search requests, however, when users typed “Dog” or “Beach” looking for those types of pictures, Ask Photos underperformed. Now, Google has addressed this and is bringing the feature to more eligible users in the United States. The search giant said that users enjoyed asking queries such as “suggest photos that’d make great phone backgrounds” or “what did I eat on my trip to Barcelona?” and getting Gemini-powered responses to these complex questions. Unfortunately, simple searches like “beach” or “dogs” were generating less than optimal results and people complained. To remedy the situation, Google has brought the best of Google Photos’ classic search feature to Ask Photos to improve latency. Easy, short requests will be dealt with by the old search mechanism and when you ask complex queries, it will switch over to the Gemini-powered search results. Now that Google has addressed this main issue of simple searches by integrated functionality from the previous search model, the company feels more confident to open up beyond early access and deliver it to more users in the United States. To be eligible, you must be 18+, be in the US, have your Google Account language set to English (United States), and have Face Groups turned on. This feature is only available on Android and iOS. To start using it, open Google Photos and tap on Ask at the bottom, then press Try now and agree to the terms. If you do not see the Ask button, it means you’re not yet eligible. The feature also can’t be used on computers yet. Hopefully, Google will quickly expand this feature outside the US so that international users can try it out too.
    • When are MS going to learn. Traditional home users who email, watch cat videos and perform basic tasks don't care if W11 is slightly faster...assuming it's true. Few home users care about faster speed and more secure claims. In any event, it's irrelevant. MS stopped caring about home users years ago as evident by their hostile, anti choice home user policies.
    • They have. https://www.xda-developers.com...-25h2-update-kind-of-small/
  • Recent Achievements

    • Week One Done
      suprememobiles earned a badge
      Week One Done
    • Week One Done
      Marites earned a badge
      Week One Done
    • One Year In
      runge100 earned a badge
      One Year In
    • One Month Later
      runge100 earned a badge
      One Month Later
    • One Month Later
      jfam earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      567
    2. 2
      +FloatingFatMan
      177
    3. 3
      ATLien_0
      169
    4. 4
      Michael Scrip
      127
    5. 5
      Xenon
      119
  • Tell a friend

    Love Neowin? Tell a friend!