/*---------------------------------------------------------- * HTBLA-Leonding / Class: 2IHIF * --------------------------------------------------------- * Exercise Number: 09 * Title: Tower of Hanoi Disk ADT implementation * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implementation of toh_board.h. * ---------------------------------------------------------- */ #include "toh_board.h" #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); 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]; }