refresh
This commit is contained in:
parent
7ea4fe4500
commit
eb14c451e1
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra -std=c99
|
CFLAGS = -Wall -Wextra -std=c99
|
||||||
dIRS = a1 du1 du2 du3 du4 du5
|
dIRS = a1 du1 du2 du3 du4 du5 a3
|
||||||
all:
|
all:
|
||||||
@for %%d in ($(dIRS)) do \
|
@for %%d in ($(dIRS)) do \
|
||||||
$(CC) $(CFLAGS) %%d\program.c -o %%d\program.exe
|
$(CC) $(CFLAGS) %%d\program.c -o %%d\program.exe
|
||||||
|
19
a3/Makefile
Normal file
19
a3/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -std=c99
|
||||||
|
|
||||||
|
OBJS = main.o snake.o world.o
|
||||||
|
|
||||||
|
snake: $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) -o snake $(OBJS)
|
||||||
|
|
||||||
|
main.o: main.c snake.h world.h
|
||||||
|
$(CC) $(CFLAGS) -c main.c
|
||||||
|
|
||||||
|
snake.o: snake.c snake.h
|
||||||
|
$(CC) $(CFLAGS) -c snake.c
|
||||||
|
|
||||||
|
world.o: world.c world.h snake.h
|
||||||
|
$(CC) $(CFLAGS) -c world.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
del *.o *.exe
|
42
a3/main.c
Normal file
42
a3/main.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "snake.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct state game_state;
|
||||||
|
|
||||||
|
setup_world(&game_state, 20, 10);
|
||||||
|
draw_world(&game_state);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
char command = read_input();
|
||||||
|
|
||||||
|
change_direction(&game_state, command);
|
||||||
|
|
||||||
|
int outcome = step_state(&game_state);
|
||||||
|
draw_world(&game_state);
|
||||||
|
|
||||||
|
if (outcome != END_CONTINUE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(1000);
|
||||||
|
#else
|
||||||
|
sleep(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
free_snake(game_state.snake);
|
||||||
|
printf("\n--- KONIEC HRY ---\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
110
a3/snake.c
Normal file
110
a3/snake.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "snake.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct snake* add_snake (struct snake* snake, int x, int y) {
|
||||||
|
struct snake* head = NULL;
|
||||||
|
|
||||||
|
head = malloc(sizeof(struct snake));
|
||||||
|
|
||||||
|
if (!head) {
|
||||||
|
return snake;
|
||||||
|
}
|
||||||
|
head->x = x;
|
||||||
|
head->y = y;
|
||||||
|
|
||||||
|
head->next = NULL;
|
||||||
|
|
||||||
|
if (snake !=NULL) {
|
||||||
|
head->next = snake;
|
||||||
|
}
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct snake* remove_snake(struct snake* snake) {
|
||||||
|
if (snake == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snake->next == NULL) {
|
||||||
|
free(snake);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct snake* temp = snake;
|
||||||
|
while (temp->next->next != NULL) {
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(temp->next);
|
||||||
|
temp->next = NULL;
|
||||||
|
|
||||||
|
return snake;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_snake(struct snake* sn) {
|
||||||
|
struct snake* walker = sn;
|
||||||
|
struct snake* next_part = NULL;
|
||||||
|
while (walker !=NULL) {
|
||||||
|
next_part = walker->next;
|
||||||
|
free(walker);
|
||||||
|
walker = next_part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_snake(struct snake* snake, int x, int y) {
|
||||||
|
struct snake* current = snake;
|
||||||
|
|
||||||
|
while (current !=NULL) {
|
||||||
|
if ((current->x==x) && (current->y==y)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int step_state(struct state* state) {
|
||||||
|
int x = state->snake->x + state->sx;
|
||||||
|
int y = state->snake->y + state->sy;
|
||||||
|
|
||||||
|
if (x < 0) return END_WALL;
|
||||||
|
if (x >= state->width) return END_WALL;
|
||||||
|
if (y < 0) return END_WALL;
|
||||||
|
if (y >= state->height) return END_WALL;
|
||||||
|
|
||||||
|
if (is_snake(state->snake, x, y)) {
|
||||||
|
return END_SNAKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int food_found = -1;
|
||||||
|
for (int idx = 0; idx < FOOD_COUNT; idx++) {
|
||||||
|
if (state->foodx[idx] == x && state->foody[idx] == y) {
|
||||||
|
food_found = idx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (food_found != -1) {
|
||||||
|
state->foodx[food_found] = -1;
|
||||||
|
state->foody[food_found] = -1;
|
||||||
|
state->snake = add_snake(state->snake, x, y);
|
||||||
|
|
||||||
|
int remaining = 0;
|
||||||
|
for (int k = 0; k < FOOD_COUNT; ++k) {
|
||||||
|
remaining += (state->foodx[k] >= 0 && state->foody[k] >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remaining == 0) {
|
||||||
|
return END_FOOD;
|
||||||
|
}
|
||||||
|
return END_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->snake = add_snake(state->snake, x, y);
|
||||||
|
state->snake = remove_snake(state->snake);
|
||||||
|
|
||||||
|
return END_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
BIN
a3/snake.exe
Normal file
BIN
a3/snake.exe
Normal file
Binary file not shown.
111
a3/snake.h
Normal file
111
a3/snake.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#ifndef snake_h_INCLUDED
|
||||||
|
#define snake_h_INCLUDED
|
||||||
|
|
||||||
|
// Number of food items on the plane
|
||||||
|
#define FOOD_COUNT 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One part of the snake;
|
||||||
|
*
|
||||||
|
* The snake is a linked list;
|
||||||
|
*/
|
||||||
|
struct snake {
|
||||||
|
// x position of the snake part
|
||||||
|
int x;
|
||||||
|
// y position of the snake part
|
||||||
|
int y;
|
||||||
|
// Pointer to the next snake part.
|
||||||
|
// The last part of the snake has NULL pointer to the next part.
|
||||||
|
struct snake* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// End game reason constants, return value of step_state
|
||||||
|
enum endgame {
|
||||||
|
// Continue the game
|
||||||
|
END_CONTINUE = 0,
|
||||||
|
// Snake hit a wall
|
||||||
|
END_WALL,
|
||||||
|
// Snake hit itself
|
||||||
|
END_SNAKE,
|
||||||
|
// No food left
|
||||||
|
END_FOOD,
|
||||||
|
// Other reason to end
|
||||||
|
END_USER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of the game.
|
||||||
|
*
|
||||||
|
* The state consists of the snake, its speed and food on the plane.
|
||||||
|
*
|
||||||
|
* The snake is a linked list of snake parts.
|
||||||
|
*
|
||||||
|
* Speed vector is a vector added to the last head position to create a new head.
|
||||||
|
*
|
||||||
|
* Food are points on the plane. Food with negative coordinates means food is already eaten.
|
||||||
|
*/
|
||||||
|
struct state {
|
||||||
|
// Snake as a linked list
|
||||||
|
struct snake* snake;
|
||||||
|
// X of the food positions
|
||||||
|
int foodx[FOOD_COUNT];
|
||||||
|
// Y of the food positions
|
||||||
|
int foody[FOOD_COUNT];
|
||||||
|
int sx;
|
||||||
|
int sy;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new snake part with given position. The new snake part becomes the new head.
|
||||||
|
*
|
||||||
|
* @param head of the snake.
|
||||||
|
* @param x coordinate of the new head;
|
||||||
|
* @param y coordinate of the new head.
|
||||||
|
* @return new head of the snake.
|
||||||
|
*/
|
||||||
|
struct snake* add_snake(struct snake* snake, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the last snake part.
|
||||||
|
* The last snake part should always have NULL next pointer.
|
||||||
|
*
|
||||||
|
* @param head of the snake.
|
||||||
|
* @return new head of the snake.
|
||||||
|
*/
|
||||||
|
struct snake* remove_snake(struct snake* snake);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds out if given coordinates are part of the snake.
|
||||||
|
* @param snake
|
||||||
|
* @param x coordinate to search in snake
|
||||||
|
* @param y coordinate to search in snake
|
||||||
|
* @return True, if there is a snake part with coordinates x,y. False otherwise
|
||||||
|
*/
|
||||||
|
int is_snake(struct snake* snake, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove and free each snake part;
|
||||||
|
* @param head of the snake.
|
||||||
|
*/
|
||||||
|
void free_snake(struct snake* sn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change game state.
|
||||||
|
*
|
||||||
|
* The function should calculate new position of the snake head
|
||||||
|
* from the current position and speed vector.
|
||||||
|
* Then it should modify snake parts or food coordinates according to the rules:
|
||||||
|
*
|
||||||
|
* - If the new position is on the snake, end the game, return END_SNAKE.
|
||||||
|
* - If the new position is on the food, mark food as eaten
|
||||||
|
* (set its coordinates to -1) and add new snake part on the position of the food. If there is no food left, return END_FOOD. Else return END_CONTINUE.
|
||||||
|
* - If the new position is on the plane, add new snake part on the new position and remove the last part of the snake, return END_CONTINUE.
|
||||||
|
*
|
||||||
|
* @param current state of the game
|
||||||
|
* @return reason to end the game according to enum endgame.
|
||||||
|
*/
|
||||||
|
int step_state(struct state* state);
|
||||||
|
|
||||||
|
#endif // snake_h_INCLUDED
|
BIN
a3/snake.o
Normal file
BIN
a3/snake.o
Normal file
Binary file not shown.
109
a3/world.c
Normal file
109
a3/world.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "world.h"
|
||||||
|
#include "snake.h"
|
||||||
|
|
||||||
|
static void place_food(struct state* s) {
|
||||||
|
int placed = 0;
|
||||||
|
|
||||||
|
while (placed < FOOD_COUNT) {
|
||||||
|
int fx = rand() % s->width;
|
||||||
|
int fy = rand() % s->height;
|
||||||
|
|
||||||
|
if (!is_snake(s->snake, fx, fy)) {
|
||||||
|
s->foodx[placed] = fx;
|
||||||
|
s->foody[placed] = fy;
|
||||||
|
placed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_world(struct state* s, int w, int h) {
|
||||||
|
if (!s) return;
|
||||||
|
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
s->width = w;
|
||||||
|
s->height = h;
|
||||||
|
|
||||||
|
s->sx = 1;
|
||||||
|
s->sy = 0;
|
||||||
|
|
||||||
|
s->snake = NULL;
|
||||||
|
int start_x = w / 2;
|
||||||
|
int start_y = h / 2;
|
||||||
|
|
||||||
|
s->snake = add_snake(s->snake, start_x, start_y);
|
||||||
|
|
||||||
|
place_food(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_world(const struct state* s) {
|
||||||
|
if (!s) return;
|
||||||
|
|
||||||
|
system("clear"); // или "cls" на Windows
|
||||||
|
|
||||||
|
for (int row = 0; row < s->height; row++) {
|
||||||
|
for (int col = 0; col < s->width; col++) {
|
||||||
|
int drawn = 0;
|
||||||
|
|
||||||
|
if (is_snake(s->snake, col, row)) {
|
||||||
|
putchar('O');
|
||||||
|
drawn = 1;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < FOOD_COUNT; ++i) {
|
||||||
|
if (s->foodx[i] == col && s->foody[i] == row) {
|
||||||
|
putchar('*');
|
||||||
|
drawn = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drawn) {
|
||||||
|
putchar('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char read_input(void) {
|
||||||
|
char key = 0;
|
||||||
|
|
||||||
|
printf("Zadaj smer (WASD): ");
|
||||||
|
scanf(" %c", &key);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void change_direction(struct state* s, char key) {
|
||||||
|
if (!s) return;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
s->sx = 0;
|
||||||
|
s->sy = -1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
s->sx = 0;
|
||||||
|
s->sy = 1;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
s->sx = -1;
|
||||||
|
s->sy = 0;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
s->sx = 1;
|
||||||
|
s->sy = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// ничего не делаем при некорректном вводе
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
11
a3/world.h
Normal file
11
a3/world.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef WORLD_MODULE_H
|
||||||
|
#define WORLD_MODULE_H
|
||||||
|
|
||||||
|
#include "snake.h"
|
||||||
|
|
||||||
|
void setup_world(struct state* s, int w, int h);
|
||||||
|
void draw_world(const struct state* s);
|
||||||
|
char read_input(void);
|
||||||
|
void change_direction(struct state* s, char key);
|
||||||
|
|
||||||
|
#endif
|
BIN
a3/world.o
Normal file
BIN
a3/world.o
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user