Logic Magnets is a Python-based board game implemented using Tkinter for the GUI and incorporates algorithms like Breadth-First Search (BFS) and Depth-First Search (DFS) for solving game puzzles. The game consists of movable magnets with different effects on other pieces on a grid board. The goal is to position all magnets on their respective target locations.
-
Red Magnets : Can be moved and have a pulling effect on other magnets in the same row and column.
-
Purple Magnets : Can be moved and have a pushing effect on other magnets in the same row and column.
-
Gray Magnets : Are immovable but can be pushed or pulled by Red and Purple magnets.
-
Move the magnets on the board to reach the designated target positions.
-
Utilize BFS and DFS algorithms to find solutions automatically.
1.Piece
Class
Represents each game piece with:
-
piece_type (
Red
,Purple
,Gray
) -
position (row, column)
2.Board
Class
Handles the board state:
-
n : Number of rows.
-
m : Number of columns.
-
pieces : Dictionary mapping piece positions to their respective
Piece
objects. -
targets : List of target positions.
-
grid : 2D list representing the board layout.
3.GameState
Class
Tracks the current state of the game:
-
board : An instance of the
Board
class. -
history : A list to store previous board states for undo functionality.
4.GameGUI
Class
Implements the graphical user interface using Tkinter:
- Displays the board, handles mouse interactions, and provides control buttons (Reset, Undo, Solve).
The BFS algorithm is used to find the shortest sequence of moves to reach the final state.
-
Queue (
deque
) : Stores tuples of the current game state and the list of moves taken to reach it. -
Visited Set : Tracks visited states to avoid revisiting.
-
Returns a list of moves if a solution is found.
-
Returns
None
if no solution exists.
-
Initialize the queue with the initial game state and an empty move list.
-
Use a set to store the unique state representations.
-
Dequeue an element, check if it's a final state.
-
If not, generate possible moves for each movable piece (Red or Purple).
-
Apply each move to generate a new state.
-
If the new state hasn't been visited, enqueue it with the updated move list.
-
Repeat until the queue is empty or a solution is found.
The DFS algorithm explores possible moves to find a solution, prioritizing depth over breadth.
-
Stack (List) : Used instead of a queue to implement the LIFO principle of DFS.
-
Visited Set : Tracks visited states to avoid cycles.
-
Returns a list of moves if a solution is found.
-
Returns
None
if no solution exists.
-
Use a stack to store the game state and move list.
-
Check if the current state is the final state.
-
If not, generate possible moves for movable pieces.
-
Apply each move and check if the new state has been visited.
-
If not, push the new state onto the stack.
-
Continue exploring until a solution is found or the stack is empty.
Each board state is represented by a tuple of pieces' positions and types:
tuple((piece.position, piece.piece_type) for piece in state.board.pieces.values())
This representation ensures that states are uniquely identifiable, which is crucial for detecting repeated states in BFS and DFS algorithms.
-
Reset Board : Resets the board to its initial state.
-
Undo Move : Reverts to the previous game state.
-
Solve using BFS : Automatically solves the puzzle using the BFS algorithm.
-
Solve using DFS : Automatically solves the puzzle using the DFS algorithm.
-
Move Log : Displays a history of moves made during the game.
-
Red Magnet (R) :
R(2, 3) to (2, 1)
-
Purple Magnet (P) :
P(1, 1) to (1, 3)
-
The
history_stack
in the GUI stores past game states for the Undo feature. -
Each move generates a new
GameState
object, which includes the updated board and history.