1 /* 2 SPDX-FileCopyrightText: 2009-2014 Graeme Gott <graeme@gottcode.org> 3 4 SPDX-License-Identifier: GPL-3.0-or-later 5 */ 6 7 #ifndef PEGE_PUZZLE_H 8 #define PEGE_PUZZLE_H 9 10 #include <QHash> 11 #include <QPoint> 12 #include <QSize> 13 14 #include <random> 15 16 /** 17 * Contains the layout of holes and pegs. 18 * 19 * This class generates and contains a board layout. When it generates a 20 * layout it tracks which holes are the furthest left and up, right and down 21 * so that the size of the layout can be quickly retrieved. 22 */ 23 class Puzzle 24 { 25 public: 26 /** Constructs an empty layout. */ 27 explicit Puzzle(); 28 29 /** Destroys the layout. */ 30 virtual ~Puzzle(); 31 32 /** Returns the layout as a hash of points describing the holes. */ 33 QHash<QPoint, bool> holes() const; 34 35 /** Returns the top left corner of the layout. */ 36 QPoint position() const; 37 38 /** Returns the size of the layout. */ 39 QSize size() const; 40 41 /** 42 * Creates a layout. 43 * 44 * @param seed the seed passed to the random number generator 45 * @param difficulty how hard of a layout to create 46 */ 47 void generate(int seed, int difficulty); 48 49 protected: 50 /** 51 * Creates a layout with a single group of pegs. 52 * 53 * @param pegs how many pegs to create 54 */ 55 virtual void generate(int pegs); 56 57 /** 58 * Returns @c true if @p hole has no peg. 59 * 60 * @param hole the hole to check 61 */ 62 virtual bool isAvailable(const QPoint& hole) const; 63 64 /** 65 * Randomly shuffles a list of pegs. 66 * 67 * @param pegs the pegs to shuffle 68 */ 69 virtual void shuffle(QList<QPoint>& pegs); 70 71 /** 72 * Determines where to move next. 73 * 74 * @param start_hole the hole that is moved from 75 * @param jumped_hole the hole between the start and end holes 76 * @param end_hole the hole that is moved to 77 */ 78 bool findNextMove(const QPoint& start_hole, QPoint& jumped_hole, QPoint& end_hole); 79 80 /** 81 * Creates a group of pegs. 82 * 83 * @param start initial peg 84 * @param loops how many pegs to create 85 */ 86 QPoint findMoves(const QPoint& start, int loops); 87 88 /** 89 * Returns whether or not the @p hole has a peg. 90 * 91 * @param hole the hole to check 92 * @return @li @c 0 if the hole is empty 93 * @li @c 1 if the hole has a peg 94 * @li @c -1 if the hole doesn't exist 95 */ 96 int hasPeg(const QPoint& hole) const; 97 98 /** 99 * Sets if the @p hole has a peg. 100 * 101 * @param hole the hole to specify 102 * @param value what to put at the hole 103 */ 104 void setHasPeg(const QPoint& hole, bool value); 105 106 private: 107 QHash<QPoint, bool> m_holes; /**< hash of holes */ 108 QList<QPoint> m_directions; /**< list of directions to check */ 109 QPoint m_top_left; /**< top left hole */ 110 QPoint m_bottom_right; /**< bottom right hole */ 111 std::mt19937 m_random; /**< random number generator */ 112 }; 113 114 /** Puzzle that has branches between groups of pegs. */ 115 class PuzzleBranch : public Puzzle 116 { 117 protected: 118 /** 119 * Creates a layout with branches between the groups. 120 * 121 * @param pegs how many pegs to create 122 */ 123 void generate(int pegs) override; 124 }; 125 126 /** Puzzle that doesn't reuse or shuffle any holes. */ 127 class PuzzleLine : public Puzzle 128 { 129 protected: 130 /** 131 * Returns true if @p hole does not exist yet. 132 * 133 * @param hole the hole to check 134 */ 135 bool isAvailable(const QPoint& hole) const override; 136 137 /** 138 * Override parent function to prevent shuffling the pegs. 139 * 140 * @param pegs the pegs to shuffle 141 */ 142 void shuffle(QList<QPoint>& pegs) override; 143 }; 144 145 #endif // PEGE_PUZZLE_H 146