How to check the conditions for neighbours? - c

I am stubborn about trying to solve as much as I can myself. However I think that I've reached an impasse.
I have to write code for a simple version for game of life on a 20x20 grid. The conditions are:
A cell which has 0 or 1 living neighbours dies next generation.
A cell which has 2 or 3 living neighbours lives next generation.
A cell which has 4 or more living neighbours dies next generation.
A empty cell which has exactly 3 living neighbours becomes a live
cell next generation.
My particular problem is how to write the algoritm that performs the above said operations.
I have not tried much since I'm out of ideas. I did hope to get some ideas which might give me a extra push into finishing my function that updates the world/field.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Constants, representation of states */
#define ALIVE 'X'
#define DEAD '.'
/* Declaration of data structure */
typedef struct{
char current;
char next;
} cell;
/* Declaration of functions */
void initField(const int rows, const int cols, cell field[rows][cols]);
void loadGlider(const int rows, const int cols, cell field[rows][cols]);
void loadSemaphore(const int rows, const int cols, cell field[rows][cols]);
void loadRandom(const int rows, const int cols, cell field[rows][cols]);
void loadCustom(const int rows, const int cols, cell field[rows][cols]);
void printWorld(const int rows, const int cols, cell field[rows][cols]);
void evolve(const int rows,const int cols,cell field[rows][cols]);
/* Function: main
* Description: Start and run games, interact with the user.
* Input: About what initial structure and whether to step or exit.
* Output: Information to the user, and the game field in each step.
*/
int main(void) {
const int rows = 20;
const int cols = 20;
cell field[rows][cols];
initField(rows,cols, field);
printWorld(rows,cols,field);
return 0;
}
/* Function: initField
* Description: Initialize all the cells to dead, then asks the user about
* which structure to load, and finally load the structure.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void initField(const int rows, const int cols, cell field[rows][cols]) {
for (int r = 0 ; r < rows ; r++) {
for (int c = 0 ; c < cols ; c++) {
field[r][c].current = DEAD;
}
}
printf("Select field spec to load ([G]lider, [S]emaphore, [R]andom ");
printf("or [C]ustom): ");
int ch = getchar();
/* Ignore following newline */
if (ch != '\n') {
getchar();
}
switch (ch) {
case 'g':
case 'G':
loadGlider(rows, cols, field);
break;
case 's':
case 'S':
loadSemaphore(rows, cols, field);
break;
case 'r':
case 'R':
loadRandom(rows, cols, field);
break;
case 'c':
case 'C':
default:
loadCustom(rows, cols, field);
break;
}
}
/* Function: loadGlider
* Description: Inserts a glider into the field.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void loadGlider(const int rows, const int cols, cell field[rows][cols]) {
field[0][1].current = ALIVE;
field[1][2].current = ALIVE;
field[2][0].current = ALIVE;
field[2][1].current = ALIVE;
field[2][2].current = ALIVE;
}
/* Function: loadSemaphore
* Description: Inserts a semaphore into the field.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void loadSemaphore(const int rows, const int cols, cell field[rows][cols]) {
field[8][1].current = ALIVE;
field[8][2].current = ALIVE;
field[8][3].current = ALIVE;
}
/* Function: loadRandom
* Description: Inserts a random structure into the field.
* Input: The field array and its size.
* Output: The field array is updated. There is a 50 % chance that a cell
* is alive.
*/
void loadRandom(const int rows, const int cols, cell field[rows][cols]) {
}
/* Function: loadCustom
* Description: Lets the user specify a structure that then is inserted into
* the field.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void loadCustom(const int rows, const int cols, cell field[rows][cols]) {
printf("Give custom format string: ");
do {
int r, c;
scanf("%d,%d", &r, &c);
field[r][c].current = ALIVE;
} while (getchar() != '\n');
}
/* Function: printWorld
* Description: Prints the current field
* Input: The field array and its size.
* Output: The field array is updated.
*/
void printWorld(const int rows, const int cols, cell field[rows][cols]){
char c = '\n';
while(c == '\n'){
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%c ", field[i][j].current);
}
printf("\n");
}
c = getchar();
if(c != '\n'){
break;
}
}
void evolve(const int rows,const int cols,cell field[rows][cols]){
for(int i = 0;i<rows;i++){
for(int j =0;j<cols;j++){
if()
}
}
}
You can see above all current progress. All the functions except for
printWorld() and evolve() are pre-made and should remain as they are.
This is my current progress for evolve, it is not much.
void evolve(const int rows,const int cols,cell field[rows][cols]){
for(int i = 0;i<rows;i++){
for(int j =0;j<cols;j++){
if()
}
}
}
All I have done is to write two nested for-loops which makes sure to check every cell.
But I am not sure however how to proceed and implement the conditions above. Any ideas on how to check neighbours for each cell?
English is not my first language. So I apologise in advance for any grammatical error. And if you have trouble understanding what I want, ask, and I'll clarify.
I would also add a disclaimer that the function: printWorld is not finished since it still requires the function evolve.

