Я закончил свой первый настоящий C-проект, и это была игра Conways Game of Life. Код работает нормально, игра запускается. Поскольку это был мой первый проект, хотя я не знаю никаких реальных соглашений о коде для написания C. Я хотел реализовать несколько тестов, поэтому мне пришлось разделить функциональность из основного файла на новый.
Я действительно не мог понять, как писать тесты, чтобы, возможно, в будущем реорганизовать код и просто в образовательных целях, поскольку я впервые пишу какие-либо реальные тесты. Поскольку я реализовал множество функций, которые работают вместе с функциями из SDL, я понятия не имею, как их тестировать. Это файл, содержащий все функции:
#include "./main.h"
multi_arr Field = {0,};
multi_arr nextState = {0,};
SDL_Color blue = {0,0,255,255};
SDL_Color black = {0,0,0,255};
SDL_Color white = {244,244,244,50};
int getLastMultiple(int number){
int multiple = RECT_SIZE;
float remainder;
if ((remainder = (number % multiple)) == 0)
return number;
else{
number -= remainder;
}
return number;
}
void colorRect(SDL_Renderer *renderer, SDL_Rect r,SDL_Color color){
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b ,255);
// Render rect
SDL_RenderFillRect(renderer, &r);
}
void drawGrid(SDL_Renderer *renderer,SDL_Color color){
SDL_SetRenderDrawColor(renderer, color.r,color.g,color.b,color.a);
for (int i = 20; i < SCREEN_WIDTH; i += 20){
SDL_RenderDrawLine(renderer, i,0,i,SCREEN_HEIGHT);
}
for (int i = 20; i < SCREEN_HEIGHT;i += 20){
SDL_RenderDrawLine(renderer, 0,i,SCREEN_WIDTH,i);
}
}
void displayImg(SDL_Renderer *renderer,char* path){
SDL_Surface *image = SDL_LoadBMP(path);
if (image == NULL){
printf("cant load imagen");
}
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
SDL_Rect image_pos = { 6,SCREEN_HEIGHT-55, 50, 50 };
SDL_Rect rect = {0,SCREEN_HEIGHT-59,60,60};
colorRect(renderer, rect, white);
SDL_RenderCopy(renderer, texture, NULL,&image_pos);
}
void updateGame(SDL_Window *window,SDL_Renderer *renderer, SDL_Rect r,bool paused){
//Loop through field-array and show rectangles if cell alive
char *path;
if (paused){
path = "./assets/start.bmp";
} else{
path = "./assets/pause.bmp";
}
for (int i = 0; i < WIDTH;i++){
for (int j = 0; j < HEIGHT;j++){
if (Field[i][j] == true){
r.x = i * 20;
r.y = j * 20;
colorRect(renderer, r, blue);
} else {
r.x = i * 20;
r.y = j * 20;
colorRect(renderer, r, white);
}
}
}
drawGrid(renderer,black);
displayImg(renderer, path);
SDL_RenderPresent(renderer);
}
int countAliveNeighbors(int x, int y){
int count = 0;
for (int rows = -1; rows < 2; rows++){
for (int columns = -1; columns < 2;columns++){
if ((x+columns) >= 0 && (x+columns) < WIDTH && (y+rows) >= 0 && (y+rows) < HEIGHT){
if (Field[x+columns][y+rows] == true){
count++;
}
}
}
}
if (Field[x][y] == true){
return count -1;
}
return count;
}
void copyArray(multi_arr arr1,multi_arr arr2){
for (int i = 0; i < WIDTH;i++){
for (int j = 0; j < HEIGHT;j++){
arr1[i][j] = arr2[i][j];
}
}
}
void nextEpoch(){
for (int i = 0; i < WIDTH;i++){
for (int j = 0; j < HEIGHT;j++){
if (Field[i][j] == true && (countAliveNeighbors(i, j) == 3 || countAliveNeighbors(i, j) == 2)){
nextState[i][j] = true;
} else if (Field[i][j] == false && countAliveNeighbors(i, j) == 3){
nextState[i][j] = true;
} else {
nextState[i][j] = false;
}
}
}
copyArray(Field, nextState);
}
bool buttonPress(int x,int y){
if (x <= 2 && x >= 0 && y >= (HEIGHT - 3) && y <= HEIGHT){
return true;
}
return false;
}
Uint32 my_callbackfunc( Uint32 interval, void *param ){
SDL_Event e;
e.user.type = SDL_USEREVENT;
e.user.code = 0;
e.user.data1 = NULL;
e.user.data2 = NULL;
SDL_PushEvent(&e);
return interval;
}
Вот тесты, которые я написал на данный момент:
#include "./include/criterion/criterion.h"
#include "include/criterion/assert.h"
#include "include/criterion/internal/test.h"
#include "main.h"
extern multi_arr Field;
Test(getLastMultiple,test_getLastMultiple_if_multiple_20){
cr_assert(getLastMultiple(58) == 40);
cr_assert(getLastMultiple(29) == 20);
cr_assert(getLastMultiple(640) == 640);
}
Test(aliveNeighbors,test_count_alive_neighbors_if_cell_active){
Field[20][10] = true;
Field[19][10] = true;
Field[21][11] = true;
cr_assert(countAliveNeighbors(20, 10) == 2);
}
Test(aliveNeighbors,test_count_alive_neighbors_if_cell__not_active){
Field[20][10] = true;
Field[19][10] = true;
Field[21][11] = true;
cr_assert(countAliveNeighbors(20, 11) == 3);
}
Test(buttonPress,test_button_press_detected){
cr_assert(buttonPress(2, HEIGHT) == true);
cr_assert(buttonPress(5, HEIGHT) == false);
}
Test(copyArray,test_array_copied){
Field[20][10] = true;
Field[19][10] = true;
Field[21][11] = true;
multi_arr copied = {0,};
copyArray(copied,Field);
/*cr_assert_arrays_eq_cmp(copied,Field);*/
}
Test(nextEpoch,test_if_next_epoch_cells_correct_pos){
int active_cells = 0;
multi_arr nextState = {0,};
Field[20][10] = true;
Field[19][10] = true;
Field[21][11] = true;
nextEpoch();
for (int i = 0;i < WIDTH;i++){
for (int j = 0; j < HEIGHT;j++){
active_cells += (Field[i][j] == true) ? 1 : 0;
}
}
cr_assert(active_cells == 2);
cr_assert(Field[20][10] == true && Field[20][11] == true);
}
Спасибо за помощь и извините, если я неправильно использовал сообщество. Любая помощь приветствуется. Это весь код: https://github.com/PhilippRados/GameOfLife
Мы высоко ценим любые советы по улучшению этого кода.
