Browse Source
Merge branch 'David' into 'main'
Merge branch 'David' into 'main'
Finished Snake See merge request pmuw_projekt/pmuw_projekt_notebinder!15remotes/origin/fdai7775-main-patch-54732
fdai8032
11 months ago
8 changed files with 458 additions and 2 deletions
-
58src/main/c/Snake/get_character.c
-
6src/main/c/Snake/get_character.h
-
201src/main/c/Snake/snake_start.c
-
22src/main/c/Snake/snake_start.h
-
5src/main/c/main.c
-
50test/Snake/test_collision.c
-
69test/Snake/test_moving_snake.c
-
49test/Snake/test_part_of_snake.c
@ -0,0 +1,58 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <unistd.h> |
||||
|
#include <sys/select.h> |
||||
|
#include <termios.h> |
||||
|
#include <time.h> |
||||
|
|
||||
|
struct termios orig_termios; |
||||
|
|
||||
|
void reset_terminal_mode(){ |
||||
|
tcsetattr(0, TCSANOW, &orig_termios); |
||||
|
} |
||||
|
|
||||
|
void set_conio_terminal_mode(){ |
||||
|
struct termios new_termios; |
||||
|
|
||||
|
/* take two copies - one for now, one for later */ |
||||
|
tcgetattr(0, &orig_termios); |
||||
|
memcpy(&new_termios, &orig_termios, sizeof(new_termios)); |
||||
|
|
||||
|
/* register cleanup handler, and set the new terminal mode */ |
||||
|
atexit(reset_terminal_mode); |
||||
|
cfmakeraw(&new_termios); |
||||
|
tcsetattr(0, TCSANOW, &new_termios); |
||||
|
} |
||||
|
|
||||
|
int kbhit(){ |
||||
|
struct timeval tv = { 0L, 0L }; |
||||
|
fd_set fds; |
||||
|
FD_ZERO(&fds); |
||||
|
FD_SET(0, &fds); |
||||
|
return select(1, &fds, NULL, NULL, &tv) > 0; |
||||
|
} |
||||
|
|
||||
|
int getch(){ |
||||
|
int r; |
||||
|
unsigned char c; |
||||
|
if ((r = read(0, &c, sizeof(c))) < 0) { |
||||
|
return r; |
||||
|
} else { |
||||
|
return c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
char get_character(double limit){ |
||||
|
set_conio_terminal_mode(); |
||||
|
|
||||
|
clock_t t = clock(); |
||||
|
char c = 0; |
||||
|
|
||||
|
while ((double)(clock() - t) / CLOCKS_PER_SEC < limit){ |
||||
|
if(kbhit()){c = getch();} |
||||
|
} |
||||
|
|
||||
|
reset_terminal_mode(); |
||||
|
|
||||
|
return c; |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
#ifndef GET_CHARACTER_H |
||||
|
#define GET_CHARACTER_H |
||||
|
|
||||
|
char get_character(double limit); |
||||
|
|
||||
|
#endif // GET_CHARACTER_H |
@ -0,0 +1,201 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdbool.h> |
||||
|
#include <time.h> |
||||
|
#include <unistd.h> |
||||
|
#include <stdlib.h> |
||||
|
#include "snake_start.h" |
||||
|
#include "get_character.h" |
||||
|
#define TURN 0.5 |
||||
|
#define START_LENGTH 3 |
||||
|
#define START_DIRECTION 1 |
||||
|
#define START_TILE 8 * 16 + 8 |
||||
|
|
||||
|
#pragma region Funktion_heads |
||||
|
void main_menu(); |
||||
|
void game(); |
||||
|
void options(); |
||||
|
Snake initialize_snake(); |
||||
|
void get_next_move(double limit, Snake *snake, bool *running); |
||||
|
void move_snake(Snake *snake); |
||||
|
void draw(Snake *snake, unsigned char fruit); |
||||
|
int part_of_snake(Snake *snake, unsigned char tile); |
||||
|
bool check_if_dead(Snake *snake); |
||||
|
unsigned char spawn_fruit(Snake *snake); |
||||
|
unsigned char eating_fruit(Snake *snake); |
||||
|
#pragma endregion |
||||
|
|
||||
|
#pragma region Global |
||||
|
double TIME_TURN = 0.5; |
||||
|
#pragma endregion //Global |
||||
|
|
||||
|
void snake_start(){ |
||||
|
system("clear"); |
||||
|
main_menu(); |
||||
|
} |
||||
|
|
||||
|
void main_menu(){ |
||||
|
bool running = true; |
||||
|
while (running){ |
||||
|
int option = 0; |
||||
|
|
||||
|
system("clear"); |
||||
|
printf("Waehlen Sie eine Option:\n"); |
||||
|
printf("\t1.Start\n"); |
||||
|
printf("\t2.Options\n"); |
||||
|
printf("\t3.Exit\n"); |
||||
|
|
||||
|
scanf("%d", &option); |
||||
|
getchar(); |
||||
|
|
||||
|
system("clear"); |
||||
|
|
||||
|
switch (option){ |
||||
|
case 1: |
||||
|
game(); |
||||
|
break; |
||||
|
case 2: |
||||
|
options(); |
||||
|
break; |
||||
|
case 3: |
||||
|
running = false; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void game(){ |
||||
|
Snake snake = initialize_snake(); |
||||
|
bool running = true; |
||||
|
clock_t t = clock(); |
||||
|
unsigned char fruit = spawn_fruit(&snake); |
||||
|
|
||||
|
while (running){ |
||||
|
system("clear"); |
||||
|
draw(&snake, fruit); |
||||
|
if(check_if_dead(&snake)){break;} |
||||
|
t = clock() - t; |
||||
|
get_next_move(TIME_TURN - (double)t / CLOCKS_PER_SEC, &snake, &running); |
||||
|
t = clock(); |
||||
|
move_snake(&snake); |
||||
|
if(part_of_snake(&snake, fruit) == 0){fruit = eating_fruit(&snake);} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void options(){ |
||||
|
int difficulty = 1; |
||||
|
system("clear"); |
||||
|
printf("Please select a difficulty(1 - 10): "); |
||||
|
scanf("%d", &difficulty); |
||||
|
TIME_TURN = TURN / difficulty;//(11 - difficulty) * TURN / 10; |
||||
|
} |
||||
|
|
||||
|
Snake initialize_snake(){ |
||||
|
Snake snake; |
||||
|
snake.direction = START_DIRECTION; |
||||
|
snake.length = START_LENGTH; |
||||
|
for(int i = 0; i < START_LENGTH; i++){ |
||||
|
snake.segments[i] = START_TILE - START_DIRECTION * i; |
||||
|
} |
||||
|
return snake; |
||||
|
} |
||||
|
|
||||
|
void get_next_move(double limit, Snake *snake, bool *running){ |
||||
|
char c; |
||||
|
|
||||
|
c = get_character(limit); |
||||
|
|
||||
|
switch (c){ |
||||
|
case 'w': |
||||
|
case 'A': |
||||
|
snake->direction = -16; |
||||
|
break; |
||||
|
case 'a': |
||||
|
case 'D': |
||||
|
snake->direction = -1; |
||||
|
break; |
||||
|
case 's': |
||||
|
case 'B': |
||||
|
snake->direction = 16; |
||||
|
break; |
||||
|
case 'd': |
||||
|
case 'C': |
||||
|
snake->direction = 1; |
||||
|
break; |
||||
|
case 'q': |
||||
|
*running = false; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void move_snake(Snake *snake){ |
||||
|
for(int i = snake->length - 1; i > 0; i--){ |
||||
|
snake->segments[i] = snake->segments[i - 1]; |
||||
|
} |
||||
|
snake->segments[0] += snake->direction; |
||||
|
} |
||||
|
|
||||
|
void draw(Snake *snake, unsigned char fruit){ |
||||
|
printf("Score:%d Speed:%f\n", snake->length - START_LENGTH, TIME_TURN); |
||||
|
printf("+"); |
||||
|
for(int i = 0; i < WIDTH; i++){printf("-");} |
||||
|
printf("+\n"); |
||||
|
for(int i = 1; i <= HEIGHT; i++){ |
||||
|
printf("|"); |
||||
|
for(int j = 1; j <= WIDTH; j++){ |
||||
|
int index = part_of_snake(snake, i * 16 + j); |
||||
|
if(index == 0){printf("0");} |
||||
|
else if(index > 0){printf("O");} |
||||
|
else if(i * 16 + j == fruit){printf("X");} |
||||
|
else{printf(" ");} |
||||
|
} |
||||
|
printf("|\n"); |
||||
|
} |
||||
|
printf("+"); |
||||
|
for(int i = 0; i < WIDTH; i++){printf("-");} |
||||
|
printf("+\n"); |
||||
|
printf("(Press q to Quit)\n"); |
||||
|
} |
||||
|
|
||||
|
//returns index of segments which is identical to tile; -1 if not found |
||||
|
int part_of_snake(Snake *snake, unsigned char tile){ |
||||
|
for(int i = snake->length - 1; i >= 0; i--){ |
||||
|
if(snake->segments[i] == tile){ |
||||
|
return i; |
||||
|
} |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
bool check_if_dead(Snake *snake){ |
||||
|
//Self |
||||
|
if(part_of_snake(snake, snake->segments[0]) > 0){ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
//Wall |
||||
|
if(snake->segments[0] % 16 == 0 || (snake->segments[0] / 16) % 16 == 0){ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
unsigned char spawn_fruit(Snake *snake){ |
||||
|
srand(time(NULL)); |
||||
|
int r = 0; |
||||
|
while (part_of_snake(snake, r) != -1 || r % 16 == 0 || (r / 16) % 16 == 0){ |
||||
|
r = rand() % 256; |
||||
|
printf("%d\n", r); |
||||
|
} |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
unsigned char eating_fruit(Snake *snake){ |
||||
|
snake->length++; |
||||
|
return spawn_fruit(snake); |
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
#ifndef SNAKE_START_H |
||||
|
#define SNAKE_START_H |
||||
|
|
||||
|
#define HEIGHT 15 |
||||
|
#define WIDTH 15 |
||||
|
#define AREA HEIGHT * WIDTH |
||||
|
|
||||
|
typedef struct{ |
||||
|
signed char direction; |
||||
|
char length; |
||||
|
unsigned char segments[AREA]; |
||||
|
}Snake; |
||||
|
|
||||
|
|
||||
|
void snake_start(); |
||||
|
Snake initialize_snake(); |
||||
|
int part_of_snake(Snake *snake, unsigned char tile); |
||||
|
void move_snake(Snake *snake); |
||||
|
bool check_if_dead(Snake *snake); |
||||
|
|
||||
|
|
||||
|
#endif // SNAKE_START_H |
@ -0,0 +1,50 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include <stdbool.h> |
||||
|
#include "../../src/main/c/Snake/snake_start.h" |
||||
|
#include "../../src/main/c/Snake/get_character.h" |
||||
|
|
||||
|
|
||||
|
void setUp(void){} |
||||
|
void tearDown(void){} |
||||
|
|
||||
|
|
||||
|
void test_self_collision(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = {1, 5, {6 + 16 * 6, 6 + 16 * 7, 7 + 16 * 7, 7 + 16 * 6, 6 + 16 * 6}}; |
||||
|
|
||||
|
/* act */ |
||||
|
result = check_if_dead(&snake); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_TRUE(result);//head collides with body |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void test_no_collision(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = initialize_snake(); |
||||
|
|
||||
|
/* act */ |
||||
|
result = check_if_dead(&snake); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_FALSE(result);//head collides with body |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void test_wall_collision(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = {-1, 4, {0 + 16 * 6, 1 + 16 * 6, 2 + 16 * 6, 3 + 16 * 6}}; |
||||
|
|
||||
|
/* act */ |
||||
|
result = check_if_dead(&snake); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_TRUE(result);//head collides with body |
||||
|
} |
||||
|
|
||||
|
#endif // TEST |
@ -0,0 +1,69 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include <stdbool.h> |
||||
|
#include <memory.h> |
||||
|
#include "../../src/main/c/Snake/snake_start.h" |
||||
|
#include "../../src/main/c/Snake/get_character.h" |
||||
|
|
||||
|
|
||||
|
void setUp(void){} |
||||
|
void tearDown(void){} |
||||
|
|
||||
|
|
||||
|
void test_moving_right(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = {1, 3, {8 + 16 * 6, 7 + 16 * 6, 6 + 16 * 6}}; |
||||
|
Snake expected = {1, 3, {9 + 16 * 6, 8 + 16 * 6, 7 + 16 * 6}}; |
||||
|
|
||||
|
/* act */ |
||||
|
move_snake(&snake); |
||||
|
result = memcmp(&snake, &expected, sizeof(Snake)) == 0; |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_TRUE(result); |
||||
|
} |
||||
|
|
||||
|
void test_moving_down(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = {16, 3, {8 + 16 * 6, 7 + 16 * 6, 6 + 16 * 6}}; |
||||
|
Snake expected = {16, 3, {8 + 16 * 7, 8 + 16 * 6, 7 + 16 * 6}}; |
||||
|
|
||||
|
/* act */ |
||||
|
move_snake(&snake); |
||||
|
result = memcmp(&snake, &expected, sizeof(Snake)) == 0; |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_TRUE(result); |
||||
|
} |
||||
|
|
||||
|
void test_moving_left(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = {-1, 3, {8 + 16 * 6, 7 + 16 * 6, 6 + 16 * 6}}; |
||||
|
Snake expected = {-1, 3, {7 + 16 * 6, 8 + 16 * 6, 7 + 16 * 6}}; |
||||
|
|
||||
|
/* act */ |
||||
|
move_snake(&snake); |
||||
|
result = memcmp(&snake, &expected, sizeof(Snake)) == 0; |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_TRUE(result); |
||||
|
} |
||||
|
|
||||
|
void test_moving_up(void){ |
||||
|
/* arrange */ |
||||
|
bool result; |
||||
|
Snake snake = {-16, 3, {8 + 16 * 6, 7 + 16 * 6, 6 + 16 * 6}}; |
||||
|
Snake expected = {-16, 3, {8 + 16 * 5, 8 + 16 * 6, 7 + 16 * 6}}; |
||||
|
|
||||
|
/* act */ |
||||
|
move_snake(&snake); |
||||
|
result = memcmp(&snake, &expected, sizeof(Snake)) == 0; |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_TRUE(result); |
||||
|
} |
||||
|
|
||||
|
#endif // TEST |
@ -0,0 +1,49 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include "../../src/main/c/Snake/snake_start.h" |
||||
|
#include "../../src/main/c/Snake/get_character.h" |
||||
|
|
||||
|
|
||||
|
void setUp(void){} |
||||
|
void tearDown(void){} |
||||
|
|
||||
|
|
||||
|
void test_find_head(void){ |
||||
|
/* arrange */ |
||||
|
int result; |
||||
|
Snake snake = initialize_snake(); |
||||
|
|
||||
|
/* act */ |
||||
|
result = part_of_snake(&snake, 8 * 16 + 8); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_EQUAL_INT(0, result);//head is at 8/8 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void test_get_correct_index(void){ |
||||
|
/* arrange */ |
||||
|
int result; |
||||
|
Snake snake = initialize_snake(); |
||||
|
|
||||
|
/* act */ |
||||
|
result = part_of_snake(&snake, 8 * 16 + 6); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_EQUAL_INT(2, result);//2. part ist at 6/8 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void test_snake_not_on_tile(void){ |
||||
|
/* arrange */ |
||||
|
int result; |
||||
|
Snake snake = initialize_snake(); |
||||
|
|
||||
|
/* act */ |
||||
|
result = part_of_snake(&snake, 6 * 16 + 6); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_EQUAL_INT(-1, result);//-1 snake is not on 6/6 |
||||
|
} |
||||
|
|
||||
|
#endif // TEST |
Write
Preview
Loading…
Cancel
Save
Reference in new issue