-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
215 lines (178 loc) · 5.78 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include <stdio.h>
#include <stdlib.h>
#include <conio.h> // for getch() in Windows, or use ncurses for Unix-like systems
#include <time.h>
#include <ctype.h>
// Define constants for grid dimensions and game states
#define GRID_SIZE_X 10
#define GRID_SIZE_Y 10
#define IRON 'I'
#define ENEMY 'E'
#define PLAYER 'X'
#define PLAYER_START_X 4
#define PLAYER_START_Y 4
//Adjust as needed
#define TARGET_SCORE 10
#define IRON_AMT 12
#define ENEMY_AMT 8
// Function to initialize the game grid
char** initializeGrid(int width, int height);
// Function to randomly scatter iron and enemies on the grid
void scatterObjects(char** grid);
// Function to display the game grid & state
void renderGrid(char** grid, int gridScore);
// Function to move the player and update game state
void movePlayer(char** grid, int* playerX, int* playerY, int* playerScore);
// Function to check for game over conditions
int isGameOver(int score);
int main() {
char** grid = initializeGrid(GRID_SIZE_X, GRID_SIZE_Y);
int playerX = PLAYER_START_X;
int playerY = PLAYER_START_Y;
int score = 0;
// Seed the random number generator
srand(time(NULL));
scatterObjects(grid);
while (isGameOver(score)) {
printf("\e[2J\e[H"); //clear the screen
renderGrid(grid, score);
movePlayer(grid, &playerX, &playerY, &score);
}
// Clean up memory
for (int i = 0; i < GRID_SIZE_X; i++) {
free(grid[i]);
}
free(grid);
return 0;
}
// Function to initialize the game grid
char** initializeGrid(int width, int height) {
// Allocate memory for the grid
// Note: Using sizeof(char) for easy type flexibility if needed later.
// Since sizeof(char) is 1, could be omitted for minor efficiency.
char** grid = (char**)malloc(width * sizeof(char*));
if (grid == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE); // Handle allocation failure
}
for (int row = 0; row < width; row++) {
grid[row] = (char*)malloc((height + 1) * sizeof(char)); // +1 for the null terminator
if (grid[row] == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE); // Handle allocation failure
}
}
// Initialize the grid elements as blank spaces
for (int row = 0; row < width; row++) {
for (int column = 0; column < height; column++) {
*(grid[row] + column) = ' ';
}
}
// Player starts in the middle
grid[PLAYER_START_Y][PLAYER_START_X] = 'P';
return grid;
}
// Function to randomly scatter iron and enemies on the grid
void scatterObjects(char** grid)
{
// Scatter Iron ('I') on the grid
for(int ironLoop = 0; ironLoop < IRON_AMT; ironLoop++)
{
// Generate random coordinates within the grid
int x, y;
do {
x = rand() % GRID_SIZE_X;
y = rand() % GRID_SIZE_Y;
} while (grid[y][x] != ' ');
// Ensure the cell is empty, add iron
grid[y][x] = IRON;
}
// Scatter Enemies ('E') on the grid
for(int enemyLoop = 0; enemyLoop < ENEMY_AMT; enemyLoop++)
{
// Generate random coordinates within the grid
int x, y;
do {
x = rand() % GRID_SIZE_X;
y = rand() % GRID_SIZE_Y;
} while (grid[y][x] != ' ');
// Ensure the cell is empty, add enemy
grid[y][x] = ENEMY;
}
}
// Function to display the game grid & state
void renderGrid(char** grid, int gridScore) {
printf("H E A V Y I R O N !\n"); // Title
// Grid
for (int row = 0; row < GRID_SIZE_X; row++) {
for (int column = 0; column < GRID_SIZE_Y; column++) {
printf("%c ", *(grid[row] + column * sizeof(char)));
}
puts(""); // End of row
}
printf("Score: %d out of %d\n", gridScore, TARGET_SCORE); // Score
}
// Function to move the player and update game state
void movePlayer(char** grid, int* playerX, int* playerY, int* playerScore) {
//get input
printf("Enter a direction (W/A/S/D): ");
char moveDirection = getchar();
while (getchar() != '\n'); // Clear input buffer
moveDirection = tolower(moveDirection); //from ctype.h, allows upper or lower input
//Save current pos for clearing after boundary check
int oldX = *playerX;
int oldY = *playerY;
// Calculate the new position based on the input
switch (moveDirection)
{
case 'w':
(*playerY)--;
break;
case 'a':
(*playerX)--;
break;
case 's':
(*playerY)++;
break;
case 'd':
(*playerX)++;
break;
default:
printf("Invalid input. Please enter W, A, S, or D.\n");
break;
}
// Check if the new position is within the bounds of the grid
if(0 <= *playerX && *playerX < GRID_SIZE_X && 0 <= *playerY && *playerY < GRID_SIZE_Y)
{
// Check what's in the new position
char foundSomething = grid[*playerY][*playerX];
// Player collects iron
if(foundSomething == 'I')
(*playerScore)++;
// Player encounters an enemy (game over)
if(foundSomething == 'E')
{
printf("The enemy got you! GAME OVER\n");
exit(0);
}
// Update the grid and player's position
grid[oldY][oldX] = ' ';
grid[*playerY][*playerX] = 'P';
}
// Player tried to move out of bounds
else
{
*playerX = oldX;
*playerY = oldY;
}
}
// Function to check for game over conditions
int isGameOver(int score)
{
if (score < TARGET_SCORE) return 1;
else
{
printf("YOU WIN! Thanks for playing Heavy Iron Quest!");
return 0;
}
}