I want to create a minesweeper generator in c and whenever I run the program either the window comes out oddly shaped thereby changing the positions of the elements to look incorrect, or the function I use to generate the tiles is generating them incorrectly. How would I solve either problem? My code is here:
#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
#include <stdlib.h> /* included for rand */
#define WIDTH 70
#define HEIGHT 35
#define BOMBS 20
HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */
void SetGrid(int grid[WIDTH][HEIGHT])
{
int bomb[2] = {abs(rand() % WIDTH),
abs(rand() % HEIGHT)};
for (int i = 0; i < BOMBS; i++)
{
while (grid[bomb[0]][bomb[1]] < -1)
{
bomb[0] = abs(rand() % WIDTH);
bomb[1] = abs(rand() % HEIGHT);
}
grid[bomb[0]][bomb[1]] = -9;
grid[bomb[0]+1][bomb[1]+1]++;
grid[bomb[0]-1][bomb[1]-1]++;
grid[bomb[0]-1][bomb[1]+1]++;
grid[bomb[0]+1][bomb[1]-1]++;
grid[bomb[0]-1][bomb[1]]++;
grid[bomb[0]+1][bomb[1]]++;
grid[bomb[0]][bomb[1]-1]++;
grid[bomb[0]][bomb[1]+1]++;
}
}
int main(void)
{
srand(time(0));
SMALL_RECT windowSize = {0, 0, WIDTH - 1, HEIGHT - 1};
COORD bufferSize = {WIDTH, HEIGHT};
COORD characterBufferSize = {WIDTH, HEIGHT};
COORD characterPosition = {0, 0};
SMALL_RECT consoleWriteArea = {0, 0, WIDTH - 1, HEIGHT - 1};
CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
rHnd = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleTitle("Our shiny new title!");
SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
SetConsoleScreenBufferSize(wHnd, bufferSize);
int startGrid[WIDTH][HEIGHT] = {0};
SetGrid(startGrid);
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if(startGrid[x][y] > 0)
{
consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
}
else
{
consoleBuffer[x][y].Char.AsciiChar = (unsigned char)219;
consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
}
}
}
WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
getchar();
}
You need to deal with several boundary issues.
The four corners default to -4
Except for the four corners, the border is -6(Although you did not use them)
Important:The increase at the boundary considers whether the boundary is exceeded.
Here is the code:
#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
#include <stdlib.h> /* included for rand */
#define WIDTH 30
#define HEIGHT 30
#define BOMBS 10
HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */
int check(int a)
{
if (a == 0 || a == WIDTH - 1 || a == HEIGHT - 1)
{
return 1;
}
else
{
return 0;
}
}
void SetGrid(int grid[WIDTH][HEIGHT])
{
int bomb[2] = { abs(rand() % WIDTH),
abs(rand() % HEIGHT) };
char t[100];
for (int i = 0; i < BOMBS; i++)
{
while (grid[bomb[0]][bomb[1]] < -1)
{
bomb[0] = abs(rand() % WIDTH);
bomb[1] = abs(rand() % HEIGHT);
}
grid[bomb[0]][bomb[1]] = -9;
if (check(bomb[0]) || check(bomb[1])) grid[bomb[0]][bomb[1]] = -6;
if (check(bomb[0]) && check(bomb[1])) grid[bomb[0]][bomb[1]] = -4;
if (bomb[0] + 1 <= WIDTH - 1 && bomb[1] + 1 <= HEIGHT - 1)
{
grid[bomb[0] + 1][bomb[1] + 1]++;
}
if (bomb[0] + 1 <= WIDTH - 1)
{
grid[bomb[0] + 1][bomb[1]]++;
}
if (bomb[1] + 1 <= HEIGHT - 1)
{
grid[bomb[0]][bomb[1] + 1]++;
}
if (bomb[0] - 1 >= 0 && bomb[1] + 1 <= HEIGHT - 1)
{
grid[bomb[0] - 1][bomb[1] + 1]++;
}
if (bomb[1] - 1 >= 0)
{
grid[bomb[0]][bomb[1] - 1]++;
}
if (bomb[1] - 1 >= 0 && bomb[0] + 1 <= WIDTH - 1)
{
grid[bomb[0] + 1][bomb[1] - 1]++;
}
if (bomb[0] - 1 >= 0 && bomb[1] - 1 >= 0)
{
grid[bomb[0] - 1][bomb[1] - 1]++;
}
if (bomb[0] - 1 >= 0)
{
grid[bomb[0] - 1][bomb[1]]++;
}
}
}
int main(void)
{
srand(time(0));
SMALL_RECT windowSize = { 0, 0, WIDTH - 1, HEIGHT - 1 };
COORD bufferSize = { WIDTH, HEIGHT };
COORD characterBufferSize = { WIDTH, HEIGHT };
COORD characterPosition = { 0, 0 };
SMALL_RECT consoleWriteArea = { 0, 0, WIDTH - 1, HEIGHT - 1 };
CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
rHnd = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleTitle("Our shiny new title!");
SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
SetConsoleScreenBufferSize(wHnd, bufferSize);
int startGrid[WIDTH][HEIGHT] = { 0 };
SetGrid(startGrid);
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if (startGrid[x][y] > 0)
{
consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
}
else
{
consoleBuffer[x][y].Char.AsciiChar = (unsigned char)111;
consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
}
}
}
WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
printf("\n\n");
getchar();
}
Related
i'm building a raycasting engine and i've done the 2d projection, with wall collisions, now shifting to 3d i'm not being able to render a proper 3d image, i'll throw my code below:
i've tried all types of things by now, even changing my line function
include "../incs/Cub3d.h"
#define DOWN 0
#define UP 1
#define LEFT 2
#define RIGHT 3
#define RAY_NUM 816
t_point horizontalinter(t_mlx *m, float ang)
{
t_point inter;
inter.hit = 1;
double xinter, yinter;
double xstep, ystep;
double xwall, ywall;
xwall = 0;
ywall = 0;
int hit = 0;
float r_angle;
r_angle = (ang);
int r_dir = upordown(r_angle);
int r_lor = leftorright(r_angle);
yinter = floor(m->p->y / TILES) * TILES;
if (r_dir == DOWN)
yinter += TILES;
xinter = m->p->x + (yinter - m->p->y)/tan(r_angle);
ystep = TILES;
if (r_dir == UP)
ystep *= -1;
xstep = TILES / tan(r_angle);
if ((r_lor == LEFT && xstep > 0) || (r_lor == RIGHT && xstep < 0))
xstep *= -1;
double nextx = xinter;
double nexty = yinter;
while (nextx >= 0 && nextx <= WIDTH && nexty >= 0 && nexty <= HEIGHT)
{
if (has_wall(nextx, nexty - (r_dir == UP ? 1 : 0) , m))
{
hit = 1;
xwall = nextx;
ywall = nexty;
break;
}
else
{
nextx += xstep;
nexty += ystep;
}
}
inter.x = xwall;
inter.y = ywall;
if (hit)
{
inter.dist2pl = distancebetween(m->p->x, m->p->y, xwall, ywall);
return(inter);
}
inter.dist2pl = INT_MAX;
return(inter);
}
t_point verticalinter(t_mlx *m, float ang)
{
t_point inter;
inter.hit = 0;
double xinter, yinter;
double xstep, ystep;
double xwall, ywall;
int hit = 0;
xwall = 0;
ywall = 0;
float r_angle = normalize_ang(ang);
int r_dir = upordown(r_angle);
int r_lor = leftorright(r_angle);
//FIND X-interseption
xinter = floor(m->p->x / TILES) * TILES;
if (r_lor == RIGHT)
xinter += TILES;
//FIND Y-interseption
yinter = m->p->y + (xinter - m->p->x) * tan(r_angle);
//find STEPS
//xstep
xstep = TILES;
if (r_lor == LEFT)
xstep *= -1;
//ystep
ystep = TILES * tan(r_angle);
if ((r_dir == UP && ystep > 0) || (r_dir == DOWN && ystep < 0))
ystep *= -1;
// next intersection
double nextx = xinter;
double nexty = yinter;
//make sure that mf hits a wall
// loop untill it finds a wall or leaves canvas, increments with x and y step
while (nextx >= 0 && nextx <= WIDTH && nexty >= 0 && nexty <= HEIGHT)
{
if (has_wall(nextx - (r_lor == LEFT ? 1 : 0) , nexty, m))
{
hit = 1;
xwall = nextx;
ywall = nexty;
break;
}
else
{
nextx += xstep;
nexty += ystep;
}
}
inter.x = xwall;
inter.y = ywall;
if (hit)
{
inter.dist2pl = distancebetween(m->p->x, m->p->y, xwall, ywall);
return(inter);
}
inter.dist2pl = INT_MAX;
return(inter);
}
void calc_rays(t_mlx *m, float ang)
{
int color ;
ang = normalize_ang(ang);
t_point h_hit = horizontalinter(m, ang);
t_point v_hit = verticalinter(m, ang);
t_point closest = v_hit.dist2pl > h_hit.dist2pl ? h_hit : v_hit;
if (closest.hit)
color = rgb_to_int(0,255,0);
else
color = rgb_to_int(0,0,255);
int lineheigth = ((TILES * 5) / closest.dist2pl) * 277;
int drawStart = -lineheigth / 2 + HEIGHT / 2;
if(drawStart < 0)drawStart = 0;
int drawEnd = lineheigth / 2 + HEIGHT / 2;
if(drawEnd >= HEIGHT)drawEnd = HEIGHT - 1;
mlx_line_to(m, closest.x,drawStart , closest.x, drawEnd, color);
printf("%f\n", closest.dist2pl);
}
void cast_rays(t_mlx *m)
{
float r_angle = m->p->ang - (FOV / 2);
for(int i = 0; i < RAY_NUM; i++)
{
calc_rays(m, r_angle);
r_angle += (FOV / RAY_NUM);
}
}
i've tried calculating line heights differently but with no sucess
I'm trying to figure out what I did wrong. My intent is in title :)
This is the code I tried, and it clearly isn't working. It just print's 1 solid colour, also edges are not included yet. What part is wrong I can't figure it out what part of this code is wrong. It's just a function and it's in C.
void edges(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE edit[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
edit[i][j] = image[i][j];
}
}
for (int q = 1; q < height - 1; q++)
{
for (int w = 1; w < width - 1; w++)
{
int redEdit[9];
int greenEdit[9];
int blueEdit[9];
for (int top = 0; top < 3; top++)
{
redEdit[top] += edit[q - 1][w - 1 + top].rgbtRed;
greenEdit[top] += edit[q - 1][w - 1 + top].rgbtGreen;
blueEdit[top] += edit[q - 1][w - 1 + top].rgbtBlue;
}
int midctr = 0;
for (int mid = 3; mid < 6; mid++)
{
redEdit[mid] += edit[q][w - 1 + midctr].rgbtRed;
greenEdit[mid] += edit[q][w - 1 + midctr].rgbtGreen;
blueEdit[mid] += edit[q][w - 1 + midctr].rgbtBlue;
midctr ++;
}
int topctr = 0;
for (int top = 6; top < 9; top++)
{
redEdit[top] += edit[q + 1][w - 1 + topctr].rgbtRed;
greenEdit[top] += edit[q + 1][w - 1 + topctr].rgbtGreen;
blueEdit[top] += edit[q + 1][w - 1 + topctr].rgbtBlue;
topctr ++;
}
int matrixgx[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
int matrixgy[] = {- 1, -2, -1, 0, 0, 0, 1, 2, 1};
int redEditgx[9];
int greenEditgx[9];
int blueEditgx[9];
int redEditgy[9];
int greenEditgy[9];
int blueEditgy[9];
for (int mtrx = 0; mtrx < 9; mtrx++)
{
redEditgx[mtrx] = redEdit[mtrx] * matrixgx[mtrx];
greenEditgx[mtrx] = greenEdit[mtrx] * matrixgx[mtrx];
blueEditgx[mtrx] = blueEdit[mtrx] * matrixgx[mtrx];
redEditgy[mtrx] = redEdit[mtrx] * matrixgy[mtrx];
greenEditgy[mtrx] = greenEdit[mtrx] * matrixgy[mtrx];
blueEditgy[mtrx] = blueEdit[mtrx] * matrixgy[mtrx];
}
// now sum up the changes of gx and gt
int redSumgx = 0;
int greenSumgx = 0;
int blueSumgx = 0;
int redSumgy = 0;
int greenSumgy = 0;
int blueSumgy = 0;
for (int sum = 0; sum < 9; sum++)
{
redSumgx += redEditgx[sum];
greenSumgx += greenEditgx[sum];
blueSumgx += blueEditgx[sum];
redSumgy += redEditgy[sum];
greenSumgy += greenEditgy[sum];
blueSumgy += blueEditgy[sum];
}
int finalRed = round(sqrt(pow(redSumgx, 2) + pow(redSumgy, 2)));
int finalGreen = round(sqrt(pow(greenSumgx, 2) + pow(greenSumgy, 2)));
int finalBlue = round(sqrt(pow(blueSumgx, 2) + pow(blueSumgy, 2)));
if (finalRed > 255)
{
finalRed = 255;
}
if (finalGreen > 255)
{
finalGreen = 255;
}
if (finalBlue > 255)
{
finalBlue = 255;
}
image[q][w].rgbtRed = finalRed;
image[q][w].rgbtGreen = finalGreen;
image[q][w].rgbtBlue = finalBlue;
}
}
return;
}
I know this code is cancer please don't judge
These arrays
int redEdit[9];
int greenEdit[9];
int blueEdit[9];
have not been initialised and hold arbitrary values. So when you execute statements such as
redEdit[top] += edit[q - 1][w - 1 + top].rgbtRed;
the sum is meaningless. You need
int redEdit[9] = { 0 };
int greenEdit[9] = { 0 };
int blueEdit[9] = { 0 };
Only static variables are implicitly initialised to 0. Local (auto) variables are not.
Below code is to remove overlap among cells residing inside grids.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
//coordinate representation
struct Point
{
double x;
double y;
};
//block representation with 4 coordinates
struct Block
{
unsigned int id;
struct Point bottomLeft, topLeft, bottomRight, topRight;
double width, height;
double whitespace;
};
struct Overlap
{
double overlapLength;
struct Block *b1, *b2;
} OL[1000];
struct Block *b;
struct Block ROW1, ROW2, ROW3;
int comparator(const void *p, const void *q)
{
return (((struct Overlap *)p)->overlapLength -
(((struct Overlap *)q)->overlapLength));
}
//intialise Blocks using bottom left x,y coordinate
void intialiseBlock(struct Block *B)
{
B->topLeft.x = B->bottomLeft.x;
B->topLeft.y = B->height + B->bottomLeft.y;
B->bottomRight.x = B->width + B->bottomLeft.x;
B->bottomRight.y = B->bottomLeft.y;
B->topRight.x = B->width + B->bottomLeft.x;
B->topRight.y = B->height + B->bottomLeft.y;
}
//update coordinate
void move(double xDelta, double yDelta, struct Point *p)
{
// Parameter values are increments to the current coordinates
p->x += xDelta;
p->y += yDelta;
}
//calculate and return distance between 2 points
double distance(const struct Point aPoint, const struct Point bPoint)
{
return sqrt((aPoint.x - bPoint.x) * (aPoint.x - bPoint.x) +
(aPoint.y - bPoint.y) * (aPoint.y - bPoint.y));
}
//generate width of cell using number of cells
double computeCellWidth(int ncell)
{
double width = (0.8 * 400) / ncell;
return width;
}
//create a
unsigned int rand_interval(unsigned int min, unsigned int max)
{
int r;
const unsigned int range = 1 + max - min;
const unsigned int buckets = RAND_MAX / range;
const unsigned int limit = buckets * range;
/* Create equal size buckets all in a row, then fire randomly towards
* the buckets until you land in one of them. All buckets are equally
* likely. If you land off the end of the line of buckets, try again. */
do
{
r = rand();
} while (r >= limit);
return min + (r / buckets);
}
//place blocks in appropriate rows
void placeVertical(struct Block *b, int n, struct Block ROW1, struct Block ROW2,
struct Block ROW3)
{
for (int i = 0; i < n; i++)
{
double distanceFromBottom = 0.0;
double distanceFromTop = 0.0;
// check if Inside Row1 and Row2
if ((b[i].bottomLeft.y < ROW1.topLeft.y) && (b[i].topLeft.y > ROW1.topLeft.y))
{
//printf("ROW1 and ROW2 Executed\n");
distanceFromBottom = ROW1.topLeft.y - b[i].bottomLeft.y;
distanceFromTop = b[i].height - distanceFromBottom;
if (distanceFromBottom > distanceFromTop)
{
move(0, -distanceFromTop, &b[i].bottomLeft);
move(0, -distanceFromTop, &b[i].topLeft);
move(0, -distanceFromTop, &b[i].bottomRight);
move(0, -distanceFromTop, &b[i].topRight);
}
else
{
move(0, distanceFromBottom, &b[i].bottomLeft);
move(0, distanceFromBottom, &b[i].topLeft);
move(0, distanceFromBottom, &b[i].bottomRight);
move(0, distanceFromBottom, &b[i].topRight);
}
}
// check if Inside Row2 and Row3
else if ((b[i].bottomLeft.y < ROW2.topLeft.y) && (b[i].topLeft.y > ROW2.topLeft.y))
{
//System.out.println("ROW2 and ROW3 Executed");
distanceFromBottom = ROW2.topLeft.y - b[i].bottomLeft.y;
distanceFromTop = b[i].height - distanceFromBottom;
if (distanceFromBottom > distanceFromTop)
{
move(0, -distanceFromTop, &b[i].bottomLeft);
move(0, -distanceFromTop, &b[i].topLeft);
move(0, -distanceFromTop, &b[i].bottomRight);
move(0, -distanceFromTop, &b[i].topRight);
}
else
{
move(0, distanceFromBottom, &b[i].bottomLeft);
move(0, distanceFromBottom, &b[i].topLeft);
move(0, distanceFromBottom, &b[i].bottomRight);
move(0, distanceFromBottom, &b[i].topRight);
}
}
else if ((b[i].bottomLeft.y >= ROW1.bottomLeft.y) && (b[i].topLeft.y <= ROW1.topLeft.y))
{
// do nothing in ROW1
}
else if ((b[i].bottomLeft.y >= ROW2.bottomLeft.y) && (b[i].topLeft.y <= ROW2.topLeft.y))
{
// do nothing in ROW2
}
else // ((b[i].bottomLeft.y >=
// ROW2.bottomLeft.y)&&(b[i].topLeft.y <=
// ROW2.topLeft.y))
{
// do nothing in ROW3
}
}
}
//use when floating point operations create run time problems
void linkfloat()
{
float a = 0.0, *x;
x = &a;
a = *x;
}
int findOverlaps(struct Block *b, int n)
{
int k, j, p = 0;
//struct Overlap OL[200];
//short flag = FALSE;
double overlapLength = 0.0;
for (int i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (k == j)
continue;
overlapLength = 0.0;
//for ROW1
if (b[k].bottomLeft.y >= 0 && b[k].topLeft.y <= 100 && b[j].bottomLeft.y >= 0 && b[j].topLeft.y <= 100)
{
//if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
if ((b[k].bottomLeft.y == b[j].bottomLeft.y) && (b[k].bottomRight.x > b[j].bottomLeft.x))
{
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else if (((b[k].topLeft.y > b[j].bottomLeft.y) && (b[k].topRight.x > b[j].bottomLeft.x)) || ((b[k].bottomLeft.y < b[j].topLeft.y) && (b[k].bottomRight.x > b[j].topLeft.x)))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else
{
}
overlapLength = 0.0;
}
//For Row2
else if (b[k].bottomLeft.y >= 100 && b[k].topLeft.y <= 200 && b[j].bottomLeft.y >= 100 && b[j].topLeft.y <= 200)
{
if ((b[k].bottomLeft.y == b[j].bottomLeft.y) && (b[k].bottomRight.x > b[j].bottomLeft.x))
{
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else if (((b[k].topLeft.y > b[j].bottomLeft.y) && (b[k].topRight.x > b[j].bottomLeft.x)) || ((b[k].bottomLeft.y < b[j].topLeft.y) && (b[k].bottomRight.x > b[j].topLeft.x)))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else
{
}
overlapLength = 0.0;
}
//For Row3
else if (b[k].bottomLeft.y >= 200 && b[k].topLeft.y <= 300 && b[j].bottomLeft.y >= 200 && b[j].topLeft.y <= 300)
{
if ((b[k].bottomLeft.y == b[j].bottomLeft.y) && (b[k].bottomRight.x > b[j].bottomLeft.x))
{
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else if (((b[k].topLeft.y > b[j].bottomLeft.y) && (b[k].topRight.x > b[j].bottomLeft.x)) || ((b[k].bottomLeft.y < b[j].topLeft.y) && (b[k].bottomRight.x > b[j].topLeft.x)))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
OL[p].overlapLength = overlapLength;
OL[p].b1 = &b[k];
OL[p].b2 = &b[j];
p++;
}
else
{
}
overlapLength = 0.0;
}
else
{
//do nothing
}
}
}
return p;
}
struct Block *
getBlock(struct Block *b, int n, int id)
{
int i;
for (i = 0; i < n; i++)
{
if (id == b[i].id)
return (b + i);
}
return NULL;
}
void placeHorizontalGreedy(struct Block *b, int n)
{
struct Block *t = NULL;
int p = 0, k = 0;
p = findOverlaps(b, n);
qsort(OL, p, sizeof(struct Overlap), comparator);
while (TRUE)
{
t = getBlock(b, 12, OL[k].b2->id);
if (t != NULL)
{
//t->bottomLeft.x = t->bottomLeft.x+OL[0].overlapLength;
if ((t->bottomLeft.x + OL[0].overlapLength + t->width) <= ROW1.bottomRight.x)
{
move(OL[0].overlapLength, 0, &t->bottomLeft);
intialiseBlock(t);
}
}
p = findOverlaps(b, n);
if (p == 0)
break;
else
qsort(OL, p, sizeof(struct Overlap), comparator);
}
}
void placeHorizontalNonGreedy(struct Block *b, int n, struct Block ROW1,
struct Block ROW2, struct Block ROW3)
{
int k, j, p = 0;
double overlapLength = 0.0;
for (int i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (k == j)
continue;
overlapLength = 0.0;
//check if in Row1
if (b[k].bottomLeft.y >= ROW1.bottomLeft.y && b[k].topLeft.y <= ROW1.topLeft.y && b[j].bottomLeft.y >= ROW1.bottomLeft.y && b[j].topLeft.y <= ROW1.topLeft.y)
{
if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
if (overlapLength != 0)
{
if (b[j].bottomLeft.x + overlapLength + b[j].width <=
ROW1.bottomRight.x)
{
b[j].bottomLeft.x += overlapLength;
intialiseBlock(&b[j]);
}
else
{
b[j].bottomLeft.x =
b[j].bottomLeft.x + (ROW1.bottomRight.x -
b[j].bottomRight.x);
}
}
}
}
//check if in Row2
else if (b[k].bottomLeft.y >= ROW2.bottomLeft.y && b[k].topLeft.y <= ROW2.topLeft.y && b[j].bottomLeft.y >= ROW2.bottomLeft.y && b[j].topLeft.y <= ROW2.topLeft.y)
{
if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
if (overlapLength != 0)
{
if (b[j].bottomLeft.x + overlapLength + b[j].width <=
400)
{
b[j].bottomLeft.x += overlapLength;
intialiseBlock(&b[j]);
}
}
}
}
//check if in Row3
else if (b[k].bottomLeft.y >= ROW3.bottomLeft.y && b[k].topLeft.y <= ROW3.topLeft.y && b[j].bottomLeft.y >= ROW3.bottomLeft.y && b[j].topLeft.y <= ROW3.topLeft.y)
{
if ((b[k].bottomRight.x > b[j].bottomLeft.x) && (b[k].bottomRight.y < b[j].topLeft.y || b[k].topRight.y > b[j].bottomLeft.y))
{
//flag = TRUE;
overlapLength = b[k].bottomRight.x - b[j].bottomLeft.x;
if (overlapLength != 0)
{
if (b[j].bottomLeft.x + overlapLength + b[j].width <=
400)
{
b[j].bottomLeft.x += overlapLength;
intialiseBlock(&b[j]);
}
}
}
}
else
{
//printf("Invalid input\n");
continue;
}
}
}
}
int main()
{
//struct Block b[16];
//struct Block b[4];
//struct Block *b;
//struct Block ROW1, ROW2, ROW3;
//FILE *fp = fopen("/home/jeetu/experimentprograms/recordcoord.txt", "w+");
//FILE *fp = fopen("/home/jeetu/experimentprograms/blockcoordinates.txt", "r");
int ncell = 0, width = 0, i = 0, totalncells = 0, id = 0;
double distanceFromBottom = 0.0;
double distanceFromTop = 0.0;
int x = 0, y = 0, temp = 0, d = 0;
printf("Enter number of cells: ");
scanf("%d", &ncell);
width = computeCellWidth(ncell);
//width = 40;
b = (struct Block *)malloc(3 * ncell * sizeof(struct Block));
//b = (struct Block *)malloc(12 * sizeof(struct Block));
srand(time(0));
ROW1.bottomLeft.x = 0;
ROW1.bottomLeft.y = 0;
ROW1.height = 100;
ROW1.width = 400;
ROW1.whitespace = 40000;
intialiseBlock(&ROW1);
ROW2.bottomLeft.x = 0;
ROW2.bottomLeft.y = 100;
ROW2.height = 100;
ROW2.width = 400;
ROW2.whitespace = 40000;
intialiseBlock(&ROW2);
ROW3.bottomLeft.x = 0;
ROW3.bottomLeft.y = 200;
ROW3.height = 100;
ROW3.width = 400;
ROW3.whitespace = 40000;
intialiseBlock(&ROW3);
for (i = 0; i < ncell; i++)
{
if (i == 0)
{
// x = rand_interval(0, width / 2);
x = rand() % (width / 2);
//y = rand_interval(0, 70);
y = rand() % 70;
temp = x;
}
//m = rand();
else
{
x = rand_interval((temp + (int)width / 2), temp + width);
//x = (rand()%((temp+width)-(temp+width/2)))+(temp+width/2);
//y = rand_interval(0, 70);
y = rand() % 70;
temp = x;
}
b[totalncells].bottomLeft.x = x;
b[totalncells].bottomLeft.y = y;
b[totalncells].width = width;
b[totalncells].height = 50;
b[totalncells].id = id;
//initial white space calculation for ROW1
if (b[totalncells].bottomLeft.y >= ROW1.bottomLeft.y && b[totalncells].topLeft.y <= ROW1.topLeft.y)
{
ROW1.whitespace =
ROW1.whitespace - b[totalncells].width * b[totalncells].height;
}
id++;
intialiseBlock(&b[totalncells]);
totalncells++;
//printf("x=%d\ty=%d\n", x, y);
}
temp = 0;
//Generate random coordinates For Row2
for (i = 0; i < ncell; i++)
{
//int x = 0, y = 0, m = 0, d = 0;
if (i == 0)
{
/*x = rand_interval(0, width / 2);
y = rand_interval(100, 170); */
//x = rand() % (width / 2);
x = rand() % (width / 2);
y = (rand() % (170 - 100)) + 100;
temp = x;
}
//m = rand();
else
{
/*x = rand_interval((temp + (int)width / 2), 400 - (int)width);
y = rand_interval(100, 170); */
//x = (rand()%((temp+width)-(temp+width/2)))+(temp+width/2);
x = rand_interval((temp + (int)width / 2), temp + width);
y = (rand() % (170 - 100)) + 100;
temp = x;
}
b[totalncells].bottomLeft.x = x;
b[totalncells].bottomLeft.y = y;
b[totalncells].width = width;
b[totalncells].height = 50;
b[totalncells].id = id;
//initial white space calculation for ROW2
if (b[totalncells].bottomLeft.y >= ROW2.bottomLeft.y && b[totalncells].topLeft.y <= ROW2.topLeft.y)
{
ROW2.whitespace =
ROW2.whitespace - b[totalncells].width * b[totalncells].height;
}
id++;
intialiseBlock(&b[totalncells]);
totalncells++;
//printf("x=%d\ty=%d\n", x, y);
}
temp = 0;
//Generate random coordinates For Row3
for (i = 0; i < ncell; i++)
{
//int x = rand_interval(0, 100 - (int)width);
//int y = rand_interval(20, 25); //cell height is 5 so max will reach 30
//int x = 0, y = 0, m = 0, d = 0;
if (i == 0)
{
/*x = rand_interval(0, width / 2);
y = rand_interval(200, 250); */
x = rand() % (width / 2);
y = (rand() % (250 - 200)) + 200;
temp = x;
}
//m = rand();
else
{
/*x = rand_interval((temp + (int)width / 2), 400 - (int)width);
y = rand_interval(200, 250); */
x = rand_interval((temp + (int)width / 2), temp + width);
//x = (rand()%((temp+width)-(temp+width/2)))+(temp+width/2);
y = (rand() % (250 - 200)) + 200;
temp = x;
}
b[totalncells].bottomLeft.x = x;
b[totalncells].bottomLeft.y = y;
b[totalncells].width = width;
b[totalncells].height = 50;
b[totalncells].id = id;
//initial white space calculation for ROW3
if (b[totalncells].bottomLeft.y >= ROW3.bottomLeft.y && b[totalncells].topLeft.y <= ROW3.topLeft.y)
{
ROW3.whitespace =
ROW3.whitespace - b[totalncells].width * b[totalncells].height;
}
id++;
intialiseBlock(&b[totalncells]);
totalncells++;
//printf("x=%d\ty=%d\n", x, y);
}
for (i = 0; i < totalncells; i++)
{
//printf("%f %f %f %f\n", b[i].bottomLeft.x, b[i].bottomLeft.y, b[i].width, b[i].height);
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x,
(int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
}
placeVertical(b, totalncells, ROW1, ROW2, ROW3);
//placeVerticalWithDensityConstraints(b,totalncells,ROW1,ROW2,ROW3);
printf("\nAfter vertical Updation\n");
for (i = 0; i < totalncells; i++)
{
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x,
(int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
}
/*placeHorizontalNonGreedy(b, 12, ROW1, ROW2, ROW3);
printf("\nAfter Horizontal Updation(Non greedy)\n");
for (i = 0; i < 12; i++)
{
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x, (int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
} */
placeHorizontalGreedy(b, totalncells);
printf("\nAfter Horizontal Updation(Greedy)\n");
for (i = 0; i < totalncells; i++)
{
printf("%d\t%d\t%d\t%d\n", (int)b[i].bottomLeft.x,
(int)b[i].bottomLeft.y, (int)b[i].width, (int)b[i].height);
}
return 0;
}
Explanation about the code
in this program I have defined three structures
one to represent a Point,one to represent rectangular block with 4 coordinates,one to represent overlap between pair of cells.
There is function(computeCellWidth) to dynamically compute width of cells according to a formula.
There are three rows ROW1,ROW2,ROW3 in which cells will reside.
This program will first ask for number of cells and this is numbers of cells per row.At first x,y coordinates for each cell is randomly generated.Then placeVertical() function will move cells to different rows which are spanning across two rows.Then there is a placeHorizontalGreedy() function which will remove overlap among cells by first finding overlaplength and then sorting them and removing the overlap between cells which has least overlap and this process will continue till either there will be no overlaps or overlap removal is not possible anymore.Here I would like to bring to the notice of everybody that cells will be moved towards the right of the grid to remove overlaps.In placeHorizontalGreedy() function I have used a variable p which will indicate number of overlaps after each iteration.for small number of cells testing for p to be zero works fine but not as I increase the numbers.Plus how can I make sure that overlaps exists but overlap removal is not possible anymore,so that I can stop the loop. Please help me out.
Im trying to make a minesweeper game in c which is compact enough to fit into a qr code, like some other people have done with snake. As it stands, my program needs to be around 2.98 KB and is currently 58KB.
Before I move on to trying to make some compiler magic happen, I wanted to know how could refine my code pre-compiler. Is my approach workable, would it have to be completely different, or is fitting the minesweeper program into that small of a size impossible without using assembly? My code can be seen here:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define WIDTH 100
#define HEIGHT 100
#define BOMBS 799
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
HANDLE wHnd;
HANDLE rHnd;
void SetGrid(int grid[WIDTH][HEIGHT])
{
int bomb[2] = { abs(rand() % WIDTH-1) + 1,
abs(rand() % HEIGHT-1) + 1 };
for (int i = 0; i < BOMBS; i++)
{
while (grid[bomb[0]][bomb[1]] < -1 || bomb[0] == 0 || bomb[1] == 0 || bomb[0] >= WIDTH-1 || bomb[1] >= HEIGHT-1)
{
bomb[0] = abs(rand() % WIDTH-1) + 1;
bomb[1] = abs(rand() % HEIGHT-1) + 1;
}
grid[bomb[0]][bomb[1]] = -9;
grid[bomb[0] + 1][bomb[1] + 1]++;
grid[bomb[0] + 1][bomb[1]]++;
grid[bomb[0]][bomb[1] + 1]++;
grid[bomb[0] - 1][bomb[1] + 1]++;
grid[bomb[0]][bomb[1] - 1]++;
grid[bomb[0] + 1][bomb[1] - 1]++;
grid[bomb[0] - 1][bomb[1] - 1]++;
grid[bomb[0] - 1][bomb[1]]++;
}
}
void ExpandGrid(int fullGrid[WIDTH][HEIGHT], int knownGrid[WIDTH][HEIGHT], int blankPos[2])
{
int neighbors[8][2] = {{0,1}, {1,0}, {1,1},
{0,-1}, {-1,0},
{-1,-1},{-1,1},{1,-1}};
int curTile[2];
knownGrid[blankPos[0]][blankPos[1]] = 1;
if(fullGrid[blankPos[0]][blankPos[1]] != 0) return;
for(int blck = 0; blck < 8; ++blck)
{
curTile[0] = abs(blankPos[0]+neighbors[blck][0]);
curTile[1] = abs(blankPos[1]+neighbors[blck][1]);
if(curTile[0] > WIDTH-1 || curTile[1] > HEIGHT-1) continue;
if(fullGrid[curTile[0]][curTile[1]] == 0 && knownGrid[curTile[0]][curTile[1]] == 0)
{
knownGrid[curTile[0]][curTile[1]] = 1;
ExpandGrid(fullGrid, knownGrid, curTile);
}
else if(fullGrid[curTile[0]][curTile[1]] > 0) knownGrid[curTile[0]][curTile[1]] = 1;
}
}
int main(void)
{
SMALL_RECT windowSize = { 0, 0, WIDTH - 1, HEIGHT - 1 };
COORD characterBufferSize = { WIDTH, HEIGHT };
COORD characterPosition = { 0, 0 };
SMALL_RECT consoleWriteArea = { 0, 0, WIDTH - 1, HEIGHT - 1 };
CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
rHnd = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleTitle("Minesweeper!");
SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
srand((unsigned int)time(NULL));
int startGrid[WIDTH][HEIGHT] = { 0 };
int knownGrid[WIDTH][HEIGHT] = { 0 };
SetGrid(startGrid);
int startCoord[2] = {0, 0};
int arrowPos[2] = {0, 0};
ExpandGrid(startGrid, knownGrid, startCoord);
while(1)
{
if (arrowPos[0] > WIDTH-1) arrowPos[0] = WIDTH-1;
if (arrowPos[0] < 0) arrowPos[0] = 0;
if (arrowPos[1] > HEIGHT-1) arrowPos[1] = HEIGHT-1;
if (arrowPos[1] < 0) arrowPos[1] = 0;
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if (knownGrid[x][y] == 1)
{
if (startGrid[x][y] > 0)
{
consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
}
else
{
consoleBuffer[x][y].Char.AsciiChar = 'o';
consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
}
}
else
{
consoleBuffer[x][y].Char.AsciiChar = 00;
consoleBuffer[x][y].Attributes = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
}
if(arrowPos[0] == x && arrowPos[1] == y)
{
consoleBuffer[x][y].Attributes = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
}
}
}
WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
switch(getch())
{
case KEY_UP:
arrowPos[0]--;
break;
case KEY_DOWN:
arrowPos[0]++;
break;
case KEY_LEFT:
arrowPos[1]--;
break;
case KEY_RIGHT:
arrowPos[1]++;
break;
case '\r':
ExpandGrid(startGrid, knownGrid, arrowPos);
break;
}
}
}
Reducing from 58K to 3K is a pretty big ask.
A few ideas:
Examine the libraries that are linked in during your build process, and reduce those to the bare minimum; Eliminate calls to library functions that you may be able to write yourself.
Possibly use shorter types. Do you need int? Can you use a byte (char) or a short instead?
Consider what parts of windows.h and stdlib.h you really need.
I was coding c in code blocks and wanted to move over to visual studio since it has a tendency to compile programs better, yet for some reason the ascii values that were displaying numbers fine in code blocks eem to be giving me weird results in vs. here's a snippet of what they look like:
Since the code is exactly the same on each platform, this leads me to believe there is some setting I overlooked int vs pertaining to ascii which is already set in code blocks. For review, here is my code:
#include <windows.h>
#define WIDTH 18
#define HEIGHT 18
#define BOMBS 50
struct xorshift_state {
int a;
};
int xorshift(struct xorshift_state *state)
{
int x = state->a;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return state->a = x;
}
void ExpandGrid(int fullGrid[WIDTH][HEIGHT], int knownGrid[WIDTH][HEIGHT], int blankPos[2])
{
int neighbors[8][2] = { { 0,1 },{ 1,0 },{ 1,1 },
{ 0,-1 },{ -1,0 },
{ -1,-1 },{ -1,1 },{ 1,-1 } };
int curTile[2];
knownGrid[blankPos[0]][blankPos[1]] = 1;
if (fullGrid[blankPos[0]][blankPos[1]] != 0) return;
for (int blck = 0; blck < 8; ++blck)
{
curTile[0] = blankPos[0] + neighbors[blck][0];
curTile[1] = blankPos[1] + neighbors[blck][1];
if (curTile[0] > WIDTH - 1 || curTile[1] > HEIGHT - 1 || curTile[0] < 0 || curTile[1] < 0) continue;
if (fullGrid[curTile[0]][curTile[1]] == 0 && knownGrid[curTile[0]][curTile[1]] == 0)
{
knownGrid[curTile[0]][curTile[1]] = 1;
ExpandGrid(fullGrid, knownGrid, curTile);
}
else if (fullGrid[curTile[0]][curTile[1]] > 0) knownGrid[curTile[0]][curTile[1]] = 1;
}
}
int main(int argc, char *argv[])
{
COORD characterBufferSize = { WIDTH, HEIGHT };
COORD characterPosition = { 0, 0 };
SMALL_RECT consoleWriteArea = { 0, 0, WIDTH - 1, HEIGHT - 1 };
CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
HANDLE wHnd = GetStdHandle(-11);
HANDLE rHnd = GetStdHandle(-10);
DWORD numEventsRead = 0;
DWORD numEvents = 0;
INPUT_RECORD *eventBuffer = { 0 };
int wait = 1000;
int startGrid[WIDTH][HEIGHT] = { 0 };
int knownGrid[WIDTH][HEIGHT] = { 0 };
int arrowPos[2] = { 0, 0 };
int bomb[2] = { 0 };
struct xorshift_state seed = { argc == 2 ? (int)argv[1] : 1 };
for (int i = 0; i < BOMBS; i++)
{
while (startGrid[bomb[0]][bomb[1]] < -1 || bomb[0] <= 0 || bomb[1] <= 0 || bomb[0] >= WIDTH - 1 || bomb[1] >= HEIGHT - 1)
{
bomb[0] = (xorshift(&seed) % WIDTH - 1) + 1;
bomb[1] = (xorshift(&seed) % HEIGHT - 1) + 1;
}
startGrid[bomb[0]][bomb[1]] = -9;
startGrid[bomb[0] + 1][bomb[1] + 1]++;
startGrid[bomb[0] + 1][bomb[1]]++;
startGrid[bomb[0]][bomb[1] + 1]++;
startGrid[bomb[0] - 1][bomb[1] + 1]++;
startGrid[bomb[0]][bomb[1] - 1]++;
startGrid[bomb[0] + 1][bomb[1] - 1]++;
startGrid[bomb[0] - 1][bomb[1] - 1]++;
startGrid[bomb[0] - 1][bomb[1]]++;
}
while (1)
{
if (arrowPos[0] > WIDTH - 1) arrowPos[0] = WIDTH - 1;
if (arrowPos[0] < 0) arrowPos[0] = 0;
if (arrowPos[1] > HEIGHT - 1) arrowPos[1] = HEIGHT - 1;
if (arrowPos[1] < 0) arrowPos[1] = 0;
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if (knownGrid[x][y] == 1)
{
if (startGrid[x][y] > 0)
{
consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
}
else
{
consoleBuffer[x][y].Char.AsciiChar = 'o';
consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
}
}
else
{
consoleBuffer[x][y].Char.AsciiChar = '00';
consoleBuffer[x][y].Attributes = 0;
}
if (arrowPos[0] == x && arrowPos[1] == y)
{
consoleBuffer[x][y].Attributes = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
}
}
}
WriteConsoleOutput(wHnd, *consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
numEvents = 0;
numEventsRead = 0;
GetNumberOfConsoleInputEvents(rHnd, &numEvents);
if (numEvents)
{
eventBuffer = malloc(sizeof(INPUT_RECORD) * numEvents);
ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);
}
if (numEventsRead && wait <= 0)
{
wait = 1000;
switch (eventBuffer[0].Event.KeyEvent.wVirtualKeyCode)
{
case 38:
arrowPos[0]--;
break;
case 40:
arrowPos[0]++;
break;
case 37:
arrowPos[1]--;
break;
case 39:
arrowPos[1]++;
break;
case 13:
ExpandGrid(startGrid, knownGrid, arrowPos);
break;
}
}
wait--;
}
}
This does not do what you think it does :
bomb[0] = (xorshift(&seed) % WIDTH - 1) + 1;
From the use of this calculated value right after, you appear to expect this to return a value in the range [1,WIDTH-2].
But :
operator precedence means that (foo % WIDTH - 1) + 1 is the same as ((foo % WIDTH) - 1) + 1. Ie. subtracting 1 is cancelled out by adding 1 again.
left-shifting negative values (as you potentially do in the xorshift function when the seed is/becomes negative) has undefined behavior : ie. anything at all could happen.
right-shifting negative values (as you potentially do in the xorshift function when the seed is/becomes negative) has implementation defined behavior : ie. it could behave differently, depending on the compiler, etc.
modulo operations on negative values are well-defined, and will result in another negative value.
Given all those issues on that one line, I'm not surprised you see strange things happen. Not only have you not properly limited the range of the calculated value, you're also a victim of implementation defined and undefined behavior.
There might well be other issues in the code, but I'd start with these.