Direction Input Handling on Linux Unlike Windows' getch(), Linux requires terminal configuration modifications to handle non-blocking keyboard input. Using termios structure settings enables real-time direction input detection:
int Game::input() {
struct termios terminalSettings, modifiedSettings;
tcgetattr(STDIN_FILENO, &terminalSettings);
modifiedSettings = terminalSettings;
modifiedSettings.c_lflag &= ~ICANON;
modifiedSettings.c_cc[VTIME] = 0;
modifiedSettings.c_cc[VMIN] = 1;
tcsetattr(STDIN_FILENO, TCSANOW, &modifiedSettings);
char keyInput = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &terminalSettings);
switch(keyInput) {
case 'w': return DIRECTION_UP;
case 's': return DIRECTION_DOWN;
case 'a': return DIRECTION_LEFT;
case 'd': return DIRECTION_RIGHT;
}
return -1;
}
Game Loop Architecture The game loop separates input handling and movement logic using pthreads:
void* Game::inputThreadHandler(void* context) {
Game* gameInstance = static_cast<Game*>(context);
while(!gameInstance->_exitFlag) {
gameInstance->processInput();
}
return nullptr;
}
int Game::startGameLoop() {
pthread_t inputThread;
pthread_create(&inputThread, nullptr, inputThreadHandler, this);
while(!_exitFlag) {
updateSnakePosition();
renderFrame();
usleep(100000); // 100ms frame rate
}
return 0;
}
Snake Growth Mechanics The snake's body management system implements chained node allocation:
int Snake::initialize(char icon, int direction, int length, Coordinate startPos) {
_head.icon = icon;
_head.direction = direction;
_head.position = startPos;
_head.next = nullptr;
_size = 1;
// Build initial body segments
for(int i = 1; i < length; i++) {
addBodySegment(icon);
}
return 0;
}
int Snake::addBodySegment(char icon) {
SnakeSegment* newSegment = new SnakeSegment();
newSegment->icon = icon;
newSegment->next = _head.next;
_head.next = newSegment;
_size++;
return 0;
}
Movement Implementation Core movement logic handles both head and body segment updates:
void Snake::moveForward() {
// Store current head position
Coordinate oldPosition = _head.position;
char oldIcon = _head.icon;
// Update head position based on direction
switch(_head.direction) {
case DIRECTION_UP: _head.position.x--; break;
case DIRECTION_DOWN: _head.position.x++; break;
case DIRECTION_LEFT: _head.position.y--; break;
case DIRECTION_RIGHT: _head.position.y++; break;
}
// Update body segments if snake has body
if(_size > 1) {
SnakeSegment* current = _head.next;
_head.next = new SnakeSegment();
_head.next->icon = oldIcon;
_head.next->position = oldPosition;
_head.next->next = current;
// Remove tail if exceeding max size
if(_size > MAX_SNAKE_LENGTH) {
removeTailSegment();
}
}
}
Testing Observations Initial testing revealed boundary collision issues requiring additional validation logic. The current implementation allows the snake to move through map boundaries, with directional input responsiveness verified across multiple test sequences. Threaded input handling successfully decouples movement timing from user input polling.