Use keyboard/Input numbers

Hello. I am making sudoku game and I have board 9x9 with numbers and I am thinking how is best way to input numbers from user to complete matrix.

There’s a few possible ways to achieve what you want.

A possible solution is to let the user, via a console window, tell the game in which row/column the number should be inserted into, and what that number should be.
Another solution is to use the SDL_TextInputEvent event functionality in SDL to let the player click on a column in the grid and then press a number key on the keyboard to save it into some string, to later be rendered on the screen.

There’s probably a few other (maybe better) solutions to achieve it but these are the solutions I can come up with at the moment.

1 Like

One possibility that occurs to me would be to just monitor for keyboard events for the nine digits, and when they arrive enter the digit at whichever grid square the mouse is currently over, without requiring a mouse button click. (Basically, treat the digits on the keyboard as nine mouse buttons.) Unfortunately, the position of the digits on a standard keyboard makes this awkward for most users. It would be just about perfect for people who use a left-handed mouse, though.

1 Like

I try do this in second way by Brian_Raiter idea. I created fucntion to going through all grids, somthing like that:
SDL_Event event;
SDL_PollEvent(&event);
SDL_Rect Frame;
bool ok = true;
Frame.h = 50;
Frame.w = 50;
Frame.x = 50;
Frame.y = 50;
SDL_SetRenderDrawColor(renderer,0, 255,255,255);
SDL_RenderDrawRect(renderer,&Frame);
SDL_RenderFillRect(renderer,&Frame);
while(SDL_KEYDOWN)
{
if(SDLK_LEFT) Frame.x+=50;

    if(SDLK_RIGHT) Frame.x-=50;

    if(SDLK_UP) Frame.y+=50;

    if(SDLK_DOWN)  Frame.y-=50;

  SDL_RenderPresent(renderer);
   }

But when I call this function, I get only one position.

I’m going to hazard a guess here that you’re still learning C? There are some basic errors in the snippet you posted. SDL_KEYDOWN isn’t a test; it’s just a value. Probably what you meant was something like if (event.type == SDL_KEYDOWN) but it’s hard to say for certain. Similar comments apply to the ifs in the loop body. And you only use SDL_RenderDrawRect() outside the loop, so that’s why you only get one position.

Anyway, this isn’t an issue with SDL but with understand the C language in general, so it’s pretty off topic here.

(If this is in fact your first non-trivial C project: You will likely learn C a whole lot faster by tackling some smaller programming projects first, before moving on to something graphical and interactive. It’s better to learn to walk before trying to run.)

1 Like

Hi again, I achieved my goal and I can input numbers to complete sudoku… but my numbers blinking I dont know why…

I seperated drawing grid in two functions: First draw sudoku without numbers and second draw numbers in some places:

while(running)
{
draw_grid();
draw_numbers();
while(Pollevent)
{
// Handle events
}

}

Show us your draw_grid() and draw_numbers() functions.

1 Like

draw_grid()

{
SDL_SetRenderDrawColor(renderer, 0,0,0,255);
SDL_RenderClear(renderer);

SDL_Rect small_rect;
small_rect.x = 50;
small_rect.y = 50;
small_rect.w = 50;
small_rect.h = 50;
SDL_Rect medium_rect;
medium_rect.x = 50;
medium_rect.y = 50;
medium_rect.w = 150;
medium_rect.h = 150;
SDL_Rect big_rect;
big_rect.x = 50;
big_rect.y = 50;
big_rect.w = 450;
big_rect.h = 450;
SDL_Rect rect;
rect.x = 50;
rect.y = 50;
rect.w = 50;
rect.h = 50;
for(int i=0; i<9; i++)
{
    small_rect.x = 50;
    rect.x = 50;

    for(int j=0; j<9; j++)
    {

     SDL_SetRenderDrawColor(renderer, 0, 128,128, 128);
     SDL_RenderFillRect(renderer,&rect);
     SDL_SetRenderDrawColor(renderer, 0, 0,255, 255);
     SDL_RenderDrawRect(renderer, &small_rect);

     small_rect.x+=50;
     rect.x+=50;
    }

  small_rect.y+=50;
  rect.y+=50;
 }
for(int i=0; i<3; i++)
{
    medium_rect.x = 50;
    for(int j=0; j<3; j++)
    {
     SDL_SetRenderDrawColor(renderer, 128, 128,128, 255);
     SDL_RenderDrawRect(renderer, &medium_rect);

    medium_rect.x+=150;
    }
    medium_rect.y+=150;
 }

    SDL_SetRenderDrawColor(renderer, 255,255,0,0);

    SDL_RenderDrawRect(renderer, &big_rect);
    SDL_RenderPresent(renderer);

}
draw_numbers()
{
TTF_Init();
TTF_Font * font = TTF_OpenFont(“arialn.ttf”, 25);
SDL_Color White = {255, 255, 255};

SDL_Surface* surfaceMessage = NULL;

SDL_Texture* Message = NULL;

SDL_Rect Message_rect;
Message_rect.x = 65;
Message_rect.y = 65;
Message_rect.w = SHAPE_SIZE;
Message_rect.h = SHAPE_SIZE;

char number[256];

for(int i=0; i<9; i++)
{
    Message_rect.x = 65;
    for(int j=0; j<9; j++)
     {
     if(matrix[i][j]!=0)
     {
     sprintf(number, "%d", matrix[i][j]);
     surfaceMessage = TTF_RenderText_Solid(font, number , White);
     Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
     SDL_RenderCopy(renderer, Message, NULL, &Message_rect);
     SDL_RenderPresent(renderer);

     }
     Message_rect.x+=50;
     }
  Message_rect.y+=50;

}

for(int i=0; i<9; i++)
{
    for(int j=0; j<9; j++)
  {
        if(matrix[i][j]!=0)
     {
      SDL_DestroyTexture(Message);

     }
  }
}
     SDL_FreeSurface(surfaceMessage);
     TTF_CloseFont(font);
     TTF_Quit();

}

