Trying to understand why my script repeats - c

I am taking an online course with very little support. I am trying to follow instructions and write a script that takes input and draws two rectangles. Unfortunately, it just repeats infinitely, and I don't know what I'm missing. Any guidance would really help! Thank you so much for your help and time, this is my first post and I apologize for any formatting errors.
#include <stdio.h>
#include <stdlib.h>
/*
* Determines if coord is in range between
* offset (INCLUSIVE) and offset + size (EXCLUSIVE)
*/
int isInRange(int coord, int offset, int size) {
// if coord is in range, return 1
if ((coord >= offset) && (coord < (offset + size))) {
return 1;
}
// else, return 0
else {
return 0;
}
return 0;
}
/*
* Determines if coord is at border of offset or
* offset + size
*/
int isAtBorder(int coord, int offset, int size) {
// if coord is equal to offest or offset + size
if (coord == offset || (offset + size)) {
return 1;
}
// return 1, else return 0
else {
return 0;
}
return 0;
}
void squares(int size1, int x_offset, int y_offset, int size2) {
//compute the max of size1 and (x_offset + size2). Call this w
int w = (size1 + (x_offset + size2));
//compute the max of size1 and (y_offset + size2). Call this h
int h = (size1 + (y_offset + size2));
//count from 0 to h. Call the number you count with y
for (int y = 0; y < h; h++) {
//count from 0 to w. Call the number you count with x
for (int x = 0; x < w; x++) {
//check if EITHER
// ((x is between x_offset and x_offset +size2) AND
if (((isInRange(x, x_offset, size2) == 1) &&
// y is equal to either y_offset OR y_offset + size2 - 1)
(isAtBorder(y, y_offset, size2 - 1) == 1))
// OR
||
// ((y is between y_offset and y_offset + size2) AND
((isInRange(y, y_offset, size2) == 1) &&
// x is equal to either x_offset OR x_offset + size2 -1)
(isAtBorder(x, x_offset, size2-1)))) {
// if so, print a *
printf ("*");
}
//if not,
// check if EITHER
// x is less than size1 AND (y is either 0 or size1-1)
else {
if (((x < size1) && (isAtBorder(y, 0, size1 - 1) == 1))
// OR
||
// y is less than size1 AND (x is either 0 or size1-1)
((y < size1) && (isAtBorder(x, 0, size1 - 1) == 1))) {
//if so, print a #
printf ("#");
}
//else print a space
else {
printf (" ");
}
}
}
//when you finish counting x from 0 to w,
//print a newline
printf ("\n");
}
}

