• 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

    • PasteBar 0.7.0 by Razvan Serea PasteBar is a powerful yet free clipboard manager that revolutionizes how you copy, organize, and reuse information. Packed with smart features, it enhances productivity and simplifies your workflow by minimizing repetitive copy-paste tasks—so you can work faster and smarter. PasteBar offers powerful clipboard management with unlimited history, searchable copy records, and note support, making it easy to retrieve past clips. You can save and organize clips into custom collections, tabs, or boards for quick access through intuitive paste menus. Privacy is a priority, with local storage, passcode protection, and PIN-locked collections ensuring your data stays secure. The app also supports custom storage locations, giving you full control over where your clipboard history is saved. Beyond basic clipboard functions, PasteBar includes smart features like support for text, images, files, and code snippets—complete with syntax highlighting and Markdown formatting. A global search function, instant pasting, and dark theme enhance usability, while customization options let you tailor hotkeys, tray behavior, and text filters. Cross-platform compatibility (macOS & Windows) ensures seamless workflow integration, with added tools for web scraping, API data extraction, and multi-language support. Backup and restore capabilities provide extra peace of mind, making PasteBar a versatile productivity tool. PasteBar 0.7.0 changelog: Added backup and restore database and images Added custom data location to store application data in a folder of your choice instead of the default location Added keyboard shortcuts to improve navigation efficiency within the application Added long press on clip to activate clips organize Added "Trim Spaces" option for clips and "Auto Trim Spaces" option for History Capture Added Quick history window user options Added option to disable capturing and storing images from clipboard Implemented clipboard history filtering based on text length limits Added support for setting hotkeys with up to 3-key combinations Fixed update history items in quick paste window after delete operation in main window Added user setting for single-click keyboard focus in history Refactored terminology for history window split to open Updated to React 19 and React Compiler Auto-activate search in quick paste window when typing any letter or number Added single-click copy/paste option in user preferences Added persistent note icons for clips with descriptions Added detect and select language modal on first app run Fixed refresh native menu on history items delete Added history item preview max lines user setting Added protected collection with PIN access Added special copy/paste for history items context menu and settings Added global templates in user preferences for saved clips Press Delete key to delete single or multiple items with confirmation on second press Added customizable tray icon behavior on Windows as user settings Added user preference to copy only menu items to clipboard without auto-pasting Fixed enhance value preview logic to fix text overflow Updated French language translation from Jean-Michel Robert Added deleting menu folders with children by moving submenus up one level Fixed user preferences UI color bug for languages Added settings to preserve pinned and starred items when clearing clipboard history Added option "Show Always on Top" for main window Added support for notes matching in global search Added Turkish language translation by AlijonMurodov Updated Chinese translation by katelya77 Download: PasteBar | Portable | ~30.0 MB (Open Source) Download: PasteBar ARM64 | Portable ARM64 Links: PasteBar Website | Screenshot | MS Store Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Well, it seems version 4.9 doesn't work well at least when trying to make a WinToGo USB. It ends very fast with an error. Had to use 4.8 instead.
    • 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.
  • 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!