Re: aem7ac shot by a foreigner in Brentwood tonight! (881582) | |||
Home > OTChat | |||
[ Read Responses | Post a New Response | Return to the Index ] |
|
Re: aem7ac shot by a foreigner in Brentwood tonight! |
|
Posted by SelkirkTMO on Sat Dec 3 20:29:17 2011, in response to Re: aem7ac shot by a foreigner in Brentwood tonight!, posted by Amanda on Sat Dec 3 17:42:05 2011. I'm banned for life. :)------------------------------------ // plays the triangular pegboard puzzle found at cracker barrel // // board usually starts out as: // // 0 // 1 1 // 1 1 1 // 1 1 1 1 // 1 1 1 1 1 // // but can start with any single pin removed // // game ends with a single pin in the pegboard (i.e., a 1) // successive moves are showns as complete boards // a jump is like in checkers, pin jumps inline neighbor into empty hole // and "captures" the jumped over pin (neighbor) // // internal struct is built out of vector (rows) of bitset (columns) // indexing is as follows: // // 0,0 // 1,0 1,1 // 2,0 2,1 2,2 // 3,0 3,1 3,2 3,3 // 4,0 4,1 4,2 4,3 4,4 // // objects are: // // PegBoard (the board itself with pins indicating position occupied) // Position (a pair of row/col position on the board, or a relative position) // Move (a pair of Positions, one absolute position, and other a direction // to move toward) // GameTree (a tree starting from initial PegBoard that will contain all the // winning successive board positions as children, representing // the next logical board position from give one) // // Optionally a PegBoard can be displayed as a decimal number (boardCode) // by adding the bits making up that board. // // 2^14 = 0,0; 2^13 = 1,0; 2^12 = 1,1; ... 2^0 = 4,4; then summed // // thus a full board with pin 0,0 out is code: 16383 // this is useful for analysing game board flows for patterns. // For example, staring with pin 0,0 out, there are 16128 solutions where // the last pin standing is 4,2. // #include #include #include #include #include #include #include using namespace std; static const bool showBoardCode = false; static const int BOARDSIZE = 5; struct Position { Position() : row_(0), col_(0) {} Position(int row, int col) : row_(row), col_(col) {} bool move(const Position& incr); Position& operator+=(const Position& incr); Position& operator*=(int incr); static bool valid(const Position& pos); friend ostream& operator<<(ostream& os, const Position& pos); int row_; int col_; }; ostream& operator<<(ostream& os, const Position& pos) { os << pos.row_ << ',' << pos.col_; return os; } bool Position::valid(const Position& pos) { if (pos.row_ >= BOARDSIZE) return false; if (pos.row_ < 0) return false; if (pos.col_ < 0) return false; if (pos.col_ >= BOARDSIZE) return false; if (pos.col_ > pos.row_) return false; return true; } bool Position::move(const Position& incr) { Position current(*this); current += incr; if (!valid(current)) return false; *this = current; return true; } Position& Position::operator+=(const Position& incr) { row_ += incr.row_; col_ += incr.col_; return *this; } Position& Position::operator*=(int incr) { row_ *= incr; col_ *= incr; return *this; } // valid movement graph static const Position MOVEMENT[] = { Position(-1,-1), Position(-1,+0), Position(+1,+0), Position(+1,+1), Position(+0,-1), Position(+0,+1) }; static const int NUMMOVEMENTS = sizeof(MOVEMENT)/sizeof(Position); struct Move { Move(const Position& peg, const Position& incr) : peg_(peg), incr_(incr) {} friend ostream& operator<<(ostream& os, const Move& m); Position peg_; Position incr_; }; ostream& operator<<(ostream& os, const Move& m) { os << "(" << m.peg_ << ":" << m.incr_ << ")"; return os; } class GameTree; class PegBoard { public: PegBoard(int startPinRow = 0, int startPinCol = 0); void possibleMoves(vector // bool play(const Move& currentMove, vector void play(const Move& currentMove, GameTree& parent) const; void jump(const Move& move); friend ostream& operator<<(ostream& os, const PegBoard& p); private: void flip(const Position& peg) { board_[peg.row_][peg.col_].flip(); } bool occupied(const Position& pos) const { return board_[pos.row_][pos.col_]; } int numPegs() const; vector< bitset }; class GameTree { public: GameTree(const PegBoard& p) : currentBoard_(p) {} void append(GameTree* g) { children_.push_back(g); } int numChildren() const { return children_.size(); } bool walk() { return GameTree::walk(*this); } private: static bool walk(GameTree& parent); PegBoard currentBoard_; list }; // to iterate is human, to recurse is divine bool GameTree::walk(GameTree& parent) { cout << parent.currentBoard_ << endl; list if (firstChild == parent.children_.end()) { cout << "========================" << endl; return true; } if (GameTree::walk(*(*firstChild))) { delete *firstChild; parent.children_.erase(firstChild); } return (parent.children_.begin() == parent.children_.end()); } PegBoard::PegBoard(int startPinRow, int startPinCol) { for (int i = 0; i < BOARDSIZE; ++i) { bitset for (int j = 0; j <= i; ++j) { b[j] = true; } board_.push_back(b); } board_[startPinRow][startPinCol] = false; } void PegBoard::possibleMoves(vector { moves.clear(); for (int i = 0; i < BOARDSIZE; ++i) { for (int j = 0; j <= i; ++j) { Position hole(i,j); if (occupied(hole)) continue; for (int m = 0; m < NUMMOVEMENTS; ++m) { Position move(hole); if (move.move(MOVEMENT[m]) && occupied(move) && move.move(MOVEMENT[m]) && occupied(move)) { Position direction(MOVEMENT[m]); direction *= -1; moves.push_back(Move(move, direction)); } } } } } int PegBoard::numPegs() const { int numPegs = 0; for (int i = 0; i < BOARDSIZE; ++i) { for (int j = 0; j <= i; ++j) { if (occupied(Position(i,j))) ++numPegs; } } return numPegs; } void PegBoard::jump(const Move& move) { Position peg(move.peg_); flip(peg); peg += move.incr_; flip(peg); peg += move.incr_; flip(peg); } #if 0 // to iterate is human, to recurse is divine bool PegBoard::play(const Move& currentMove, vector { PegBoard nextBoard(*this); nextBoard.jump(currentMove); if (nextBoard.numPegs() == 1) { goodMoves.push_back(currentMove); return true; } vector nextBoard.possibleMoves(moves); for (int i = 0; i < moves.size(); ++i) { if (nextBoard.play(moves[i], goodMoves)) { goodMoves.push_back(currentMove); return true; } } return false; } #endif // to iterate is human, to recurse is divine void PegBoard::play(const Move& currentMove, GameTree& parent) const { PegBoard nextBoard(*this); nextBoard.jump(currentMove); auto_ptr if (nextBoard.numPegs() == 1) { parent.append(node.release()); return; } vector nextBoard.possibleMoves(moves); for (int i = 0; i < moves.size(); ++i) { nextBoard.play(moves[i], *node); } if (node->numChildren() > 0) { parent.append(node.release()); } } ostream& operator<<(ostream& os, const PegBoard& p) { int boardCode = 0; for (int i = 0; i < BOARDSIZE; ++i) { os << setfill(' ') << setw(BOARDSIZE-i) << " "; for (int j = 0; j <= i; ++j) { os << p.board_[i][j] << ' '; boardCode <<= 1; if (p.board_[i][j]) boardCode |= 1; } os << endl; } if (showBoardCode) os << boardCode << endl; return os; } int main(int argc, char* argv[]) { int startPinRow = 0; int startPinCol = 0; if (argc == 3) { startPinRow = atoi(argv[1]); startPinCol = atoi(argv[2]); } PegBoard board(startPinRow, startPinCol); vector board.possibleMoves(moves); GameTree root(board); for (int i = 0; i < moves.size(); ++i) { board.play(moves[i], root); } while (!root.walk()) ; } |