The real problem is, I suppose, in your squares function. Check out your for loop in this snippet:
for (int y = 0; y < h; h++) {
//count from 0 to w. Call the number you count with x
for (int x = 0; x < w; x++) {
In the first loop you're incrementing h, not y. Your "y" variable always stays at value which is equal 0, thus it won't finish this loop, since it will ALWAYS be smaller than "h" variable, unless "h" is less or equal than 0. You probably were aiming to increment "y" variable, not h.
After that, please check out your isAtBorder function. The "or" logical operator:
int isAtBorder(int coord, int offset, int size) {
// if coord is equal to offest or offset + size
if (coord == offset || (offset + size)) {
return 1;
}
// return 1, else return 0
else {
return 0;
}
return 0;
}
in the if statement is always true, so basically this function always returns 1.

Related

Game of Life problem with board update function in C

I need help with my Game of Life implementation in C. Other posts on Stackoverflow lead me to believe that my problem was to do with dangling pointers, but after modifying my program to use a global 2D array for the game grid instead of passing it to functions which return new 2D arrays, I realized that it was a problem with my update function.
I have tried hard-coding a number of simple patterns, including gliders and oscillators, and the grid doesn't update correctly. The patterns do update the same way every time the program is run, so I don't think it's a problem of uninitialized memory causing problems. I also know that there are no cells which contain values greater than 1. Therefore, the problem must lie in my mechanisms for updating the grid.
Can someone help me find the problem? I can't find anything wrong with my code and I believe I have programmed the rules correctly.
Here are my neighbors and update functions, along with the relevant variable and constant declarations.
#define MAX_Y 10 /* height */
#define MAX_X 30 /* width */
int grid[MAX_Y][MAX_X];
int neighbors(int x, int y) {
int dx, dy, dstx, dsty;
int n = 0;
for (dy = -1; dy <= 1; ++dy) {
for (dx = -1; dx <= 1; ++dx) {
dsty = y + dy;
dstx = x + dx;
if (dsty >= 0 && dsty < MAX_Y && dstx >= 0 && dstx < MAX_X)
n += !!grid[dsty][dstx]; /* use !! so that non-zero values eval to 1 */
}
}
/* (n > 0) ? printf("Point (%d,%d) has %d neighbors!\n", x, y, n) : 0; */
return n;
}
void update(void) {
int new[MAX_Y][MAX_X];
memset(new, 0, sizeof(int) * MAX_Y * MAX_X);
int i, j, n;
for (i = 0; i < MAX_Y; ++i) {
for (j = 0; j < MAX_X; ++j) {
n = neighbors(i, j);
/* alive, 2 or 3 neighbors -> alive!
* dead, 3 neighbors -> alive!
* anything else -> dead :(
*/
if (grid[i][j] && (n == 2 || n == 3))
new[i][j] = 1;
else if (!grid[i][j] && n == 3)
new[i][j] = 1;
else
new[i][j] = 0;
}
}
memcpy(grid, new, sizeof grid);
}
In your neighbors function, you need to think carefully about the loop iteration where dx and dy are both zero. Conway's Game of Life does not consider a cell to be neighbor of itself, so you need to avoid counting it.
You're also confusing yourself by using the letters i and j. You're allowing j to go all the way up to MAX_X, but then you are using j as the y coordinate when you call neighbors, so that will cause overflows and incorrect calculations. (Starting with the easier case of a 10x10 grid would sometimes save you from bugs like this.)
You should adjust the neighbors() function to omit the cell itself.
Here is a modified version:
#define MAX_Y 10 /* height */
#define MAX_X 30 /* width */
unsigned char grid[MAX_Y][MAX_X];
int neighbors(int x, int y) {
int n = -!!grid[y][x];
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
int dsty = y + dy;
int dstx = x + dx;
if (dsty >= 0 && dsty < MAX_Y && dstx >= 0 && dstx < MAX_X && grid[dsty][dstx])
n++;
}
}
return n;
}
void update(void) {
int new[MAX_Y][MAX_X] = { 0 };
for (int y = 0; y < MAX_Y; ++y) {
for (int x = 0; x < MAX_X; ++x) {
int n = neighbors(y, x);
/* alive, 2 or 3 neighbors -> alive!
* dead, 3 neighbors -> alive!
* anything else -> dead :(
*/
new[y][x] = (grid[y][x] && n == 2) || n == 3;
}
}
memcpy(grid, new, sizeof grid);
}
The neighbors() function can be simplified with fewer tests:
int neighbors(int x, int y) {
int n = -(grid[y][x] != 0);
int x1 = x - (x > 0);
int x2 = x + (x < MAX_X - 1);
int y1 = y - (y > 0);
int y2 = y + (y < MAX_Y - 1);
for (y = y1; y <= y2; y++) {
for (x = x1; x <= x2; x++) {
n += grid[y][x] != 0;
}
}
return n;
}

Not sure how to deal with the error "excess elements in array initializer"

