Browse Source

Merge branch 'David' into 'main'

Finished Snake

See merge request pmuw_projekt/pmuw_projekt_notebinder!15
remotes/origin/fdai7775-main-patch-54732
fdai8032 11 months ago
parent
commit
b913acc799
  1. 58
      src/main/c/Snake/get_character.c
  2. 6
      src/main/c/Snake/get_character.h
  3. 201
      src/main/c/Snake/snake_start.c
  4. 22
      src/main/c/Snake/snake_start.h
  5. 5
      src/main/c/main.c
  6. 50
      test/Snake/test_collision.c
  7. 69
      test/Snake/test_moving_snake.c
  8. 49
      test/Snake/test_part_of_snake.c

58
src/main/c/Snake/get_character.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;
}

6
src/main/c/Snake/get_character.h

@ -0,0 +1,6 @@
#ifndef GET_CHARACTER_H
#define GET_CHARACTER_H
char get_character(double limit);
#endif // GET_CHARACTER_H

201
src/main/c/Snake/snake_start.c

@ -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);
}

22
src/main/c/Snake/snake_start.h

@ -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

5
src/main/c/main.c

@ -3,6 +3,7 @@
#include <stdbool.h>
#include "Template/game100.h"
#include "Snake/snake_start.h"
int main(){
bool running = true;
@ -15,7 +16,7 @@ int main(){
printf("Waehlen Sie eine Option:\n");
printf("\t1.Spiel1 starten\n");
printf("\t2.Spiel2 starten\n");
printf("\t3.Spiel3 starten\n");
printf("\t3.Snake starten\n");
printf("\t4.Spiel4 starten\n");
printf("\t100.Template starten\n");
printf("\t6.Exit\n");
@ -31,7 +32,7 @@ int main(){
//start_game2();
break;
case 3:
//start_game3();
snake_start();
break;
case 4:
//start_game4();

50
test/Snake/test_collision.c

@ -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

69
test/Snake/test_moving_snake.c

@ -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

49
test/Snake/test_part_of_snake.c

@ -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
Loading…
Cancel
Save