All I have done is to write two nested for-loops which makes sure to check every cell.
Well that's a start.
But I am not sure however how to proceed and implement the conditions above. Any ideas on how to check neighbours for each cell?
The evolve() function receives the field, apparently describinbg the current state of the board and the next state. It would appear that the data for a cell with indices i, j would be in field[i][j]. So the main question is: which cells are the neighbors of that one? But that shouldn't be hard. They are the eight cells other than (i, j) each of whose indices differs by at most 1 from i or j, respectively. That is, (i - 1, j - 1), (i - 1, j), (i - 1, j + 1), (i, j - 1), etc.. Work out an example if you need to do, with actual cell indices, for one cell.
So it seems you would count the live population of all the neighbor cells, and use that in combination with whether the current cell is alive, to determine and record how that cell will evolve.
Do note that the edges and corners are special cases: they do not have neighbors on at least one side, and you must not try to examine the neighbors that do not exist. You should be able to accomplish that by checking whether the neighbor cell indices are in bounds before trying to access them.

Related

Unable to read a maze of chars and put it into a bidimensional array

I am making a maze solving game. There is a function in the middle of the game that saves the progress and prints everything into the file. But now i want to read the maze, the character, etc from the file and put it into a bidimensional array but i am not being able to do so.
The array is declared globally (because of its use in several functions) and it is maze[30][30]. N is also declared globally as a variable size but at this point it should be 10. filePath too and it gives the name of the file.
This is how they are declared globally.
int N = 10;
char* filePath = "./save.txt";
char maze[30][30];
This is the read function:
void ler()
{
int i, j;
ex=1; ey=0;
sx=N-2; sy=N-1;
int aux;
FILE *fp = fopen(filePath, "r");
if (fp == NULL)
{
printf("Unable to perform.");
return;
}
system("cls");
for(i=0 ; i<N ; i++)
{
for(j=0 ; j<N ; j++)
{
fscanf(fp, "%c", maze[j][i]);
}
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf("%c", maze[j][i]); //Double print just for visuals
printf("%c", maze[j][i]);
}
printf("\n");
}
fclose(fp);
}
This is the save function:
void save(char maze[30][30]){
int i,j;
FILE *fp = fopen(filePath, "w");
if(fp==NULL){
printf("Unable to perform.");
return;
}
for(i=0 ; i<N ; i++){
for(j=0 ; j<N ; j++){
fprintf(fp, "%c", maze[j][i]);
fprintf(fp, "%c", maze[j][i]);
}
fprintf(fp, "\n", maze[j][i]);
}
fclose(fp);}
At this point it should only be possible to print the maze but it is not doing even that.
What save.txt file looks like after saving
The weird II is the caharcter and the other is like a highscore thing.
Using multidimensional arrays in C is actually more pain than they're worth. A much better option is to use a structure with a dynamically allocated array describing the maze, and accessor functions to examine and change the maze cells. Instead of putting markers in the maze data, you can put start/end/current location coordinates in the structure.
(I do realize that this does not answer the OP's stated question, but this is an answer to the underlying problem OP is trying to solve.)
Consider the following example. It limits the maze size to 255×255, but because each coordinate and maze cell is always just one byte, the save files are portable between architectures, as there is no byte order (endianness) to worry about. (You, as the programmer, do need to choose to use only codes 0..255 in the maze, though, to keep the data portable; the functions below won't enforce that.)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
unsigned char row;
unsigned char col;
} mazepoint;
typedef struct {
unsigned char rows;
unsigned char cols;
unsigned char *cell;
mazepoint player;
} maze;
#define OUTSIDE 0
static inline unsigned char maze_get(maze *const m,
const int row,
const int col)
{
if (m &&
row >= 0 && row < (int)(m->rows) &&
col >= 0 && col < (int)(m->cols))
return m->cell[ (size_t)col + (size_t)(m->cols) * (size_t)row ];
else
return OUTSIDE;
}
static inline unsigned char maze_set(maze *const m,
const int row,
const int col,
const unsigned char val)
{
if (m &&
row >= 0 && row < (int)(m->rows) &&
col >= 0 && col < (int)(m->cols))
return m->cell[ (size_t)col + (size_t)(m->cols) * (size_t)row ] = val;
else
return OUTSIDE;
}
static inline void maze_free(maze *const m)
{
if (m) {
free(m->cell);
m->rows = 0;
m->cols = 0;
m->cell = NULL;
}
}
int maze_create(maze *const m,
const int rows,
const int cols)
{
size_t cells = (size_t)rows * (size_t)cols;
unsigned char *cell;
if (!m)
return -1; /* NULL reference to a maze variable! */
if (rows < 1 || rows > 255 ||
cols < 1 || cols > 255)
return -1; /* Invalid number of rows or columns! */
cell = malloc(cells); /* sizeof (unsigned char) == 1. */
if (!cell)
return -1;
/* Initialize all maze cells to OUTSIDE. */
memset(cell, OUTSIDE, cells);
m->rows = rows;
m->cols = cols;
m->cell = cell;
/* Let's initialize player location to upper left corner. */
m->player.row = 0;
m->player.col = 0;
return 0; /* Success. */
}
int maze_save(maze *const m, const char *filename)
{
size_t cells;
FILE *out;
if (!m || m->rows < 1 || m->cols < 1)
return -1; /* No maze to save! */
if (!filename || !filename[0])
return -1; /* NULL or empty filename! */
cells = (size_t)(m->rows) * (size_t)(m->cols);
out = fopen(filename, "wb");
if (!out)
return -1; /* Cannot open file for writing! */
do {
/* First byte is the number of rows. */
if (fputc(m->rows, out) == EOF)
break;
/* Second byte is the number of columns. */
if (fputc(m->cols, out) == EOF)
break;
/* rows*cols bytes of maze data follows. */
if (fwrite(m->cell, 1, cells, out) != cells)
break;
/* Player location follows. */
if (fputc(m->player.row, out) == EOF)
break;
if (fputc(m->player.col, out) == EOF)
break;
/* You can save additional data at this point. */
/* That completes the save file. Ensure it is correctly saved. */
if (fflush(out))
break;
if (fclose(out))
break;
/* Maze successfully saved. */
return 0;
} while (0);
/* Save failed. */
fclose(out);
remove(filename);
return -1;
}
int maze_load(maze *const m, const char *filename)
{
size_t cells;
unsigned char *cell;
int rows, cols, r, c;
FILE *in;
if (!m)
return -1; /* No reference to a maze variable to load into! */
/* Just in case, we clear the maze first. Might help finding bugs! */
m->rows = 0;
m->cols = 0;
m->cell = NULL;
if (!filename || !filename[0])
return -1; /* NULL or empty filename! */
in = fopen(filename, "rb");
if (!in)
return -1; /* Cannot open file for reading. */
rows = fgetc(in);
cols = fgetc(in);
if (rows == EOF || rows < 1 || rows > 255 ||
cols == EOF || cols < 1 || cols > 255) {
fclose(in);
return -1; /* Not a saved maze! */
}
cells = (size_t)(rows) * (size_t)(cols);
cell = malloc(cells);
if (!cell) {
fclose(in);
return -1; /* Not enough memory available! */
}
do {
/* Read maze cell data. */
if (fread(cell, 1, cells, in) != cells)
break;
/* Player location. */
r = fgetc(in);
c = fgetc(in);
if (r == EOF || r < 0 || r > 255 ||
c == EOF || c < 0 || c > 255)
break;
m->player.row = r;
m->player.col = c;
/* Load other saved data here. */
/* All data read successfully. */
fclose(in);
m->rows = rows;
m->cols = cols;
m->cell = cell;
return 0;
} while (0);
/* Read error. */
fclose(in);
free(cell);
return -1;
}
In your own program, you'd create a maze thus:
maze m;
/* Create a 20-row, 30-column maze. */
if (maze_create(&m, 20, 30)) {
/* Failed to create maze! Show an error message. */
exit(EXIT_FAILURE);
}
To save the maze to say maze.dat, you use
m.player.row = /* row where the player is */
m.player.col = /* column where the player is */
if (maze_save(&m, "maze.dat")) {
/* Failed! Show an error message. */
exit(EXIT_FAILURE);
}
If you look at the example code, you can add additional data, especially points like the player place, to be saved and loaded along with the maze cells themselves.
To destroy a maze when it is no longer needed, use
maze_free(&m);
To load a saved maze, say from maze.dat, use
if (maze_load(&m, "maze.dat")) {
/* Failed! Show an error message. */
exit(EXIT_FAILURE);
}
/* Restore player place from m.player.row and m.player.col */
The accessor function maze_get() is not limited to the valid coordinates (0 through rows-1 or cols-1, inclusive). If you examine outside the maze itself, it will just return the value of the OUTSIDE macro. For example,
if (maze_get(&m, row, col) == 5) {
/* That cell has value 5 */
} else {
/* Either the cell has a different value,
or row,col is outside the maze. */
}
Similarly, you can try to set any cell value safely. It will only "stick" if it is within the valid maze coordinate range, however; elsewhere it will return OUTSIDE:
if (maze_set(&m, row, col, 5) == 5) {
/* Changed cell value to 5 */
} else {
/* row,col is outside the maze. */
}
The reason I wrote the accessor macros that way, is that it makes rendering only a part of the maze very simple. If the view is viewrows by viewcols in size, centered at row and col, then you can render the view using a simple loop:
const int top = row - viewrows / 2;
const int left = col - viewcols / 2;
int vr, vc;
for (vr = 0; vr < viewrows; vr++) {
for (vc = 0; vc < viewcols; vc++) {
const unsigned char v = maze_get(&m, top+vr, left+vc);
/* Draw v at row vr, col vc */
}
}
and the cells are even drawn in the same order as you read this text; from top to bottom, left to right.
Note that instead of using the maze cell values for character codes, you should use a lookup table instead. For example,
int cell_char[256];
Instead of printing cell values directly, you'd print the corresponding cell_char, for example
fputc(cell_char[maze_get(&m, row, col)], stdout);
That way you can group e.g. different wall characters into a consecutive range, or even use the individual bits in the 8-bit cell value as identifiers. The maze cells then describe the logical contents in that maze cell, rather than its visual representation, with the logical-to-visual mapping in a separate array.
If you used Gtk+, you could have an array of GtkImage pointers,
GtkImage *cell_image[256] = {0}; /* All NULL by default */
or using SDL, you could have the maze cells as textures you can render,
SDL_Texture *cell_texture[256] = {0}; /* All NULL by default */
and in both cases, read them from either one large image (say, divided into 16×16 exact same size rectangles), or from individual image files.
For example, you could decide that the four least significant bits in the cell value specify whether movement from that cell up (previous row), down (next row), left (previous column), or right (next column) is possible:
#define CAN_GO_UP(value) ((value) & (1 << 0)) /* == 1 */
#define CAN_GO_DOWN(value) ((value) & (1 << 1)) /* == 2 */
#define CAN_GO_LEFT(value) ((value) & (1 << 2)) /* == 4 */
#define CAN_GO_RIGHT(value) ((value) & (1 << 3)) /* == 8 */
Note that this allows you to do "trap walls": passages that only work one way. Maze cell values that are multiples of 16 (0, 16, 32, 48, 64, 80, 96, ..., 208, 224, and 240) represent completely blocked cells: no way out. +1 allows passage up; +2 allows passage down; +3 allows passage up and down; +4 allows passage left; +5 allows passage left and up; +6 allows passage left and down; +7 allows passage up, left, and down; +8 allows passage right; +9 allows passage up and right; +10 allows passage down and right; +11 allows passage up, down, and right; +12 allows passage left and right; +13 allows passage up, left, and right; +14 allows passage down, left, and right; and +15 allows passage up, down, left, and right.
I would personally also recommend using the wide version of the ncurses library (ncursesw). (I do not use Windows, so I am not exactly sure how you install and use it in windows, but the ncurses home page does have downloads when using mingw.)
Then, you would have a much wider variety of glyphs you could use. (When using UTF-8 locales, potentially the entire Unicode glyph set -- the Box Drawing block especially would be useful for maze drawing, and most of those glyphs are also available in the old CP437 codepage, which means they should work both in Windows and non-Windows terminals nicely.)
In that case, you'd probably use
cchar_t cell_char[256];
As I mentioned above, you could even do a graphical version (perhaps later on, extending your terminal version?) in C using SDL or GTK+. (Note that the above separation between logical maze cell content value and the visual describing the cell also means you can, at runtime, choose between "themes", by having more than one set of cell images. That allows you to start with crude informational versions, for debugging, and then add visual goodness.)
The approach shown in this answers allows you to start with a simple terminal-based game, and if you decide you want to, add support for graphical UI, with image-based maze cells, without having to rewrite any of your core maze code.

Creating a tic-tac-toe program using a 2-D array and functions in C

In my code I have a total of ten functions and I was only able to fully code two of them and i have my main function all set up. The other functions I am completely lost on. It would be a huge help if you can add example coding and explanations so I could get a better understanding.
Here is my code:
#include <stdio.h>
#define SIZE 3
/* main function */
int main ()
{
char board[SIZE][SIZE];
int row, col;
clear_table (board);
display_table (board);
do
{
get_player1_mover (board, row, col);
generate_player2_move (board, row, col);
} while (check_end_of_game (board) == false);
print_winner (board);
return 0;
}
/* display table function */
void display_table (int board[][SIZE], int SIZE)
{
int row, col;
printf ("The current state of the game is:\n");
for (row = 0; row < SIZE; row++)
{
for (col = 0; col < SIZE; col++)
{
char board[row][col];
board[row][col] = '_';
printf ("%c ", board[row][col]);
}
printf ("\n");
}
}
/* clear table function */
void clear_table (int board[][SIZE], int SIZE)
{
int row, col;
char board[row][col];
for (row = 0; row < SIZE; row++) {
for (col = 0; col < SIZE; col++) {
if (board[row][col] == 'x' || array[row][col] == 'o') {
board[row][col] = '_';
}
}
}
}
/* check table full function */
/* return True if board is full */
/* return False if board is not full */
check_table_full (int board[][SIZE], int SIZE)
{
/* update table function */
/* updates board with player moves */
/* return nothing */
void update_table (int board[][SIZE], int SIZE)
{
/* check legal option function */
/* True if legal, False if not */
/* if move is within bounds of board or on empty cell */
check_legal_option (int board[][SIZE], int SIZE)
{
/* generate player2(computer) move function */
/* generate a random move */
/* update board */
/* print out current state of board */
void generate_player2_move (int board[][SIZE], int SIZE)
{
/* check three in a row function */
/* return zero if draw */
/* return one if player1 has three in a row */
/* return two if player2 has three in a row */
check_three_in_a_row (int board[][SIZE], int SIZE)
{
/* check end of game function */
/* return True if game ended */
/* return false if game continues */
check_end_of_game (int board[][SIZE], int SIZE)
{
/* get player 1 move function */
/* if given move is not valid get another move */
/* update board */
/* print out board */
void get_player1_move (int board[][SIZE], int SIZE)
{
int row, col;
printf
("Player 1 enter your selection [row, col]: ");
scanf ("%d,%d", &row, &col);
char board[row][col];
board[row][col] = 'o';
printf ("The current state of the game is:\n");
/* print winner function */
void print_winner (int board[][SIZE], int SIZE)
{
The functions I've completed are display_table and the clear_table and I almost completed get_player1_move but I am stuck with how to make sure it prints out table.
It is apparent you are stuck on understanding your function declarations and where you have used int and where you have used char. (types matter).
Before addressing anything else, the No. 1 thing you can do to let your compiler help you code is to enable compiler warnings. That means at minimum for gcc/clang, add -Wall -Wextra as compiler options (recommend: -Wall -Wextra -pedantic -Wshadow), for VS (cl.exe) use /W3 and -- do not accept code until it compiles cleanly without warning! Your compiler will tell you the exact line (and many times the column) where it sees problematic code. Let the compiler help you write better code.
Next, you use the constant SIZE to provide the dimensions for your board. Good! If you need a constant -- #define one or more -- as you have. Understand, when you define a constant, it has file scope, it can be seen and used within any function within that file (or within any file that includes the header in which the constant is defined). As such, there is no need to pass SIZE as a parameter to your functions. They know what SIZE is, e.g.:
void display_table (char board[][SIZE]);
void clear_table (char board[][SIZE]);
Next, you cannot re-declare char board[row][col]; as you have in clear_table(). That declaration "shadows" the declaration of board from main() that you pass a parameter, e.g. void clear_table (char board[][SIZE]);. (thus the advice of including the -Wshadow compiler option to warn you when you try something that creative....) The same applied to display_table.
When you re-declare board in clear_table (e.g. char board[row][col];) and then use board in clear_table, you are updating the re-declared board that is local to the function (and is thus destroyed when the function returns), so the changes are never seen back in main().
Further, you declare board as type char in main(), e.g.
char board[SIZE][SIZE] = {{0}}; /* initialize all variables */
but then attempt to pass board as type int, e.g.
void display_table (int board[][SIZE], int SIZE) {
Your parameter needs to match your declaration type.
With those simple adjustments and cleaning up your clear_table and display_table just a tad, you could do something like:
/* display table function */
void display_table (char board[][SIZE])
{
int row, col;
printf ("\nThe current state of the game is:\n");
for (row = 0; row < SIZE; row++) {
for (col = 0; col < SIZE; col++) {
putchar (' ');
if (board[row][col])
putchar (board[row][col]); /* use putchar for a single char */
else
putchar ('_');
}
putchar ('\n');
}
}
/* clear table function */
void clear_table (char board[][SIZE])
{
int row, col;
// char board[row][col]; /* don't redeclare board */
/* your compiler should be screaming warnings */
for (row = 0; row < SIZE; row++)
for (col = 0; col < SIZE; col++)
board[row][col] = '_'; /* just clear, no need to check */
}
Now simply make sure you provide a prototype of the functions above main() in your file so main() knows of the existence of both functions before they are called in main() (alternatively, you could just move the definition of both functions above main()). (a function must be declared before it can be used -- that means above the function where it is called in a "top down read" of the file)
Your code for both functions wasn't that far off, you were just missing a few implementation details (rules). To provide a working clear_table and display_table (along with a cheezy diagonal_x function to initialize the diagonal to all 'x' and the remainder to 'o', you could do:
#include <stdio.h>
#define SIZE 3 /* if you need a constant, #define one (Good!) */
void display_table (char board[][SIZE]);
void clear_table (char board[][SIZE]);
/* cheezy init funciton */
void diagonal_x (char (*board)[SIZE])
{
for (int row = 0; row < SIZE; row++)
for (int col = 0; col < SIZE; col++)
if (row == col)
board[row][col] = 'x';
else
board[row][col] = 'o';
}
int main (void) /* no comment needed, main() is main() */
{
char board[SIZE][SIZE] = {{0}}; /* initialize all variables */
clear_table (board); /* set board to all '_' */
display_table (board); /* output board */
diagonal_x (board); /* init board to diagonal_x */
display_table (board); /* output board */
/*
do {
get_player1_mover (board, row, col);
generate_player2_move (board, row, col);
} while (check_end_of_game (board) == false);
print_winner (board);
*/
return 0;
}
/* display table function */
void display_table (char board[][SIZE])
{
int row, col;
printf ("\nThe current state of the game is:\n");
for (row = 0; row < SIZE; row++) {
for (col = 0; col < SIZE; col++) {
putchar (' ');
if (board[row][col])
putchar (board[row][col]); /* use putchar for a single char */
else
putchar ('_');
}
putchar ('\n');
}
}
/* clear table function */
void clear_table (char board[][SIZE])
{
int row, col;
// char board[row][col]; /* don't redeclare board */
/* your compiler should be screaming warnings */
for (row = 0; row < SIZE; row++)
for (col = 0; col < SIZE; col++)
board[row][col] = '_'; /* just clear, no need to check */
}
(note: whether you include enclosing '{' and '}' on loops or conditionals with only a single expression is up to you. It may help keep things straight for you -- up to you)
Also note, you can pass board as a pointer-to-array of char [SIZE], e.g. char (*board)[SIZE] as well as char board[][SIZE], they are equivalent.
Example Use/Output
Note: I added a space before each character in the board to make the display a little more readable -- you can remove it if you like.
$ ./bin/checkerinit
The current state of the game is:
_ _ _
_ _ _
_ _ _
The current state of the game is:
x o o
o x o
o o x
This should get your going. Let me know if you have further questions.

Fixing small error in output using arrays in C

I am currently working on a project that when given a main function which calls another function confab(), outputs a serious of characters. The question refers to some made up race. They choose an integer nRows between 2 and half the length of the message, e.g. a message of length 11 would allow values of nRows in the range 2 to 5. The message is then written down the columns of a grid, one character in each grid cell, nRows in each column, until all message characters have been used. This may result in the last column being only partially filled. The message is then read out row-wise.
For example the message "Don't wait until the last day before starting" with a nRows of 3 would return:
D'wtnlhltabo ai.ota t ea yersrnn iuit sd fettg
I have written code that does this fairly efficiently, however I have been provided with a test case that i cannot seem to work out.
char buffer[8] = {'*','*','*','*','*','*','*','*',};
confab("ABCDEF.", 3, buffer);
printf("%s\n", buffer);
Is this example, and the output it should give is:
AD.BECF
However my code returns:
AD.BECF*
Due to the extra * in the outText buffer not being replaced with a character. I have tried many things such as removing this extra *, or re initializing the outText to be the same length as the inText (within the code as the main case provided is not allowed to be edited), however nothing thus far has made a difference.
I was wondering if there would be a quick edit I could apply to my code that would perform this change, as I cannot seem to find a way apart from editing the main input which is not allowed.
My code is as follows:
/*
* Confabulons.c
* A program to encode for the Confabulons
*
* August 8th 2015
*/
#include <stdio.h>
#include <string.h>
//A simple function confab which given input text, and a number
//of rows, returns a phrase in the Confabulons encoding scheme.
void confab(const char inText[], int nRows, char outText[])
{
int count = 0;
int i = 0;
int z = 0;
int len = strlen(inText);
while (z < nRows)
{
while (((int)inText[count] > 0) && (count < len))
{
outText[i] = inText[count];
i ++;
count = count + nRows;
}
z ++;
count = z;
}
}
At the end of the function add line:
outText[i] = '\0';
You need to validate the length of the outText string, try:
void confab(const char inText[], int nRows, char outText[])
{
int count = 0;
int i = 0;
int z = 0;
int len = strlen(inText);
int lenOut = strlen(outText);
while (z < nRows)
{
while (((int)inText[count] > 0) && (count < len))
{
outText[i] = inText[count];
i ++;
count = count + nRows;
}
z ++;
count = z;
}
if (i < lenOut) {
outText[i] = '\0';
}
}

Getting the values of linked list with loops

I have to create a function who can get the value of a matrix wich take the form of a double linked list. Here is the structures of the matrix
typedef struct row {
unsigned int indiceRow;
struct row * next;
struct col * data;
} row;
typedef struct col{
double value;
unsigned int indiceColumn;
struct col * next;
} col;
typedef struct matrix{
int nRows;
int nCols;
struct row * rowFirst;
}matrix;
the structure matrix represent the top of the linked list and contain the total number of rows and columns and a variable row wich point to the first node of the list of row nodes. the row nodes contain the number of the row of the matrice, a variable row called next wich represent the next line of the matrix and a variable data point to another list of col nodes. Those col nodes contains the number of the column, the value at those coordonates(row,column) and the a col next. only the values different of zero have to be in the col linked list.
To get the value of a precise point of the matrix I created the function sp_get. It take a structure matrix, the line and column I'm looking for and a double variable as argument. It returns 0 when it works and update the variable double *val with the value I'm looking for.
int sp_get( struct matrix *mat, unsigned int rows, unsigned int col, double *val){
row * temps = (row*)malloc(sizeof(row));
temps = mat->rowFirst;
while(temps->indiceRow!= rows){
temps = temps->next;
}
while(temps->data!= NULL && temps->data->indiceColumn!= col && temps->data->next!=NULL){
temps->data = temps->data->next;
}
if(temps->data->indiceColumn == col){
*(val) = temps->data->value;
}
else{
*(val) = 0.0;
}
return 0;
First I create a row variable to run through the matrix, then I look for the good row and then for the good column. If I can't find the good column it means that the value is 0.
When I use the function to look for one value, it works well, and always return the good value.(tempMatrix is a matrix variable and contain the linked list)
double * vall =(double*)malloc(sizeof(double));
sp_get(tempMatrix, 2, 3, vall);
but when I'm using the function with a double loop for I don't have the same results and I can't not explain why...
double * vall =(double*)malloc(sizeof(double));
int i;
int j;
for(i=1;i<=tempMatrix->nRows;i++){
for(j=1; j<=tempMatrix->nCols;j++){
sp_get(tempMatrix,i,j,vall);
printf(" %f ", *(vall));
}
printf("\n");
}
Here are the result I get with the loops
and here are the results I should get
It might be a proble of memory leak, I don't know where it comes from.
Thanks in advance for your help!
Just in sp_get alone the following problems abound:
Memory the first two lines.
Anytime you see something like this in successive lines in C:
ptr = malloc(...)
ptr = <something else>
it is always a memory leak.
Updating the column header rather than simply enumerating it
Once you find the row you seek, you then do this:
while(temps->data!= NULL &&
temps->data->indiceColumn!= col &&
temps->data->next!=NULL)
{
temps->data = temps->data->next;
}
Ask yourself, what is temps->data = ... actually updating? It is changing the temps->data pointer to point to its own next, which means what temps->data pointed to prior is gone. That's fine if temps->data is a temporary pointer, but it isn't. It is the data member in the row struct you worked so hard to find in the prior loop.
Potential NULL pointer dereference
You may think having this:
while(temps->data!= NULL &&
temps->data->indiceColumn!= col &&
temps->data->next!=NULL)
for the while-condition in your loop will harbor safety from temp-data being NULL for the code that follows:
if(temps->data->indiceColumn == col)
{
*(val) = temps->data->value;
}
but if it did, then why bother with the first clause (which is correct, btw). It appears the addition of the last clause (temps->data->next!=NULL) was an effort to stave off crashes. That isn't the way to do it.
Minor: Hiding type col with parameter col
Needs little explanation. See your var names.
Minor: There is no need to dynamically allocate the out-parameter as you're using it.
Your code do to this:
double * vall =(double*)malloc(sizeof(double));
int i, j;
for(i=1;i<=tempMatrix->nRows;i++)
{
for(j=1; j<=tempMatrix->nCols;j++)
{
sp_get(tempMatrix,i,j,vall);
printf(" %f ", *(vall));
}
printf("\n");
}
Can just as easily do this:
double val = 0.0;
int i, j;
for(i=1;i<=tempMatrix->nRows;i++)
{
for(j=1; j<=tempMatrix->nCols;j++)
{
sp_get(tempMatrix,i,j,&val); // note address-of operator
printf(" %f ", val);
}
printf("\n");
}
Updated sp_get
I'm pretty sure this is what you're trying to do. The following will return 0 if the indexed values found and retrieved, otherwise it returns -1 and the out-parameter is set to 0.0.
int sp_get( struct matrix const *mat, unsigned int rows, unsigned int cols, double *val)
{
// prime to 0.0
*val = 0.0;
if (!mats)
return -1;
// walk the row table
struct row const *row_ptr = mat->rowFirst;
while (row_ptr && row_ptr->indiceRow != rows)
row_ptr = row_ptr->next;
// leave now if we didn't find the row.
if (!row_ptr)
return -1;
struct col const *col_ptr = row_ptr->data;
while (col_ptr && col_ptr->indiceColumn != cols)
col_ptr = col_ptr->next;
if (!col_ptr)
return -1;
*val = col_ptr->value;
return 0;
}
Note we modify nothing in the actual matrix, so the entire thing, including all pointers we use to index within it, can be const (and should be).
Best of luck.

Transposing a matrix

I want to transpose a matrix, its a very easy task but its not working with me :
UPDATE
I am transposing the first matrix and
storing it in a second one
The two
arrays point to the same structure
I
need two arrays (target and source)
so I can display them later for
comparison.
struct testing{
int colmat1;
int rowmat1;
float mat[64][64];
};
int testtranspose(testing *test,testing *test2){
int i,j;
test2->colmat1 = test->rowmat1;
test2->rowmat1 = test->colmat1
for(i=0;i<test->rowmat1;i++){
for(j=0;j<test->colmat1;j++){
test2->mat[i][j] = test->mat[i][j];
}
printf("\n");
}
}
I thought this is the correct method of doing it, but apparently for a matrix such as :
1 2
3 4
5 6
7 8
I get :
1 2 0 0
3 4 0 0
What is the problem ?
Please help,
Thanks !
To transpose the matrix, you need to change rows and columns. So you need to use:
targetMatrix[i][j] = sourceMatrix[j][i];
Note how the order of i,j is changed, since one matrix's rows are another's columns.
By the way, instead of (*a).b, you can write a->b. This is the normal way of accessing a field of a struct pointer.
Try this...
struct testing{
int colmat;
int rowmat;
float mat[64][64];
};
int testtranspose(testing *test,testing *test2){
int i,j;
test2->colmat = test->rowmat;
test2->rowmat = test->colmat;
for(i=0;i<test->rowmat;i++){
for(j=0;j<test->colmat;j++){
test2->mat[j][i] = test->mat[i][j];
}
}
return 0;
}
int printmat(testing* mat)
{
for(int i=0;i<mat->rowmat;i++)
{
printf("\n");
for(int j=0;j<mat->colmat;j++)
printf((" %f"),mat->mat[i][j]);
}
return 0;
}
// 2
// main.cpp
int _tmain(int argc, _TCHAR* argv[])
{
testing mat1, mat2;
memset(&mat1,0,sizeof(testing));
memset(&mat2,0,sizeof(testing));
mat1.colmat =2;
mat1.rowmat =3;
for(int i=0;i<mat1.rowmat;i++)
{
for(int j=0;j<mat1.colmat;j++)
mat1.mat[i][j] = (float)rand();
}
printmat(&mat1);
testtranspose(&mat1,&mat2);
printmat(&mat2);
getchar();
}
I am new to C / C++ (3rd day or so :) ) and I had the same problem. My approach was slightly different in that I thought it would be nice to have a function that would return a transposed matrix. Unfortunately, as I found out, you cannot return a an array nor pass an array to a function in C++ (let alone a double array), but you can pass / return a pointer which works similar to an array. So this is what I did:
int * matrix_transpose(int * A, int A_rows, int A_cols){
int * B;
int B_rows, B_cols;
B_rows = A_cols; B_cols= A_rows;
B = new int [B_rows*B_cols];
for(int i=0;i<B_rows;i++){
for(int j=0;j<B_cols;j++){
B[i*B_cols+j]=A[j*A_cols+i];
}
}
return B;
};
The trick was in dynamic arrays. I used A_rows and B_rows as separate names (you can use only rows and cols) in order to make the problem less intricate and less confusing when reading code.
B = new int [rows*cols] // This is cool in C++.

Resources