#include <stdio.h>
#include <ncurses.h>
#include <stdlib.h>
#include "game.h"
void initializeGame(char **grid, int rows, int cols, FILE *file, int *playerRow, int *playerCol, int *win, int *collision) {
int i, j, val;
*win = 0;
*collision = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (fscanf(file, "%d", &val) != 1) {
exit(EXIT_FAILURE);
}
switch (val) {
case 0:
grid[i][j] = EMPTY_SPACE;
break;
case 1:
grid[i][j] = ROAD;
break;
case 2:
grid[i][j] = CAR_RIGHT;
break;
case 3:
grid[i][j] = PLAYER;
*playerRow = i;
*playerCol = j;
break;
case 4:
grid[i][j] = GOAL;
break;
case 5:
grid[i][j] = CAR_LEFT;
break;
case 6:
grid[i][j] = CAR_UP;
break;
case 7:
grid[i][j] = CAR_DOWN;
break;
}
}
}
for (i = 0; i < rows; i++) {
grid[i][0] = BORDER;
grid[i][cols - 1] = BORDER;
}
for (j = 0; j < cols; j++) {
grid[0][j] = BORDER;
grid[rows - 1][j] = BORDER;
}
}
void displayGame(char **grid, int rows, int cols) {
int i, j;
clear();
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
move(i, j);
printw("%c", grid[i][j]);
}
}
mvprintw(rows, 0, "Press 'w' to move up");
mvprintw(rows + 1, 0, "Press 'a' to move left");
mvprintw(rows + 2, 0, "Press 's' to move down");
mvprintw(rows + 3, 0, "Press 'd' to move right");
refresh();
}
void moveCars(char **grid, int rows, int cols) {
int i, j, nextI, nextJ;
char direction, nextDirection;
char **tempGrid = (char **)malloc(rows * sizeof(char *));
for (i = 0; i < rows; i++) {
tempGrid[i] = (char *)malloc(cols * sizeof(char));
for (j = 0; j < cols; j++) {
tempGrid[i][j] = grid[i][j];
}
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
direction = grid[i][j];
nextI = i;
nextJ = j;
nextDirection = direction;
if (direction == CAR_RIGHT && j + 1 < cols && grid[i][j + 1] == ROAD) {
nextJ++;
} else if (direction == CAR_LEFT && j - 1 >= 0 && grid[i][j - 1] == ROAD) {
nextJ--;
} else if (direction == CAR_UP && i - 1 >= 0 && grid[i - 1][j] == ROAD) {
nextI--;
} else if (direction == CAR_DOWN && i + 1 < rows && grid[i + 1][j] == ROAD) {
nextI++;
}
if (nextI != i || nextJ != j) {
tempGrid[nextI][nextJ] = nextDirection;
tempGrid[i][j] = (grid[i][j] == PLAYER) ? PLAYER : ROAD;
}
}
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
grid[i][j] = tempGrid[i][j];
}
free(tempGrid[i]);
}
free(tempGrid);
}
int collision = 0;
void movePlayer(char **grid, int rows, int cols, char move, int *win, int *playerRow, int *playerCol, int *collision) {
int newPlayerRow = *playerRow;
int newPlayerCol = *playerCol;
switch (move) {
case 'w': newPlayerRow -= (newPlayerRow > 0) ? 1 : 0; break;
case 'a': newPlayerCol -= (newPlayerCol > 0) ? 1 : 0; break;
case 's': newPlayerRow += (newPlayerRow < rows - 1) ? 1 : 0; break;
case 'd': newPlayerCol += (newPlayerCol < cols - 1) ? 1 : 0; break;
}
if (newPlayerRow >= 0 && newPlayerRow < rows && newPlayerCol >= 0 && newPlayerCol < cols) {
if (grid[newPlayerRow][newPlayerCol] == EMPTY_SPACE || grid[newPlayerRow][newPlayerCol] == ROAD) {
grid[*playerRow][*playerCol] = EMPTY_SPACE;
*playerRow = newPlayerRow;
*playerCol = newPlayerCol;
grid[newPlayerRow][newPlayerCol] = PLAYER;
*collision = 0;
} else if (grid[newPlayerRow][newPlayerCol] == GOAL) {
*win = 1;
} else {
*collision = 1;
}
} else {
*collision = 1;
}
}
#include "game.h"
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *file;
int mapRows, mapCols;
char **gameGrid;
int move;
int win = 0, collision = 0;
int playerRow = -1, playerCol = -1;
int i;
if (argc != 2) {
printf("Usage: %s <config_file>\n", argv[0]);
return 1;
}
file = fopen(argv[1], "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
if (fscanf(file, "%d %d", &mapRows, &mapCols) != 2) {
printf("Invalid file format. The first line must contain two integers.\n");
fclose(file);
return 1;
}
if (mapRows < 3 || mapCols < 5) {
printf("Invalid map size. Please ensure <map_row> is >= 3 and <map_col> is >= 5.\n");
fclose(file);
return 1;
}
gameGrid = (char **)malloc(mapRows * sizeof(char *));
if (!gameGrid) {
fprintf(stderr, "Memory allocation failed for gameGrid.\n");
return 1;
}
for (i = 0; i < mapRows; i++) {
gameGrid[i] = (char *)malloc(mapCols * sizeof(char));
if (!gameGrid[i]) {
fprintf(stderr, "Memory allocation failed for gameGrid row %d.\n", i);
while (--i >= 0) {
free(gameGrid[i]);
}
free(gameGrid);
return 1;
}
}
initializeGame(gameGrid, mapRows, mapCols, file, &playerRow, &playerCol, &win, &collision);
fclose(file);
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
curs_set(0);
do {
displayGame(gameGrid, mapRows, mapCols);
move = getch();
if (move == 'w' || move == 'a' || move == 's' || move == 'd') {
movePlayer(gameGrid, mapRows, mapCols, move, &win, &playerRow, &playerCol, &collision);
moveCars(gameGrid, mapRows, mapCols);
displayGame(gameGrid, mapRows, mapCols);
}
collision = 0;
if (collision) {
clear();
printw("You have failed to clear the level.\nPress any key to exit.\n");
refresh();
getch();
break;
} else if (win) {
clear();
printw("Congratulations! You have cleared the level.\nPress any key to exit.\n");
refresh();
getch();
break;
}
napms(100);
} while (move != 'q');
endwin();
for (i = 0; i < mapRows; i++) {
free(gameGrid[i]);
}
free(gameGrid);
return 0;
}
#ifndef GAME_H
#define GAME_H
#include <stdio.h>
#define CAR_LEFT '<' /* Define symbol for car facing left */
#define CAR_RIGHT '>' /* Define symbol for car initially facing east and for general rightward movement */
#define CAR_UP '^' /* Define symbol for car facing upwards */
#define CAR_DOWN 'V' /* Define symbol for car facing downwards */
#define EMPTY_SPACE ' ' /* Symbol for empty space */
#define ROAD '.' /* Symbol for road */
#define PLAYER 'P' /* Symbol for player */
#define GOAL 'G' /* Symbol for goal */
#define BORDER '*' /* Symbol to represent the border */
void initializeGame(char **grid, int rows, int cols, FILE *file, int *playerRow, int *playerCol, int *win, int *collision);
void displayGame(char **grid, int rows, int cols);
void moveCars(char **grid, int rows, int cols);
void movePlayer(char **grid, int rows, int cols, char move, int *win, int *playerRow, int *playerCol, int *collision);
#endif /* GAME_H */
Configuration file:
10 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 1 1 1 1 0 0
0 0 1 0 0 1 0 0 0 1 0 0 1 0 0
0 0 1 0 0 1 1 1 1 1 1 1 1 0 0
0 0 1 0 0 0 0 0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0 4 1 0 0 0 0 0
0 0 1 1 1 1 1 2 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The first two integers represent the dimensions of the grid
0 represent the grid borders and empty spaces
1 represents the road path
2 represents the car
3 represents the player
4 represents the goal
What I have tried:
I'm working on a simple grid-based game in C where a player navigates through roads, avoiding cars that move along predetermined paths. I've implemented basic movement for the player and static car placement, but I'm struggling with two specific issues:
Making the car move: The car should move one step in its facing direction each time the player moves, following the road ('.'). Initially, the car faces east ('>'), but it needs to turn and follow the road's path, changing direction smoothly.
Implementing turns for the car: When the car reaches a turn or an intersection, it should choose the correct direction to continue following the road. The car's direction should be visually indicated (east '>', west '<', north '^', south 'v').
I am also facing the issue where the road disappears when the player moves through it.