Initial commit

This commit is contained in:
github-classroom[bot] 2025-01-14 11:07:40 +00:00 committed by GitHub
commit 87dcb960bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
67 changed files with 6733 additions and 0 deletions

163
toh_visualizer.c Normal file
View file

@ -0,0 +1,163 @@
/*----------------------------------------------------------
* HTBLA-Leonding / Class: n/a
* ---------------------------------------------------------
* Exercise Number: 09
* Title: Tower of Hanoi Visualizer
* Author: S. Schraml
* Due Date: n/a
* ----------------------------------------------------------
* Description:
* Implementation of ToH Visualizer.
* ----------------------------------------------------------
*/
#include "toh_visualizer.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include "config.h"
/* The encapsulated visualizer data */
struct VisData {
bool disabled;
unsigned short refresh_line_count;
unsigned short disk_count;
int offset;
int board_oversize;
int left_rod_pos;
int middle_rod_pos;
int right_rod_pos;
int last_move_count;
int total_move_count;
char* last_msg;
unsigned short last_disk_count_left;
unsigned short last_disk_count_middle;
unsigned short last_disk_count_right;
};
/* The visualizer instance */
static struct VisData vis_data = {0};
/* Provides the number output lines for a configured game. */
static void _print_new_line() {
vis_data.refresh_line_count++;
printf("\n");
}
/* Prints the given disk on the given rod or a 'rod' marker if no disk is given */
static void _print_centered_disk(Disk disk, int center) {
char symbol = '|';
int width = 1;
/* determine disk properties */
if (td_is_valid(disk)) {
width = 2 * td_get_size(disk) - 1;
symbol = '#';
}
printf("\033[%dG", center - (width / 2)); /* set the cursor to the left border of the disk */
for (int c = 0; c < width; c++) {
printf("%c", symbol);
}
}
/* Prints the bottom line of the board. */
static void _print_board() {
if (vis_data.disk_count > 0) {
printf("\033[2K"); /* clear current line */
printf("\033[%dG", vis_data.offset); /* set cursor to end of offset */
int board_width = vis_data.left_rod_pos + vis_data.right_rod_pos + 2 * vis_data.board_oversize;
for (int i = 0; i < board_width; i++) {
printf("=");
}
_print_new_line();
}
}
/* Prints the status line */
static void _print_status_line(unsigned int move_count) {
printf("\033[2K"); /* clear current line */
printf("\033[%dG", vis_data.offset); /* set cursor to end of offset */
printf("Move %4u of %u", move_count, vis_data.total_move_count);
_print_new_line();
}
/* Prints the message line */
static void _print_message(char* msg) {
printf("\033[2K"); /* clear current line */
printf("\033[%dG", vis_data.offset); /* set cursor to end of offset */
if (msg != 0) {
printf("%s", msg);
}
_print_new_line();
}
/* Prints the game: disks and board */
static void _print_game(TohBoard board, unsigned int move_count, char* msg) {
printf("\033[%dA", vis_data.refresh_line_count); /* move cursor to the first line of the game output */
vis_data.refresh_line_count = 0;
_print_new_line(); /* print an empty heading line */
for (int disk_idx = vis_data.disk_count; disk_idx >= 0; disk_idx--) {
printf("\033[2K"); /* clear current line */
int offset = vis_data.offset + vis_data.board_oversize;
_print_centered_disk(tb_get_disk(board, LEFT, disk_idx), offset + vis_data.left_rod_pos);
_print_centered_disk(tb_get_disk(board, MIDDLE, disk_idx), offset + vis_data.middle_rod_pos);
_print_centered_disk(tb_get_disk(board, RIGHT, disk_idx), offset + vis_data.right_rod_pos);
_print_new_line();
}
_print_board(vis_data.disk_count + 2);
_print_status_line(move_count);
_print_message(msg);
_print_new_line(); /* blank line */
}
void toh_init_visualizer(unsigned short disk_count) {
if (disk_count > 0) {
vis_data.refresh_line_count = 0;
vis_data.disk_count = disk_count;
vis_data.total_move_count = pow(2, disk_count) - 1;
vis_data.offset = VIS_BOARD_OFFSET;
vis_data.board_oversize = 2;
int rod_distance = 2 * disk_count - 1 + 2; /* width of the largest disk + 1 gap on each side */
vis_data.left_rod_pos = rod_distance / 2 ;
vis_data.middle_rod_pos = vis_data.left_rod_pos + rod_distance;
vis_data.right_rod_pos = vis_data.middle_rod_pos + rod_distance;
}
}
void toh_disable_visualizer(bool disable) {
vis_data.disabled = disable;
}
void toh_visualize(TohBoard board, unsigned int move_count) {
toh_visualize_with_msg(board, move_count, 0);
}
void toh_visualize_with_msg(TohBoard board, unsigned int move_count, char* msg) {
vis_data.last_move_count = move_count;
vis_data.last_msg = msg;
if (!vis_data.disabled) {
if (!tb_is_valid(board)) {
printf("invalid board given!");
} else {
_print_game(board, move_count, msg);
if (MOVE_DELAY > 0) {
usleep(MOVE_DELAY * 100 * 1000);
}
}
}
}
void toh_visualize_last() {
bool disabled = vis_data.disabled;
vis_data.disabled = false;
TohBoard board = tb_get_board();
toh_visualize_with_msg(board, vis_data.last_move_count, vis_data.last_msg);
vis_data.disabled = disabled;
}