Browse Source
Merge branch 'branchJulia' into 'main'
Merge branch 'branchJulia' into 'main'
merge 'branchJulia' into 'main' See merge request pmuw_projekt/pmuw_projekt_notebinder!31remotes/origin/fdai7775-main-patch-54732
fdai8032
11 months ago
12 changed files with 450 additions and 6 deletions
-
1src/main/c/Pong/game.c
-
231src/main/c/Pong/pong.c
-
9src/main/c/Pong/pong.h
-
7src/main/c/main.c
-
2src/main/c/main.h
-
0test/Pong/.gitkeep
-
63test/Pong/test_checkCollision.c
-
34test/Pong/test_checkGameEnd.c
-
38test/Pong/test_clearScreen.c
-
42test/Pong/test_playerInputMovement.c
-
27test/Pong/test_pong.c
-
2test/test_template.c
@ -1 +0,0 @@ |
|||||
|
|
@ -0,0 +1,231 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <termios.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <unistd.h> |
||||
|
#include <fcntl.h> |
||||
|
#include <stdbool.h> |
||||
|
|
||||
|
#define WIDTH 40 //Breite Spielfeld |
||||
|
#define HEIGHT 20 //Höhe Spielfeld |
||||
|
#define PADDLE_LENGTH 4 |
||||
|
#define PADDLE "\033[1;31m#\033[0m" |
||||
|
#define BALL "\033[1;31mO\033[0m" |
||||
|
|
||||
|
//Ballstruktur |
||||
|
typedef struct { |
||||
|
int x; |
||||
|
int y; |
||||
|
int speedX; |
||||
|
int speedY; |
||||
|
} Ball; |
||||
|
|
||||
|
// Bildschirm löschen nach Veränderung Position |
||||
|
void clearScreen() { |
||||
|
system("clear"); |
||||
|
} |
||||
|
|
||||
|
void drawField(int paddle1PositionY, int paddle2PositionY, Ball ball, int score1, int score2, int isPaused) { |
||||
|
clearScreen(); |
||||
|
|
||||
|
for (int i = 0; i <= HEIGHT; i++){ |
||||
|
for (int j = 0; j <= WIDTH; j++){ |
||||
|
if (i == 0 || i == HEIGHT){ |
||||
|
printf("-"); |
||||
|
} else if ((j == 0 || j == WIDTH) && (i < paddle1PositionY || i >= paddle1PositionY + PADDLE_LENGTH) && (i < paddle2PositionY || i >= paddle2PositionY + PADDLE_LENGTH)) { |
||||
|
printf("|"); |
||||
|
} else if (i >= paddle1PositionY && i < paddle1PositionY + PADDLE_LENGTH && j == WIDTH) { |
||||
|
printf("%c", PADDLE); |
||||
|
} else if (i >= paddle2PositionY && i < paddle2PositionY + PADDLE_LENGTH && j == 0) { |
||||
|
printf("%c", PADDLE); |
||||
|
} else if (i == ball.y && j == ball.x) { |
||||
|
printf("%c", BALL); |
||||
|
} else { |
||||
|
printf(" "); |
||||
|
} |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
|
||||
|
printf("Spieler 1: %d\tSpieler 2: %d\n", score1, score2); |
||||
|
if (isPaused) { |
||||
|
printf("Spiel pausiert. Drücken Sie 'p', um fortzufahren.\n"); |
||||
|
} else { |
||||
|
printf("Drücken Sie 'p', um das Spiel zu pausieren.\n"); |
||||
|
} |
||||
|
printf("Drücken Sie 'q', um das Spiel zu beenden.\n"); |
||||
|
} |
||||
|
|
||||
|
int kbhit(void){ |
||||
|
struct termios oldt, newt; |
||||
|
int ch, oldf; |
||||
|
|
||||
|
tcgetattr(STDIN_FILENO, &oldt); |
||||
|
newt = oldt; |
||||
|
newt.c_lflag &= ~(ICANON | ECHO); |
||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt); |
||||
|
oldf = fcntl(STDIN_FILENO, F_GETFL, 0); |
||||
|
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); |
||||
|
|
||||
|
ch = getchar(); |
||||
|
|
||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); |
||||
|
fcntl(STDIN_FILENO, F_SETFL, oldf); |
||||
|
|
||||
|
if (ch != EOF) { |
||||
|
ungetc(ch, stdin); |
||||
|
return 1; |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
int getch(void) { |
||||
|
int ch; |
||||
|
|
||||
|
while ((ch = getchar()) == '\n'); |
||||
|
|
||||
|
return ch; |
||||
|
} |
||||
|
|
||||
|
//Aktualisierung Ballposition |
||||
|
void updateBallPosition(Ball *ball) { |
||||
|
ball->x += ball->speedX; |
||||
|
ball->y += ball->speedY; |
||||
|
} |
||||
|
|
||||
|
//Verbesserung Kollision mit Schlägern&Wänden |
||||
|
int checkCollision(Ball ball, int paddle1PositionY, int paddle2PositionY) { |
||||
|
// Kollision mit Schlägern und Wänden |
||||
|
if (ball.y <= 0 || ball.y >= HEIGHT - 1){ |
||||
|
ball.speedY = -ball.speedY; |
||||
|
} |
||||
|
if (ball.x == 1 && (ball.y >= paddle2PositionY && ball.y < paddle2PositionY + PADDLE_LENGTH)){ |
||||
|
ball.speedX = -ball.speedX; |
||||
|
} |
||||
|
|
||||
|
if (ball.x == WIDTH - 1 && (ball.y >= paddle1PositionY && ball.y < paddle1PositionY + PADDLE_LENGTH)){ |
||||
|
ball.speedX = -ball.speedX; |
||||
|
} |
||||
|
|
||||
|
//Punkte zählen |
||||
|
if (ball.x <= 0){ |
||||
|
return 1; // Spieler 2 gewinnt Punkt |
||||
|
} |
||||
|
|
||||
|
if (ball.x >= WIDTH - 1){ |
||||
|
return 2; // Spieler 1 gewinnt Punkt |
||||
|
} |
||||
|
|
||||
|
return 0; // kein Punkt |
||||
|
} |
||||
|
|
||||
|
//Reset |
||||
|
void resetScore(int *score1, int *score2) { |
||||
|
*score1 = 0; |
||||
|
*score2 = 0; |
||||
|
} |
||||
|
|
||||
|
int checkGameEnd(int score1, int score2, int maxScore) { |
||||
|
if (score1 >= maxScore || score2 >= maxScore) { |
||||
|
return 1; // Das Spiel endet |
||||
|
} else { |
||||
|
return 0; // Das Spiel endet nicht |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void processPlayerInput(int *paddlePositionY, int userInput) { |
||||
|
if (userInput == -1) { |
||||
|
// Bewegt den Schläger nach oben, solange der obere Rand nicht erreicht ist |
||||
|
if (*paddlePositionY > 0) { |
||||
|
*paddlePositionY -=1; |
||||
|
} |
||||
|
} else if (userInput == 1) { |
||||
|
// Bewegt den Schläger nach unten, solange der untere Rand nicht erreicht ist |
||||
|
if (*paddlePositionY < HEIGHT - PADDLE_LENGTH) { |
||||
|
*paddlePositionY += 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int pong(){ |
||||
|
int paddle1PositionY = HEIGHT / 2 - PADDLE_LENGTH / 2; |
||||
|
int paddle2PositionY = HEIGHT / 2 - PADDLE_LENGTH / 2; |
||||
|
Ball ball = {WIDTH / 2, HEIGHT / 2, 1, 1}; //Startposition&Geschwindigkeit Ball |
||||
|
int score1 = 0; |
||||
|
int score2 = 0; |
||||
|
int maxScore = 5; |
||||
|
int isPaused = 0; |
||||
|
|
||||
|
while (score1 < maxScore && score2 < maxScore) { |
||||
|
//Steuerung für Schläger 1 |
||||
|
if (!isPaused && kbhit()){ |
||||
|
char input = getch(); |
||||
|
if (input == 'w' && paddle1PositionY > 1) |
||||
|
{ |
||||
|
paddle1PositionY--; |
||||
|
} else if (input == 's' && paddle1PositionY < HEIGHT - PADDLE_LENGTH - 1) { |
||||
|
paddle1PositionY++; |
||||
|
} else if (input == 'p') { |
||||
|
isPaused = !isPaused; |
||||
|
} else if (input == 'q') { |
||||
|
clearScreen(); |
||||
|
printf("Spiel beendet.\n"); |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//Steuerung für Schläger 2 |
||||
|
if (!isPaused && kbhit()){ |
||||
|
char input = getch(); |
||||
|
if (input == 'i' && paddle2PositionY > 1){ |
||||
|
paddle2PositionY--; |
||||
|
} else if (input == 'k' && paddle2PositionY < HEIGHT - PADDLE_LENGTH - 1){ |
||||
|
paddle2PositionY++; |
||||
|
} else if (input == 'p') { |
||||
|
isPaused = !isPaused; |
||||
|
} else if (input == 'q') { |
||||
|
clearScreen(); |
||||
|
printf("Spiel beendet.\n"); |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//Wenn Pauseiert |
||||
|
if (isPaused) { |
||||
|
drawField(paddle1PositionY, paddle2PositionY, ball, score1, score2, 1); |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
//Bewegung Ball |
||||
|
updateBallPosition(&ball); |
||||
|
int result = checkCollision(ball, paddle1PositionY, paddle2PositionY); |
||||
|
|
||||
|
//Aktualisiert Spielstand und Ballposition |
||||
|
if (result == 1) { |
||||
|
score2++; |
||||
|
ball.x = WIDTH / 2; |
||||
|
ball.y = HEIGHT / 2; |
||||
|
ball.speedX = -ball.speedX; |
||||
|
} else if (result == 2) { |
||||
|
score1++; |
||||
|
ball.x = WIDTH / 2; |
||||
|
ball.y = HEIGHT / 2; |
||||
|
ball.speedX = -ball.speedX; |
||||
|
} |
||||
|
|
||||
|
resetScore(&score1, &score2); //Zurücksetzen Spielstand |
||||
|
|
||||
|
drawField(paddle1PositionY, paddle2PositionY, ball, score1, score2, 0); |
||||
|
usleep(100000); //Verlangsamen Schleife/Spiel |
||||
|
} |
||||
|
|
||||
|
clearScreen(); |
||||
|
if (score1 == maxScore) { |
||||
|
printf("Spieler 1 gewinnt!\n"); |
||||
|
} else { |
||||
|
printf("Spieler 2 gewinnt!\n"); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,9 @@ |
|||||
|
#ifndef PONG_H |
||||
|
#define PONG_H |
||||
|
|
||||
|
int pong(); |
||||
|
|
||||
|
void resetScore(int *score1, int *score2); |
||||
|
|
||||
|
#endif |
||||
|
|
@ -0,0 +1,63 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include "pong.h" |
||||
|
#define WIDTH 40 //Breite Spielfeld |
||||
|
#define HEIGHT 20 //Höhe Spielfeld |
||||
|
|
||||
|
typedef struct { |
||||
|
int x; |
||||
|
int y; |
||||
|
int speedX; |
||||
|
int speedY; |
||||
|
} Ball; |
||||
|
|
||||
|
typedef struct { |
||||
|
int x; |
||||
|
int y; |
||||
|
int width; |
||||
|
int height; |
||||
|
} Paddle; |
||||
|
|
||||
|
void setUp(void){ |
||||
|
//Wenn Funktion Vorraussetzungen braucht |
||||
|
} |
||||
|
|
||||
|
void tearDown(void){ |
||||
|
} |
||||
|
|
||||
|
void test_checkCollision(void){ |
||||
|
Ball ball = {10, 10, 1, 1}; |
||||
|
Paddle paddle = {50, 10, 5, 10}; |
||||
|
|
||||
|
// Test Ball trifft rechte und linke Wand |
||||
|
ball.x = 0; |
||||
|
int result1 = checkCollision(ball, paddle.y, paddle.y); |
||||
|
TEST_ASSERT_EQUAL_INT(1, result1); |
||||
|
|
||||
|
ball.x = WIDTH - 1; |
||||
|
int result2 = checkCollision(ball, paddle.y, paddle.y); |
||||
|
TEST_ASSERT_EQUAL_INT(2, result2); |
||||
|
|
||||
|
// Test Ball trifft obere und untere Wand |
||||
|
ball.x = 5; |
||||
|
ball.y = 0; |
||||
|
int result3 = checkCollision(ball, paddle.y, paddle.y); |
||||
|
TEST_ASSERT_EQUAL_INT(0, result3); |
||||
|
|
||||
|
ball.y = HEIGHT - 1; |
||||
|
int result4 = checkCollision(ball, paddle.y, paddle.y); |
||||
|
TEST_ASSERT_EQUAL_INT(0, result4); |
||||
|
|
||||
|
// Test wenn Ball Paddle trifft |
||||
|
ball.x = paddle.x - 1; |
||||
|
ball.y = paddle.y + 1; |
||||
|
int result5 = checkCollision(ball, paddle.y, paddle.y); |
||||
|
TEST_ASSERT_EQUAL_INT(2, result5); |
||||
|
|
||||
|
ball.x = paddle.x + 1; |
||||
|
ball.y = paddle.y + 1; |
||||
|
int result6 = checkCollision(ball, paddle.y, paddle.y); |
||||
|
TEST_ASSERT_EQUAL_INT(2, result6); |
||||
|
} |
||||
|
|
||||
|
#endif // TEST |
@ -0,0 +1,34 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include "pong.h" |
||||
|
|
||||
|
// Prüfen Spiellogik für Beenden des Spiels |
||||
|
|
||||
|
void setUp(void){ |
||||
|
//Wenn Funktion Vorraussetzungen braucht |
||||
|
} |
||||
|
|
||||
|
void tearDown(void){ |
||||
|
} |
||||
|
|
||||
|
void test_checkGameEnd(void){ |
||||
|
/* arrange */ |
||||
|
int maxScore = 5; |
||||
|
int score1 = 4, score2 = 2; |
||||
|
|
||||
|
/* act */ |
||||
|
int result = checkGameEnd(score1, score2, maxScore); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_EQUAL_INT(0, result); // Das Spiel sollte noch nicht enden |
||||
|
|
||||
|
/* Spieler 1 erreicht den Maximalscore */ |
||||
|
score1 = 5; |
||||
|
result = checkGameEnd(score1, score2, maxScore); |
||||
|
TEST_ASSERT_EQUAL_INT(1, result); // Das Spiel sollte enden, da Spieler 1 den Maximalscore erreicht hat |
||||
|
|
||||
|
/* Weitere Tests mit anderen Spiellogikfällen und Endspielbedingungen können hinzugefügt werden */ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#endif // TEST |
@ -0,0 +1,38 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include "pong.h" |
||||
|
|
||||
|
#define TEST_SCREEN_WIDTH 40 |
||||
|
#define TEST_SCREEN_HEIGHT 20 |
||||
|
|
||||
|
char screen[TEST_SCREEN_HEIGHT][TEST_SCREEN_WIDTH+1]; |
||||
|
|
||||
|
void setUp(void){ |
||||
|
//Wenn Funktion Vorraussetzungen braucht |
||||
|
} |
||||
|
|
||||
|
void tearDown(void){ |
||||
|
} |
||||
|
|
||||
|
void test_clearScreen(void){ |
||||
|
/* arrange */ |
||||
|
int i, j; |
||||
|
for (i = 0; i < TEST_SCREEN_HEIGHT; i++) { |
||||
|
for (j = 0; j < TEST_SCREEN_WIDTH; j++) { |
||||
|
screen[i][j] = ' '; |
||||
|
} |
||||
|
screen[i][j] = '\0'; |
||||
|
} |
||||
|
|
||||
|
/* act */ |
||||
|
clearScreen(); |
||||
|
|
||||
|
/* assert */ |
||||
|
for (i = 0; i < TEST_SCREEN_HEIGHT; i++) { |
||||
|
for (j = 0; j < TEST_SCREEN_WIDTH; j++) { |
||||
|
TEST_ASSERT_EQUAL_INT(' ', screen[i][j]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif // TEST |
@ -0,0 +1,42 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include "pong.h" |
||||
|
|
||||
|
typedef struct { |
||||
|
int x; |
||||
|
int y; |
||||
|
int speedX; |
||||
|
int speedY; |
||||
|
} Paddle; |
||||
|
// sicherstellen korrekte Funktion Steuerung für Schläger |
||||
|
|
||||
|
void setUp(void){ |
||||
|
//Wenn Funktion Vorraussetzungen braucht |
||||
|
} |
||||
|
|
||||
|
void tearDown(void){ |
||||
|
} |
||||
|
|
||||
|
void test_playerInputMovement(void){ |
||||
|
/* Test 1: Bewegung nach oben */ |
||||
|
int paddlePositionY = 10; |
||||
|
int userInput = -1; // Benutzereingabe für Bewegung nach oben |
||||
|
int expectedY = paddlePositionY - 1; |
||||
|
|
||||
|
processPlayerInput(&paddlePositionY, userInput); |
||||
|
TEST_ASSERT_EQUAL_INT(expectedY, paddlePositionY); |
||||
|
|
||||
|
/* Test 2: Bewegung nach unten */ |
||||
|
userInput = 1; |
||||
|
expectedY = paddlePositionY + 1; |
||||
|
// Benutzereingabe für Bewegung nach unten |
||||
|
|
||||
|
processPlayerInput(&paddlePositionY, userInput); |
||||
|
TEST_ASSERT_EQUAL_INT(expectedY, paddlePositionY); |
||||
|
|
||||
|
/* Weitere Tests mit anderen Bewegungsrichtungen und Grenzfällen können hinzugefügt werden */ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
#endif // TEST |
@ -0,0 +1,27 @@ |
|||||
|
#ifdef TEST |
||||
|
#include "unity.h" |
||||
|
#include "pong.h" |
||||
|
|
||||
|
|
||||
|
void setUp(void){ |
||||
|
//Wenn Funktion Vorraussetzungen braucht |
||||
|
} |
||||
|
void tearDown(void){ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void test_input_all_5(void){ |
||||
|
/* arrange */ |
||||
|
int a = 4, b = 5; |
||||
|
|
||||
|
/* act */ |
||||
|
resetScore( &a, &b ); |
||||
|
|
||||
|
/* assert */ |
||||
|
TEST_ASSERT_EQUAL_INT(0, a); |
||||
|
TEST_ASSERT_EQUAL_INT(0, b); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
#endif // TEST |
Write
Preview
Loading…
Cancel
Save
Reference in new issue