In line 10 I cannot find out where my problem is at first. I place int a[100][100]={0} but the cpu speed is stuck.
Then, I try to change it into a[n][n] but no output is shown.
Last, I try to change it again as if it resembles the original ones.
However, nothing works instead of a new question.
#include<stdio.h>
int main() {
int n;
while (scanf("%d", &n)) {
n *= 2;
int x = 0, y = 0, num = 1;
int a[n][n] = {0};
a[x][y] = num++;
while (n * n >= num) //定義陣列
{
while (y + 1 < n && !a[x][y + 1]) //向右
a[x][++y] = num++;
while (x + 1 < n && !a[x + 1][y]) //向下
a[++x][y] = num++;
while (y - 1 >= 0 && !a[x][y - 1]) //向左
a[x][--y] = num++;
while (x - 1 >= 0 && !a[x - 1][y]) //向上
a[--x][y] = num++;
}
for (x = 0; x < n; x++) //print 陣列
{
for (y = 0; y < n; y++) {
if (y != n - 1) {
printf("%d ", a[x][y]);
} else {
printf("%d", a[x][y]);
}
}
printf("\n");
}
break;
}
return 0;
}
At least this problem:
Variable Length Arrays (VLA) cannot be initialized via the C standard.
Alternate, assign via memset() after defining a.
// int a[n][n]={0};
int a[n][n];
memset(a, 0, sizeof a);

Knight's tour- given n moves, in how many options can a knight move from (1,1) to (8,8) in n moves?

I've been trying to improve my recursion skills in C and I came across this question. I've tried to solve it, yet the code doesn't seem to work properly.
For example, there are 108 options for the knight to move from (1,1) to (8,8) in 6 moves and in my code the result is completely different. The question asks how many ways are there to move a knight from (1,1) to (8,8) in n moves(n given from the user) in 8x8 board. here's my code:
#include <stdio.h>
#define SIZE 8
//x,y coordinates of the knight.
int knightsTour(int x, int y, int num);
void main() {
int n;
int result;
do {
scanf(" %d", &n);
result = knightsTour(1,1,n);
printf("%d\n", result);
} while (n > 0);
}
int knightsTour(int x,int y,int num) {
int result = 0;
int i, j;
if (num == 0) {
return 0;
}
if (((x > 8) || (y > 8))||((x == 8) && (y == 8))) {
return 0;
}
for (i = 1; i <= SIZE; i++) {
for (j = 1; j <= SIZE; j++) {
if ((i != y) && (j != x) && ((i != y + j) && (j != x + i)) && ((i != y + j) && (j != x - i))
&& ((i != y - j) && (j != x + i)) && ((i != y - j) && (j != x - i))) {
result += knightsTour(i, j, num - 1) + 1;
}
}
}
return result;
}
Your code has several problems:
You add one to the results unconditionally when you call your recursivev function. You should only count paths that land on h8 after 6 moves, for which you can check only after you have jumped to the new position.
When you want to find possible moves, it is wasteful to check all squares on the board. You know the rank and file of the knight, so you also know the eight possible moves. You must take care not to jump off the board. It is easier to verify that rank and file are valid at the beginning of the function.
One approach would be the following recursive method:
Are rank and file valid? If not, return 0.
Have we reached the desired number of moves? If so, return 1 if the current square is h8, and 0 otherwise.
Return the sum of the number of valid moves the knight can make with one fewer move for the eight possible moves from the current positions. You don't need to check here, because the validity of a move will be checked at the beginning of the function.
Putting this together:
#include <stdio.h>
#define SIZE 8
int knightsTour(int x, int y, int num)
{
if (x < 1 || x > SIZE) return 0;
if (y < 1 || y > SIZE) return 0;
if (num == 0) return (x == SIZE && y == SIZE);
return knightsTour(x + 2, y + 1, num - 1)
+ knightsTour(x + 1, y + 2, num - 1)
+ knightsTour(x - 1, y + 2, num - 1)
+ knightsTour(x - 2, y + 1, num - 1)
+ knightsTour(x - 2, y - 1, num - 1)
+ knightsTour(x - 1, y - 2, num - 1)
+ knightsTour(x + 1, y - 2, num - 1)
+ knightsTour(x + 2, y - 1, num - 1);
}
int main(void)
{
int result = knightsTour(1, 1, 6);
printf("%d\n", result);
return 0;
}
This code is straightforward and it determines the 108 possible moves.

Segmentation fault on trying to pass a recursive function to populate a 2D array