I don’t know how much programming knowledge you have and how experienced you’re with c++, SDL, memory leaks etc but there’s quite a few issues I’ve found in each of the two functions.

draw_grid()

This function looks okay, except that you’re executing the SDL_RenderPresent() function in it.

The SDL_RenderPresent() function is supposed to be executed once at the end of the frame, i.e when all the render commands (SDL_RenderCopy(), SDL_RenderFillRect etc) has been finished, to update the window with the new data/information.

So in your while(running) loop, after you’ve finished rendering the grid, the numbers and other graphical elements you might want to render, execute SDL_RenderPresent() and remove the call to that function in all the other places where it’s currently executed.

draw_numbers()

This function unfortunately doesn’t look as okay.

First of all, you’re initializing the TTF library, and also load a font, each frame.
The TTF library (and other libraries too, for that matter) is supposed to be created/loaded/initialized at the startup of the application and destroyed/unloaded/deinitialized at application shutdown.

When it comes to loading files (a font file in this case), you usually want to avoid loading/unloading files as much as you can, during runtime.
So instead of loading the font each time the draw_numbers() function is called, create the font at the startup of the application and destroy it at application shutdown.

There’s a big issue with the creation of the SDL_Surface- and the SDL_Texture instances that you’re (potentially) creating in the 2-dimensional for-loop. You’re creating a new SDL_Surface instance and a new SDL_Texture instance each time a non-zero value occur in the matrix array, but those specific SDL_Surface- and SDL_Texture instances are never destroyed before new instances of those data types are (eventually) created in the next loop iteration.
This can cause a massive memory leak and the code can potentially create 81 SDL_Surface instances and 81 SDL_Texture instances each frame (since the 2-dimensional for-loop’s range is 9x9), that’s never destroyed.
Eventually your computer will run out of memory and the application (and maybe also your OS) will crash.

To fix the memory leak issues, move the SDL_FreeSurface() and SDL_DestroyTexture() calls up into the 2-dimensional for-loop, right after the SDL_RenderCopy() call.
You should, just like in the draw_grid() function, remove the SDL_RenderPresent() call, since it should only be executed at the end of the frame.

These are the issues I’ve spotted at the moment and there might be other stuff I’ve missed.

As for your original issue, with the blinking numbers - my guess is that it’s caused by the incorrect usage of the SDL_RenderPresent() function and/or the SDL_Texture allocation issue above.

1 Like

Thanks for tips, now everything with input numbers is okay, now I am thinking about how to check corectness of input by user numbers

I created functions to check rows and columns like this:

void check_rows(int x,int y) // x position and y position
{
if(matrix[x][y]!=0)
{
for(int i=0; i<9; i++)
{
if(x==i)
continue;
if(matrix[x][y]==matrix[i][y])
{
// Anything I do in this while, this appear on screen only for second. I dont know how stopped this informing obejct until user change number in grid
break;
}
}
}

}

What are you trying to accomplish with your code? It’s a bit unclear what the goal is.

1 Like

I want to in case of wrong number(which can detect function check_row or check_column) would appear any information to user for example red rectangle in place of this number but in my loop anything i do will be shown on screen only for second

You’ll have to show the actual mainloop and the function(s) that doesn’t work as planned.

A while back in this thread, you posted two functions that you used to render your graphical elements, draw_grid() and draw_numbers().
After that, I wrote an answer to you and explained some issues with the code, what to do to fix them and how to get the graphical elements to render properly.
If you’re still using those functions, have you fixed the issues etc that I wrote about?

1 Like