In a nutshell
A cache is small, so every block of memory needs a rule for where it is allowed to sit. The address is split into three parts: the offset picks the byte inside a block, the index picks which slot (set) to look in, and the tag confirms whether the block sitting there is the one you wanted. Direct-mapped gives each block exactly one slot — fast, but two blocks wanting that slot keep evicting each other; set-associative and fully associative give each block several slots, trading more tag comparisons for fewer collisions.