Я делаю программу, которая решает судоку в c, и отображает его с помощью SDL.
Проблема в том, что SDL_Delay()
не работает, программа работает очень медленно, я думаю, что я забылосвободить поверхности или уничтожить текстуры или еще что-то, чтобы сохранить память, но я не могу точно определить это.
Вот весь код:
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
const int window_width = 860;
const int window_height = 640;
int blank_board[9][9] = {
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0},
{0,0,0, 0,0,0, 0,0,0}};
void square(SDL_Renderer *renderer, float x, float y, int width, int height, int colour1, int colour2, int colour3)
{
SDL_SetRenderDrawColor(renderer, colour1, colour2, colour3, 255);
SDL_Rect rect = {x, y, width, height};
SDL_RenderFillRect(renderer, &rect);
}
void easy_message(SDL_Renderer *renderer, char message_string[50], bool use_int_messge, int message_int, int colour1, int colour2, int colour3, int text_size, int x, int y)
{
char letter[420];
if (use_int_messge == true)
{
sprintf(letter, "%s %d ", message_string, message_int);
}
else
{
sprintf(letter, "%s ", message_string);
}
SDL_Color colour = {colour1, colour2, colour3};
TTF_Font * font = TTF_OpenFont("arial.ttf", text_size);
SDL_Surface * surface = TTF_RenderText_Solid(font, letter, colour);
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
int textW = 0;
int textH = 0;
SDL_QueryTexture(texture, NULL, NULL, &textW, &textH);
SDL_Rect text_rect = {x, y, textW, textH};
SDL_RenderCopy(renderer, texture, NULL, &text_rect);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
TTF_CloseFont(font);
}
bool in_box(bool mouse_clicked, int mouse_posx, int mouse_posy, int box_x, int box_y, int box_width, int box_height)
{
if(mouse_clicked == true)
{
if(mouse_posx >= box_x && mouse_posx <= box_x + box_width)
{
if(mouse_posy >= box_y && mouse_posy <= box_y + box_height)
return true;
}
}
return false;
}
void print_board(int *arr[9][9], SDL_Renderer *renderer)
{
SDL_Surface * image = IMG_Load("board.png");
if (!image)
{
printf("IMG_Load: %s\n", IMG_GetError());
}
int z,x, y, w, h;
x = 50;
y = 50;
w = 150;
h = 150;
SDL_Texture * img_board = SDL_CreateTextureFromSurface(renderer, image);
for (z=1; z < 12; ++z)
{
if(z/3 == 1)
{
SDL_Rect rect = {x - 350 + z*158, y, w, h};
SDL_RenderCopy(renderer, img_board, NULL, &rect);
}
if(z/3 == 2)
{
SDL_Rect rect = {x - 824 + z*158, y + h + 10, w, h};
SDL_RenderCopy(renderer, img_board, NULL, &rect);
}
if(z/3 == 3)
{
SDL_Rect rect = {x - 1298 + z*158, y + (h+10)*2, w, h};
SDL_RenderCopy(renderer, img_board, NULL, &rect);
}
}
/*int len_of_arr, len_of_ind, i, j;
len_of_arr = (sizeof(*arr) / sizeof(*arr[0]));
len_of_ind = (sizeof(arr[0]) / sizeof(*arr[0][0]));
char letter[5];
for (i=0; i < len_of_arr; ++i)
{
if(i%3 == 0 && i != 0)
{
printf("--------------------\n");
}
for (j=0; j < len_of_ind; ++j)
{
if(j%3 == 0)
{
printf("|");
}
if (j == 8)
{
printf("%d\n", arr[i][j]);
}
else
{
sprintf(letter, "%d", arr[i][j]);
strcat(letter, " ");
printf("%s", letter);
}
}
}*/
SDL_FreeSurface(image);
SDL_DestroyTexture(img_board);
}
int find_empty_row(int *arr[9][9])
{
int len_of_arr, len_of_ind, i, j;
len_of_arr = (sizeof(*arr) / sizeof(*arr[0]));
len_of_ind = (sizeof(arr[0]) / sizeof(*arr[0][0]));
for (i=0; i < len_of_arr; ++i)
{
for(j=0; j < len_of_ind; j++)
{
if(arr[i][j] == 0)
return i;
}
}
return -1;
}
int find_empty_col(int *arr[9][9])
{
int len_of_arr, len_of_ind, i, j;
len_of_arr = (sizeof(*arr) / sizeof(*arr[0]));
len_of_ind = (sizeof(arr[0]) / sizeof(*arr[0][0]));
for (i=0; i < len_of_arr; ++i)
{
for(j=0; j < len_of_ind; j++)
{
if(arr[i][j] == 0)
return j;
}
}
return -1;
}
bool valid(int *arr[9][9], int num, int pos1, int pos2)
{
int len_of_arr, len_of_ind, i, j, box_x, box_y;
len_of_arr = (sizeof(*arr) / sizeof(*arr[0]));
len_of_ind = (sizeof(arr[0]) / sizeof(*arr[0][0]));
for (i=0; i < len_of_ind; ++i)
{
if(arr[pos1][i] == num && pos2 != i)
{
return false;
}
}
for (i=0; i < len_of_arr; ++i)
{
if(arr[i][pos2] == num && pos1 != i)
{
return false;
}
}
box_x = pos2 / 3;
box_y = pos1 / 3;
for(i=(box_y*3); i < (box_y*3 + 3); ++i)
{
for (j=(box_x*3); j < (box_x*3 + 3); ++j)
{
if(arr[i][j] == num && i != pos1 && j != pos2)
{
return false;
}
}
}
return true;
}
bool solve(int *arr[9][9])
{
//func(9, 9, arr);
int find1, find2, row, col;
find1 = find_empty_row(arr);
find2 = find_empty_col(arr);
if(find1 == -1 && find2 == -1)
{
return true;
}
else
{
row = find1;
col = find2;
}
for(int i=1; i < 10; ++i)
{
if(valid(arr, i, row, col))
{
arr[row][col] = i;
if(solve(arr))
{
return true;
}
arr[row][col] = 0;
}
}
return false;
}
void do_numbers_i(int i, int j, int y_add, SDL_Renderer *renderer, int *board[9][9], bool passed_in_board)
{
if(passed_in_board == false)
{
if(i <= 2)
{
easy_message(renderer, "", true, board[j][i], 0, 0, 0, 28, 180 + i*53, 60 + y_add);
}
if (i <= 5 && i > 2)
{
easy_message(renderer, "", true, board[j][i], 0, 0, 0, 28, 180 + i*53, 60 + y_add);
}
if (i <= 8 && i > 5)
{
easy_message(renderer, "", true, board[j][i], 0, 0, 0, 28, 180 + i*53, 60 + y_add);
}
}
else
{
if(i <= 2)
{
easy_message(renderer, "", true, board[j][i], 0, 0, 0, 28, 180 + i*53, 60 + y_add);
}
if (i <= 5 && i > 2)
{
easy_message(renderer, "", true, board[j][i], 0, 0, 0, 28, 180 + i*53, 60 + y_add);
}
if (i <= 8 && i > 5)
{
easy_message(renderer, "", true, board[j][i], 0, 0, 0, 28, 180 + i*53, 60 + y_add);
}
}
}
void do_numbers_j(int i, int j, SDL_Renderer *renderer, int *board[9][9], bool passed_in_board)
{
if(j==0)
{
do_numbers_i(i, j, 0, renderer, board, passed_in_board);
}
if(j==1)
{
do_numbers_i(i, j, 50, renderer, board, passed_in_board);
}
if(j==2)
{
do_numbers_i(i, j, 100, renderer, board, passed_in_board);
}
if(j==3)
{
do_numbers_i(i, j, 160, renderer, board, passed_in_board);
}
if(j==4)
{
do_numbers_i(i, j, 210, renderer, board, passed_in_board);
}
if(j==5)
{
do_numbers_i(i, j, 260, renderer, board, passed_in_board);
}
if(j==6)
{
do_numbers_i(i, j, 320, renderer, board, passed_in_board);
}
if(j==7)
{
do_numbers_i(i, j, 370, renderer, board, passed_in_board);
}
if(j==8)
{
do_numbers_i(i, j, 420, renderer, board, passed_in_board);
}
if(j==9)
{
do_numbers_i(i, j, 470, renderer, board, passed_in_board);
}
}
void write_numbers_on_board(SDL_Renderer *renderer, int *board[9][9], bool passed_in_board)
{
if (passed_in_board == true)
{
for (int i=0; i < 9; ++i)
{
for (int j=0; j < 9; ++j)
{
do_numbers_j(i, j, renderer, board, true);
}
}
}
else
{
for (int i=0; i < 9; ++i)
{
for (int j=0; j < 9; ++j)
{
do_numbers_j(i, j, renderer, board, false);
}
}
}
}
void do_sudoku(int *board[9][9], SDL_Renderer *renderer, bool do_it)
{
print_board(board, renderer);
write_numbers_on_board(renderer, board, do_it);
clock_t begin = clock();
if (do_it == true)
{
solve(board);
}
//printf("_______________________\n\n");
//print_board(board, renderer);
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
//printf("\n\nTime taken: %f\n\n", time_spent);
}
int main(int argc, char* argv[])
{
int board[9][9] = {
{0,8,0, 5,0,0, 0,0,0},
{0,0,0, 0,3,0, 2,0,0},
{0,0,9, 0,2,0, 7,0,0},
{0,0,7, 0,0,0, 0,0,6},
{0,4,0, 0,0,0, 0,5,0},
{1,0,0, 2,0,0, 0,0,7},
{0,0,8, 0,6,0, 0,0,3},
{0,0,0, 3,0,1, 6,0,4},
{0,0,1, 0,0,9, 0,0,0}};
bool running = true;
int mouse_x, mouse_y;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SDL_Window * window = SDL_CreateWindow("SDL_ttf in SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
bool solve = false;
float x = 1;
float y = 0;
while (running)
{
while(SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
running = false;
break;
}
/*if (event.type == SDL_MOUSEMOTION)
{
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
}*/
if (event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_RETURN:
solve = true;
break;
}
}
}
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
printf("\nMouse (%d, %d)", mouse_x, mouse_y);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
do_sudoku(board, renderer, solve);
square(renderer, x, y, 50, 50, 255, 0, 0);
SDL_RenderPresent(renderer);
x = x+1;
y = y+1;
//SDL_Delay(20);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
TTF_Quit();
return 0;
}
Я добавил квадрат, чтобы перемещаться пона экране, чтобы увидеть, насколько быстро он это делает, основываясь на скорости цикла, и без функции do_sudoku()
он работает очень быстро, и это все, что мне удалось обнаружить.