From 59a36fe5f3774e585552f30d6dc4fe496d004c81 Mon Sep 17 00:00:00 2001 From: MarcUs7i Date: Sun, 19 Jan 2025 09:34:55 +0100 Subject: [PATCH] completed ToH board ADT implementation --- toh_board.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++ toh_board.h | 10 ++-- 2 files changed, 135 insertions(+), 4 deletions(-) diff --git a/toh_board.c b/toh_board.c index f1a9fb3..423a74a 100644 --- a/toh_board.c +++ b/toh_board.c @@ -14,7 +14,136 @@ #include "config.h" #include "toh_disk.h" +#include + +#ifdef NULL +#undef NULL +#define NULL ((void *)0) +#endif /** Abstraction of a rod type */ /* Hint: Define a type 'Rod' as a pointer to Disk for usage in exchange with Disk array */ + +struct TohBoardData { + Rod rods[3][MAX_DISKS]; +}; + +static TohBoard static_board = NULL; + +/** + * Provides the instance of the 'Tower of Hanoi' board. + * Exactly one instance is supported. + * + * @return TohBoard The board instance. + */ +TohBoard tb_get_board() { + if (tb_is_valid(static_board)) { + return static_board; + } + + static_board = (TohBoard)calloc(sizeof(struct TohBoardData), 1); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < MAX_DISKS; j++) { + static_board->rods[i][j] = NULL; + } + } + return static_board; +} + +/** + * Removes all disks from any rod of the given board. + * + * @param board The board instance in focus. + */ +void tb_clear_board(TohBoard board) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < MAX_DISKS; j++) { + board->rods[i][j] = NULL; + } + } +} + +/** + * Determines whether or not the given board is valid. + * A board is NOT valid, if it is 0. + * + * @param board The board to evaluate. + * @return If the given board is valid, false otherwise. + */ +bool tb_is_valid(TohBoard board) { + return board != NULL; +} + +/** + * Provides the top-most disk of the given rod and removes it from this rod. + * + * @param board The board instance in focus. + * @param rodName The rod from which the disk shall be taken and removed. + * @return The removed disk or 0, if no disk was on the rod. + */ +Disk tb_pop_disk(TohBoard board, RodName rodName) { + if (!tb_is_valid(board)) { + return NULL; + } + + Disk disk = NULL; + for (int i = MAX_DISKS - 1; i >= 0; i--) { + if (board->rods[rodName][i] != NULL) { + disk = board->rods[rodName][i]; + board->rods[rodName][i] = NULL; + break; + } + } + + return disk; +} + +/** + * Applies the given disk to the given rod, if this + * is allowed according to the rules. + * + * @param board The board instance in focus. + * @param rodName The rod on which the disk shall be placed. + * @param disk The disk to place on the rod. + * @return True if the disk could be legally placed on the rod + * (move is allowed and disk is valid), false otherwise. + */ +bool tb_push_disk(TohBoard board, RodName rodName, Disk disk) { + if (!tb_is_valid(board) || !td_is_valid(disk)) { + return false; + } + + for (int i = 0; i < MAX_DISKS; i++) { + if (board->rods[rodName][i] == NULL) { + // Check if it is at the bottom or if the it is smaller than the one below + if (i > 0 && !td_is_smaller(board->rods[rodName][i - 1], disk)) { + return false; + } + + board->rods[rodName][i] = disk; + return true; + } + } + + return false; +} + +/** + * Provides the disk from the named rod at the given position. + * + * @param board The board instance in focus. + * @param rodName The rod on which the disk shall be placed. + * @param idx The index of the desired disk on the named rod. + * Index 0 addresses the bottom-most disk. + * @return The addressed disk or 0, if not disk is located on the + * index position of the named rod. + */ +Disk tb_get_disk(TohBoard board, RodName rodName, unsigned short idx) { + if (!tb_is_valid(board) || idx >= MAX_DISKS) { + return NULL; + } + + // no need to check, as everything is going to be initalized with 0 + return board->rods[rodName][idx]; +} \ No newline at end of file diff --git a/toh_board.h b/toh_board.h index 801c93a..5955e4b 100644 --- a/toh_board.h +++ b/toh_board.h @@ -26,7 +26,9 @@ typedef enum { LEFT, MIDDLE, RIGHT -} Rod; +} RodName; + +typedef Disk Rod; /** Declares type for the 'Tower of Hanoi' board */ typedef struct TohBoardData* TohBoard; @@ -62,7 +64,7 @@ bool tb_is_valid(TohBoard board); * @param rodName The rod from which the disk shall be taken and removed. * @return The removed disk or 0, if no disk was on the rod. */ -TohBoard tb_pop_disk(TohBoard board, Rod rodName); +Disk tb_pop_disk(TohBoard board, RodName rodName); /** * Applies the given disk to the given rod, if this @@ -74,7 +76,7 @@ TohBoard tb_pop_disk(TohBoard board, Rod rodName); * @return True if the disk could be legally placed on the rod * (move is allowed and disk is valid), false otherwise. */ -bool tb_push_disk(TohBoard board, Rod rodName, TohDisk disk); +bool tb_push_disk(TohBoard board, RodName rodName, Disk disk); /** * Provides the disk from the named rod at the given position. @@ -86,6 +88,6 @@ bool tb_push_disk(TohBoard board, Rod rodName, TohDisk disk); * @return The addressed disk or 0, if not disk is located on the * index position of the named rod. */ -TohDisk tb_get_disk(TohBoard board, Rod rodName, unsigned short idx); +Disk tb_get_disk(TohBoard board, RodName rodName, unsigned short idx); #endif \ No newline at end of file