I'm trying to pass a recursive function that populates my 2D array of structs. My memory allocation is working fine, but when I try to do a recursion, I get the error: Segmentation fault (core dumped).
Any idea why this must be happening? I think I wrote my code so that no index out of bound occurs. I still don't know why this is happening. Any help is going to be appreciated. Thanks!
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct {
char val;
bool filled;
} elements;
void assign(elements ** elements, int row, int column, int x, int y, int limit);
int main(int argc, char** argv)
{
int row = 0;
int column = 0;
int x = 0;
int y = 0;
int limit = 0;
sscanf(argv[1], "%d", &row);
sscanf(argv[2], "%d", &column);
sscanf(argv[3], "%d", &x);
sscanf(argv[4], "%d", &y);
sscanf(argv[5], "%d", &limit);
elements **foo;
foo = (elements **)malloc(sizeof(elements *) * row);
for (int i = 0; i < column; i++)
foo[i] = (elements *)malloc( sizeof(elements) * row);
foo[y][x].val = 'C';
// printf("%c\n", foo[y][x].val);
assign(foo, row, column, x, y, limit);
for(int i = 0; i < row; i++)
{
for(int j = 0; j < column; j++)
{
// foo[i][j].val = '.';
printf("%d\t ", foo[i][j].filled);
}
printf("\n");
}
}
void assign(elements ** elements, int row, int column, int x, int y, int limit)
{
int tempX = x;
int tempY = y;
if(elements[y][x].filled != 0 )
{
//printf("reached.");
return;
}
else if(limit < 0)
{
//printf("reached.");
return;
}
else
{
if(elements[y][x].val != 'C')
elements[y][x].val = limit + '0';
elements[y][x].filled = true;
tempX = x - 1;
tempY = y;
if (!( x < 0 || y < 0 || x > column - 1 || y > row -1 ))
assign(elements, row, column, tempX, tempY, limit - 1); // go up
tempX = x;
tempY = y + 1;
if (!( x < 0 || y < 0 || x > column - 1 || y > row -1 ))
assign(elements, row, column, tempX, tempY, limit - 1); // go right
tempX = x + 1;
tempY = y;
if (!( x < 0 || y < 0 || x > column - 1 || y > row -1 ))
assign(elements, row, column, tempX, tempY, limit - 1); // go down
tempX = x;
tempY = y - 1;
if (!( x < 0 || y < 0 || x > column - 1 || y > row -1 ))
assign(elements, row, column, tempX, tempY, limit - 1); // go left
}
}
each of the if() code blocks in the last half of assign() are beginning with the same basic parameter values, except the limit changes.
so the total number of recursions (which the code seems to be limiting the the value in 'limit' is not actually limited,
because when limit is 0, it is not necessarily the last call to be made to assign() and once limit is <0 the code will recurse about 16 gig more times. (at least) This is probably why the program crashes
Suggest decrementing limit within assign() before any of the recursive calls to assign()

How to fix Segfault due to recursive algorithm

I'm trying to code a perfect maze generator, but I have few problems in the code due to the recursion which leads to Segfault when the maze is too big. Here is the main part of the code:
t_maze *init_maze(int w, int h)
{
t_maze *maze;
int j;
int i;
if ((maze = malloc(sizeof(t_maze))) == NULL)
return (NULL);
maze->w = w;
maze->h = h;
if ((maze->cells = malloc(sizeof(char *) * maze->h)) == NULL)
return (NULL);
j = -1;
while (++j < maze->h)
{
if ((maze->cells[j] = malloc(sizeof(char) * maze->w)) == NULL)
return (NULL);
i = -1;
while (++i < maze->w)
maze->cells[j][i] = (j % 2 == 1 || i % 2 == 1) ? (1) : (0);
}
return (maze);
}
void detect_neighbours(t_maze *maze, char *neighbours, int x,
int y)
{
int i;
// I fill the array with 1 (means there is no neighbours)
// If there is a neighours, I set the cell to 0
// In this order: Top, right, bottom, left
i = -1;
while (++i < 4)
neighbours[i] = 1;
if (y - 2 >= 0 && x >= 0 && y - 2 < maze->h
&& x < maze->w && maze->cells[y - 2][x] == 0)
neighbours[0] = 0;
if (x + 2 >= 0 && x + 2 < maze->w && y >= 0 && y < maze->h
&& maze->cells[y][x + 2] == 0)
neighbours[1] = 0;
if (y + 2 < maze->h && y + 2 >= 0 && x >= 0
&& x < maze->w && maze->cells[y + 2][x] == 0)
neighbours[2] = 0;
if (x - 2 >= 0 && x - 2 < maze->w && y >= 0 && y < maze->h
&& maze->cells[y][x - 2] == 0)
neighbours[3] = 0;
}
int there_is_no_neighbours(char *neighbours)
{
int i;
// this function returns 0 if there is at least 1 neigbours
i = -1;
while (++i < 4)
if (neighbours[i] == 0)
i = 41;
if (i == 42)
return (0);
return (1);
}
void set_maze_protected(t_maze *maze, int y, int x, int val)
{
// To prevent segfault when I put values in the maze,
// I check the x and y keys
if (x >= 0 && y >= 0 && x < maze->w && y < maze->h)
maze->cells[y][x] = val;
}
int build_maze(t_maze *maze, int x, int y)
{
char neighbours[4];
int i;
int ret;
ret = 0;
detect_neighbours(maze, neighbours, x, y);
if (there_is_no_neighbours(neighbours) == 1)
return (0);
i = rand() % 4;
while (neighbours[i] == 1)
i = rand() % 4;
if (i == 0)
{
set_maze_protected(maze, y - 1, x, 2);
set_maze_protected(maze, y - 2, x, 2);
ret = build_maze(maze, x, y - 2);
}
if (i == 1)
{
set_maze_protected(maze, y, x + 1, 2);
set_maze_protected(maze, y, x + 2, 2);
ret = build_maze(maze, x + 2, y);
}
if (i == 2)
{
set_maze_protected(maze, y + 1, x, 2);
set_maze_protected(maze, y + 2, x, 2);
ret = build_maze(maze, x, y + 2);
}
if (i == 3)
{
set_maze_protected(maze, y, x - 1, 2);
set_maze_protected(maze, y, x - 2, 2);
ret = build_maze(maze, x - 2, y);
}
while (ret != 0)
ret = build_maze(maze, x, y);
return (1);
}
int main()
{
t_maze *maze;
int w;
int h;
w = 50;
h = 50;
srand(time(NULL) * getpid());
if ((maze = init_maze(w, h)) == NULL)
return (1);
maze->cells[0][0] = 2;
build_maze(maze, 0, 0);
// display_maze shows values in the 2D array (maze->cells)
display_maze(maze);
return (0);
}
I call this function in main with this call:
build_maze(maze, 0, 0);
The function detects is the cell has neighbours, and if it has, the function calls one of them randomly and open the door between the two.
If the x and y args are bigger than 2500 for example, it will segfault. (If it is less than 2500, it will work great)
How to fix this ?
I learnt about tail call but I ignore how to implement that in this case,
Thank you,
Best Regards
You can increase the stack size.
On POSIX systems, you can use the following code.
#include<stdio.h>
#include <sys/resource.h>
#define required_stack_size 0x8000000 // change this to the stack size you need
int main (int argc, char **argv)
{
struct rlimit rl;
int result;
if((result = getrlimit(RLIMIT_STACK, &rl)) < 0)
{
fprintf(stderr, "getrlimit returned result %d\n", result);
return -1;
}
if(rl.rlim_cur<required_stack_size)
{
rl.rlim_cur = required_stack_size;
if((result = setrlimit(RLIMIT_STACK, &rl)) < 0)
{
fprintf(stderr, "setrlimit returned result = %d\n", result);
return -1;
}
}
//the rest code
return 0;
}

Resources