I want to find the neighboring element that surrounds p. the program below doesn't print of the neighbors
I know we can use brute-force approach, like this:
array[i-1][i]
array[i-1][i-1]
array[i][i-1]
array[i+1][i]
and so on...
But, I worry that it would get tedious to check every possible places of that element p. I am trying to figure out an elegant way to do this.
#include <stdio.h>
#include <stdlib.h>
void draw_board();
int row_number, column_number;
char mark_board(char mark, int row_num, int column_num);
char find_neighborhood(char board[6][6], int i, int j);
char board[6][6] = {
{ '0','0','0','0','0','0' },
{ '0','1','2','3','0','0' },
{ '0','4','P','5','0','0' },
{ '0','6','7','8','0','0' },
{ '0','0','0','0','0','0' },
{ '0','0','0','0','0','0' }
};
int main() {
draw_board();
find_neighborhood(board[6][6], 3, 3); // trying to find neighbor of char p
return 0;
}
void draw_board() {
printf(" 1 2 3 4 5 6\n");
printf(" -----------\n");
for (int i = 0; i < 6; i++) { // rows
printf("%i| ", i + 1);// row number to be printed
for (int j = 0; j < 6; j++) { // columns
printf("%c ", board[i][j]);
}
printf("\n");
}
}
char find_neighborhood(char board[6][6], int row_num, int col_num) {
int rows = sizeof(board); // row limit
int columns = sizeof(board[0]) - 1; // column limit
for (int j = row_num - 1; j <= row_num + 1; j++) {
for (int i = col_num - 1; i <= col_num + 1; i++) {
if (i >= 0 && j >= 0 && i < columns && j < rows && !(j == row_num && i == col_num)) {
printf("The neighbor of p is: %c\n", board[j][i]);
}
}
}
}
In addition to the good points made by #chqlie, you have other areas that pose significant "anti-patters" or just plain "code-smells". The most vexing is your mixing of 1-based rows and columns with 0-based array indexing. In C, all indexing is 0-based. When you write functions manipulating arrays, all indexing should be 0-based. Not only does this make your code easier to follow and maintain, it removes the risk of an off-by-one error associated with mixing 1-based and 0-based indexing.
If you must take 1-based coordinates from the user, then map 1-based indexing to 0-based indexing before you call your array manipulation function. If you don't do it at the point of input, then make it clear to anyone maintaining your code that an indexing changes is occurring. A simple commented function will do, e.g.
/* convert 1-based rows/cols to 0-based indexes */
int toindex (int rc)
{
return rc ? rc - 1 : rc;
}
and call:
/* DANGER mixing 1-based & 0-based indexes !!! */
find_neighborhood (board, toindex (3), toindex (3));
Don't use MagicNumbers in your code. (e.g. 6). This limits your code to a single arrays size requiring picking though all loop and array declarations and recompiling your code just to handle a change of array size. Instead:
#define ROWS 6 /* if you need a constant, #define one (or more) */
#define COLS ROWS
void draw_board (const char board[ROWS][COLS]);
void find_neighborhood (const char board[ROWS][COLS], int row, int col);
This impacts how you write you reading in draw_board() as well, e.g.
void draw_board(const char board[ROWS][COLS])
{
fputs (" ", stdout); /* don't use MagicNumbers */
for (int i = 0; i < ROWS; i++) /* create your headings */
printf ("%2d", i + 1); /* from defined constants */
fputs ("\n ", stdout);
for (int i = 0; i < 2 * COLS - 1; i++)
putchar ('-');
putchar ('\n');
for (int i = 0; i < ROWS; i++) {
printf (" %d|", i);
for (int j = 0; j < COLS; j++) {
printf (j ? " %c" : "%c", board[i][j]);
}
putchar ('\n');
}
}
You have another subtle issue with your declaration of board as char board[6][6] and then your use of the const qualifier in your function parameter lists. Pointers to arrays with different qualifiers are incompatible in ISO C. C11 Standard - 6.7.6.1 Pointer declarators(p2). This is the result of array/pointer conversion on a 2D array resulting in a pointer-to-array of actual type char (*)[6]. Try it, enable full warnings with -Wall -Wextra -pedantic (or /W3 on VS)
As for a "more-elegant" ways to write find_neighborhood() your though of nested loops and bounds checks at the edges is as good as any other approach. You started out in that direction, and other than writing a set of if...else if...else if...else conditionals, it probably a good choice. Eliminating your 1-based/0-based problem it could be written as:
/* all array manipulation functions should use 0-based indexes */
void find_neighborhood (const char board[ROWS][COLS], int row, int col)
{
printf ("\nThe neighbors of '%c' are:\n\n", board[row][col]);
for (int i = row ? row - 1 : row; i <= (row < ROWS - 1 ? row + 1 : row); i++) {
for (int j = col ? col - 1 : col; j <= (col < COLS - 1 ? col + 1 : col); j++) {
if (i == row && j == col)
fputs (" ", stdout);
else
printf (" %c", board[i][j]);
}
putchar ('\n');
}
}
Putting it altogether, you would have:
#include <stdio.h>
#define ROWS 6 /* if you need a constant, #define one (or more) */
#define COLS ROWS
void draw_board (const char board[ROWS][COLS]);
void find_neighborhood (const char board[ROWS][COLS], int row, int col);
/* convert 1-based rows/cols to 0-based indexes */
int toindex (int rc)
{
return rc ? rc - 1 : rc;
}
int main() {
const char board[ROWS][COLS] = { /* avoid global variables */
{ '0','0','0','0','0','0' },
{ '0','1','2','3','0','0' }, /* pointers to arrays with */
{ '0','4','P','5','0','0' }, /* different qualifiers are */
{ '0','6','7','8','0','0' }, /* incompatible in ISO C */
{ '0','0','0','0','0','0' },
{ '0','0','0','0','0','0' },
};
draw_board(board);
/* DANGER mixing 1-based & 0-based indexes !!! */
find_neighborhood (board, toindex (3), toindex (3));
}
void draw_board(const char board[ROWS][COLS])
{
fputs (" ", stdout); /* don't use MagicNumbers */
for (int i = 0; i < ROWS; i++) /* create your headings */
printf ("%2d", i + 1); /* from defined constants */
fputs ("\n ", stdout);
for (int i = 0; i < 2 * COLS - 1; i++)
putchar ('-');
putchar ('\n');
for (int i = 0; i < ROWS; i++) {
printf (" %d|", i);
for (int j = 0; j < COLS; j++) {
printf (j ? " %c" : "%c", board[i][j]);
}
putchar ('\n');
}
}
/* all array manipulation functions should use 0-based indexes */
void find_neighborhood (const char board[ROWS][COLS], int row, int col)
{
printf ("\nThe neighbors of '%c' are:\n\n", board[row][col]);
for (int i = row ? row - 1 : row; i <= (row < ROWS - 1 ? row + 1 : row); i++) {
for (int j = col ? col - 1 : col; j <= (col < COLS - 1 ? col + 1 : col); j++) {
if (i == row && j == col)
fputs (" ", stdout);
else
printf (" %c", board[i][j]);
}
putchar ('\n');
}
}
Example Use/Output
$ ./bin/board_neighbors
1 2 3 4 5 6
-----------
0|0 0 0 0 0 0
1|0 1 2 3 0 0
2|0 4 P 5 0 0
3|0 6 7 8 0 0
4|0 0 0 0 0 0
5|0 0 0 0 0 0
The neighbors of 'P' are:
1 2 3
4 5
6 7 8
When you look for a "more elegant" way of doing anything, in the end you will get a fair amount of opinion built in. Let me know if you have further questions.
There are multiple issues in the code:
find_neighborhood(board[6][6], 3, 3); is incorrect: you should write this instead:
find_neighborhood(board, 3, 3);
in find_neighborhood, the definition int rows = sizeof(board); initializes rows to the size of a pointer, not the number of rows in the matrix. You should use explicit constants or pass the dimensions as extra arguments.
find_neighborhood() performs many tests... But that's the core of the question.
row_number, column_number and board should not be global variables. It is confusing that some functions use the global variables and others take them as arguments (with the same name).
Here is a modified version:
void find_neighborhood(char board[6][6], int row, int col) {
for (int j = max(0, row - 1); j <= min(row + 1, 6); j++) {
for (int i = max(0, col - 1); i <= min(col + 1, 6); i++) {
if (j != row || i != col) {
printf("The neighbor of p is: %c\n", board[j][i]);
}
}
}
}
There is an elegant way to address your objective: you can define board as an 8x8 array where the first and last rows and columns are always empty. The active part of the board has index values in the range 1..6.
Here is a modified version with this approach:
#include <stdio.h>
#include <stdlib.h>
void draw_board(const char board[8][8]);
char mark_board(char board[8][8], char mark, int row, int col);
void find_neighborhood(char board[8][8], int row, int col);
int main() {
int row_number, column_number;
char board[8][8] = {
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, '0','0','0','0','0','0', 0 },
{ 0, '0','1','2','3','0','0', 0 },
{ 0, '0','4','P','5','0','0', 0 },
{ 0, '0','6','7','8','0','0', 0 },
{ 0, '0','0','0','0','0','0', 0 },
{ 0, '0','0','0','0','0','0', 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
};
draw_board(board);
find_neighborhood(board, 4, 4); // trying to find neighbors of char p
return 0;
}
void draw_board(const char board[8][8]) {
printf(" 1 2 3 4 5 6\n");
printf(" -----------\n");
for (int i = 1; i <= 6; i++) { // rows
printf("%i| ", i); // row number to be printed
for (int j = 1; j <= 6; j++) { // columns
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void find_neighborhood(char board[8][8], int row, int col) {
char save = board[row][col];
board[row][col] = 0;
for (int j = row - 1; j <= row + 1; j++) {
for (int i = col - 1; i <= col + 1; i++) {
if (board[j][i] != 0) {
printf("The neighbor of p is: %c\n", board[j][i]);
}
}
}
board[row][col] = save;
}
I'm having a problem on making a move on my 9 x 9 tic tac toe program.
When I enter a coordinate such as (5,5), The x is displayed correctly on the grid.
MY PROBLEM IS THAT when I enter a coordinate which has the number 7 in it such as (4,7), TWO X's ARE DISPLAYED ON THE GRID.
I previously did the program declaring my array as a global variable. All was working fine. The issue started when I switched to a dynamically allocated array and passed the array using a double-pointer.
So I'm guessing that my problem is because of my array.
Can someone tell me where does this issue occur and how to fix it please.
I have declared the array in my main
//previously the array was declared here
//char grid[ROW][COLUMN];
int main()
{
//dynamically create an array of pointers os size ROW
char **grid = (char **)malloc(ROW * sizeof(char *));
// dynamically allocate memory of size ROW*COLUMN and let *grid point to it
*grid = (char *)malloc(sizeof(char) * ROW * COLUMN);
make move method
int make_move(char **grid, int x, int y,int row, int col, char letter)
{
if (x < 0 || x >= row || y < 0 || y >= col || grid[x][y] != ' ' )
{
// checks to see if the input is valid
return 1;
}
if( grid[x][y] == ' ')
grid[x][y] = letter;
// sets the coordinates in the grid to the letter
return 0;
}
update grid method
// Updates the grid accordingly every time a move is made
void update_grid(char **grid,int x, int y, int row, int col)
{
// int counter = 1;
//checks the input
while (x < 0 || x >= row || y < 0 || y >= col || grid[x][y] != ' ')
{
fputs("Error, Move not valid! Please reenter: ", stderr);
scanf("%d,%d", &x, &y);
}
++counter;
{
//Acts as an increment for the turns of the players
if(counter % 2 == 0)
{
//checks to see if it is player X's turn
grid[x][y] = 'X';
}
if(counter % 2 != 0)
{
//checks to see if it is player O's turn
grid[x][y] = 'O';
}
//prints grid
printf(" ");
for (int c = 0; c < col; c++)
{
printf(" ");
printf(" %d", c);
}
printf("\n");
for (int r = 0; r < row; ++r)
{
printf("%d", r);
printf("|");
for (int dot = 0; dot < (col*row); ++dot)
{
printf("|");
printf("%c", grid[r][dot]);
printf(" ");
if (dot == col - 1)
{
// stops j from over printing
printf("|| \n");
break;
}
}
}
}
}
As B. Go said your malloc is wrong, here's how it should look.
//dynamically create an array of pointers os size ROW
char **grid = malloc(ROW * sizeof(char *));
for(size_t i = 0; i < ROW; i++){
grid[i] = malloc(COLUMN);
}
you allocated ROW pointers but you only filled the first one, you need to give them each COLUMN bytes of data.
Im trying to make a function that sets the values of a 2D array, and then another function that prints those values.
For some reason, with my current implementation, if I create a 3x3 matrix and I set every value to the number 5, it prints the values, but it prints them counting up from 5, so it prints 567, 678, 789, when instead I want it to print the exact value that I set.
Here are the function definitions - what am I doing wrong?:
Struct Definition:
struct matrix{
char matrixName[50];
int rows;
int columns;
float* data;
};
typedef struct matrix matrix_t;
Matrix Creation:
int create_matrix(matrix_t* matrixP, int matrixLocation){
char tempName[50];
int rows, cols;
printf("Enter a name for your matrix>\n");
scanf("%s", tempName);
printf("Enter the number of rows>\n");
scanf("%d", &rows);
printf("Enter the number of cols>\n");
scanf("%d", &cols);
float * our_matrix = (float *) malloc(rows * cols * sizeof(float));
strcpy(matrixP[matrixLocation].matrixName, tempName);
matrixP[matrixLocation].rows = rows;
matrixP[matrixLocation].columns = cols;
matrixP[matrixLocation].data = our_matrix;
return 0;
}
Set Values:
int setValues(matrix_t* our_matrix, int matrix_index) {
int counter = 0;
int row = 0, col = 0;
for (col = 1; col <= our_matrix[matrix_index].columns; col++) {
for (row = 1; row <= our_matrix[matrix_index].rows; row++) {
counter++;
printf("Enter the value for column number %d of row number %d>\n", col, row);
scanf("%f", our_matrix[matrix_index].data+(col-1)+(row-1));
}
/* separate rows by newlines */
}
return 0;
}
Print:
int printMatrix(matrix_t* our_matrix, int index) {
int row = 0, col = 0;
for (col = 1; col <= our_matrix[index].columns; col++) {
for (row = 1; row <= our_matrix[index].rows; row++) {
printf(" %2.f ", *our_matrix[index].data+(col-1)+(row-1));
}
printf("\n");
}
return 0;
}
If I call the printMatrix() function without first using setValues, it seems to print the relative position of the cell that it's printing like so:
But when I call setValues() and set all values to the number 5, its prints counting up from the number 5 like this:
Your position calculation is incorrect. There's one problem and one 'aconventional notation' issue.
The problem is the calculation of the array subscripts:
scanf("%f", our_matrix[matrix_index].data+(col-1)+(row-1));
printf(" %2.f ", *our_matrix[index].data+(col-1)+(row-1));
You need to multiply the (row - 1) value by our_matrix[matrix_index].cols. You will probably do better with some shorter names for the values:
int max_col = our_matrix[matrix_index].columns;
int max_row = our_matrix[matrix_index].rows;
float *data = our_matrix[matrix_index].data;
for (col = 1; col <= max_col; col++)
{
for (row = 1; row <= max_row; row++)
{
printf("Enter the value for column number %d of row number %d>\n", col, row);
if (scanf("%f", data + (col-1) + (row-1) * max_col) != 1)
{
…report error and do not continue…
}
}
}
for (col = 1; col <= max_col; col++)
{
for (row = 1; row <= max_row; row++)
printf(" %.2f", data[(col-1) + (row-1) * max_col]);
putchar('\n');
}
That deals with the substantive bug. Note the error checking on scanf(). That is important in 'real world' programs (even if you get away without it in classes or in online contests). You could sensibly use the notation &data[(col-1) + (row-1) * max_cols] in place of data + (col-1) + (row-1) * max_cols in the call to scanf() too — that would improve the consistency of the code.
The 'aconventional notation' issue is that in C, array indexing starts at 0, not 1, and you could avoid the multitude of -1 terms by following the C conventions. This snippet also declares the loop variables when they're needed, minimizing their scope. This is a feature of C since C99 — it may not be available to you on some retrograde (but popular and widespread) platforms.
for (int col = 0; col < max_col; col++)
{
for (int row = 0; row < max_row; row++)
printf(" %.2f", data[col + row * max_col]);
putchar('\n');
}
I needed some help with my homework. I've spent about 2 hours on this but I can't get my head around it (c programming). I have to print an x like so:
* *
* *
* *
* *
*
* *
* *
* *
* *
The steps of the program should work like this.
1. User inputs a single number which is the size (this single number is basically the width and height). Also we can assume the user always puts an odd number (so we don't need conditions for that).
2. It draws the X in respect to that size.
However, I can only use while loops, and if statements, scanf and printf. Nothing else.
This is what I can get so far (just a diagonal)
row = 0;
while (row < size) {
column = 0;
while (column < size) {
if (row == column) {
printf("*");
} else {
printf(" ");
}
column++;;
}
printf("\n");
row++;
}
this should work
#include <stdio.h>
int main()
{
int size, row, column;
scanf("%d", &size);
row = 0;
while (row < size)
{
column = 0;
while (column < size)
{
if (column == row || column == size - row - 1)
{
printf("x");
}
else
{
printf(" ");
}
column++;
}
printf("\n");
row++;
}
return 0;
}
#include <stdio.h>
int main(void) {
int size = 11; //this should be the size given by user.
char line[size + 1];
int i;
for(i = 0; i < size; i++) line[i] = ' ';
line[size] = '\0';
int se = 0;
int sw = size - 1;
while(se < size && sw >= 0){
line[se] = line[sw] = 'x';
printf("%s\n", line);
line[se++] = line[sw--] = ' ';
}
return 0;
}
Tested on Ideone and worked.
You are checking only one diagonal.To get the required pattern ,change the if condition as follows...
if ((row == column)||(row==(size-column-1)))
I am writing this code to print the following matrix in this spiral order(spiral by column).But my code is printing totally different thing.
a a+7 a+8 a+15
a+1 a+6 a+9 a+14
a+2 a+5 a+10 a+13
a+3 a+4 a+11 a+12
Here is what i did:
int main() {
int a;
int Sum = 0;
int i = 0, j = 0,n;
printf("Insert the value of n: ");
scanf("%d",&n);
printf("Insert the value of a number: ");
scanf("%d",&a);
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%d ",a);
a = a + 7;
printf("\t");
}
printf("%d",a);
a = a + 1 ;
printf("\n");
}
return 0;
}
The way I approached this is to build the matrix of values you actually want, but doing so in column order, where we can relatively easily control the logic of value progression by row. Then, with that matrix in hand, print out the values in row order, as you want the output:
int main()
{
int a = 7;
int n = 4;
int array[4][4];
for (int c=0; c < n; ++c)
{
for (int r=0; r < n; ++r)
{
// values ascending for even columns
if (c % 2 == 0)
{
array[r][c] = a + c*n + r;
}
// values descending for odd columns
else
{
array[r][c] = a + c*n + n-r-1;
}
}
}
for (int i=0; i < n; ++i)
{
for (int j=0; j < n; ++j)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
}
Output:
Demo here:
Rextester
Instead of using this complex mechanism to keep track of all elements you can just calculate the value to add at any time by simple arithmetic.
See this
int row;
int column;
printf("\n");
for (row = 0; row < n; row++) {
for (column = 0; column < n; column++) {
int base;
int flag;
if (column % 2 != 0) {
base = (column+1)/2 * 2*n - 1;
flag = -1;
}else {
base = column/2 * 2*n;
flag = 1;
}
printf( "%d ", a + base + flag * row);
}
printf("\n");
}
I hope you are able to follow this logic. If not feel free to ask.
Demo here:
Ideone
There seem to be two issues with your code as it is. As mentioned in the above comment, you are using the variable a in the loop calculation, so it is constantly being updated. This means your loop becomes invalid after a few iterations. If you define a dummy variable, this would avoid the problem. Secondly the implementation of the spiralling is close to being right, but it's not quite there.
Consider in the case n = 4. When you print along each row, the difference between a new element and the last alternates between values of (2n - 1) = 7 and 1. To take this into account, you could for example check every time you want to print whether the column index (j) is odd or even, and use this to determine which difference to add. Once you have the row machinery fixed, it shouldn't be difficult to extend it to the columns.
Simple solution using a matrix to calculate values before print them
#include <stdio.h>
int main(void)
{
int a;
int i = 0, j = 0, n;
printf("Insert the value of n: ");
scanf("%d", &n);
printf("Insert the value of a number: ");
scanf("%d", &a);
int matrix[n][n];
for (i=0; i< n*n; i++)
{
// even columns ascending
if (((i/n) % 2) == 0)
{
matrix[i%n][i/n] = a++;
}
// odd column descending
else
{
matrix[n-(i%n)-1][i/n] = a++;
}
}
for (i=0; i< n; i++)
{
for (j=0; j< n; j++)
{
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
return 0;
}
Output
Insert the value of n: 4
Insert start value: 1
1 8 9 16
2 7 10 15
3 6 11 14
4 5 12 13