Assignment 2: SpinOut
Objectives
- to create a class
Introduction
SpinOut is a version of the Chinese Ring Puzzle. SpinOut has 7 disks that can be rotated between a vertical or horizontal orientation. Only one disk can be rotated at once and a disk can only be rotated if the one immediately to its right is vertical and all the ones to the right of that are horizontal. The puzzle typically starts with all disks in the vertical orientation and the puzzle is solved when all disks are in the horizontal orientation.Assignment
Create a class and amain
that enables us to play Spin Out interactively or check
a solution.
First, create a class called SpinOut
in the cs427_527
namespace. The
header file must be named "spinout.hpp" and the implementation file
must be named "spinout.cpp"; those must be the only two files
necessary to use the SpinOut
class and
those files must compile cleanly with the -Wall -pedantic -std=c++17
compiler options.
The SpinOut
class must have the following members that behave
as follows.
- A constructor
SpinOut()
that initializes the puzzle so all disks are vertical. - A constructor
SpinOut(const std::string& s)
that initializes the puzzle according to the given string. The string will consist of 7 characters, each of which is '/' or '-' respectively to indicate a disk that is intially vertical or horizontal respectively. - A method
bool isLegalMove(int i) const
which takes an integer between 0 and 6 inclusive and determines whether it is possible to rotate that disk in the current object to its other orientation. Disks are numbered from left to right starting with zero. - A method
void makeMove(int i)
which takes an integer for whichisLegalMove
returns true and rotates the indicated disk in the current object into its other orientation. - A method
int totalMoves() const
which counts the number of legal moves performed on the current object since it was created. - A method
bool isSolved() const
which determines if the current object is in its solved configuration (all disks rotated horizontally). - A method
std::string toString() const
which returns a string representation of the current object in the same format as that passed to the second version of the constructor. - A
static const int SIZE
that is initialized to 7.
The string
constructor and isLegalMove
should
throw a std::invalid_argument
or std::out_of_range
exception if their preconditions are violated.
The behavior of the other methods when the arguments violate the preconditions
stated above is undefined and your submissions will not be tested on such
cases.
Second, create a program with an executable named SpinOut
that allows users to
play interactively or check a solution depending
on the command-line arguments.
To play interactvely, the first command-line
argument will be -i
and the second,
if present, will be a 7-character string of
-
and /
giving the starting configuration in the form required
by the SpinOut
class constructor;
if the second argument is not present then the
game should start with all disks vertical.
In interactive mode, the program should
read from standard input integers representing the disk to rotate. There will be one
integer per line of input with no leading and trailing whitespace. If the move is not
legal then the message illegal move
should be printed to standard output.
The resulting state of the puzzle should be printed to standard output at the beginning
of the program and after each legal move. The program should continue
to read input
until the puzzle is solved or there are no more integers available as input (the user
gives up). If
a move leaves the puzzle in the
solved configuration then then the total number of legal moves made
should be printed as the last line of
standard output after the line that displays the
solved configuration as the result of the move.
The format should be n moves
where n
is replaced with the number of moves.
In non-interactive mode, the first command-line argument may be a 7-character string
giving the starting configuration in the format required by the constructor
and the following zero or more arguments will be the indices of disks in
the range 0 to 6 inclusive indicating the sequence of disks to rotate,
in the order they should be rotated, given as a sequence of decimal digits.
If the first argument is not a starting configuration then the default configuration
///////
should be used and all the arguments
will be indices as described above.
The program should print a single
line to standard output, where the line is of the form
SpinOut: illegal move n in position m for config
if one of the moves in the sequence is
illegal where m
is position within the sequence of moves of the first illegal
move (the first move is position 1), n
is the index of the disk that could
not be moved, and config
is the configuration of the puzzle before
the attempted illegal move in the format returned by toString
;
SOLVED
if the sequence of moves ends with the puzzle solved; or,
otherwise, the final state of the puzzle in the format returned by toString
.
In both interactive and non-interactive modes, the command-line arguments will not contain whitespace.
In both modes, there must not be anything written to standard output or standard error beyond what is specified above. And unless otherwise specified, your program should behave gracefully if any any input, whether in interactive mode or on the command-line, is not as specified (and note that terminating because of an uncaught exception is not considered a graceful exit).
Unit Tests
There is also file spinout_unit.cpp
in
/c/cs427/hw2/Required
that contains a
main
function that runs unit tests on your SpinOut
class. Your makefile should build an executable called Unit
from that file and whatever other files you created that are necessary
to use your SpinOut
class. Your makefile must assume that
the spinout_unit.cpp
file is in the current directory; do not
hard-code the directory containing that file. There will be private
unit tests added to spinout_unit.cpp
for grading.
Example
The following is a transcript of running theSpinOut
and Unit
programs in various ways.
[jrg94@frog SpinOut]$ ./SpinOut -i /////// 6 //////- 5 illegal move 4 ////-/- [jrg94@frog SpinOut]$ ./SpinOut -i ------/ ------/ 6 ------- 1 moves [jrg94@frog SpinOut]$ ./SpinOut ------/ 6 SOLVED [jrg94@frog SpinOut]$ ./SpinOut 6 4 5 SpinOut: illegal move 5 in position 3 for ////-/- [jrg94@frog SpinOut]$ ./SpinOut 6 4 6 5 6 ////--- [jrg94@frog SpinOut]$ for i in `seq 0 6`; do ./Unit $i; done solved: 0 total moves: 0 isLegalMove(4): 0 isLegalMove(5): 1 isLegalMove(6): 1 ------/ spinning 6 gives ------- caught exception
Submissions
Submit whatever source code (.cpp and .hpp) files you created and a makefile that builds executables calledSpinOut
and Unit
when called with no arguments and the individual executables when called
with their respective names (so make SpinOut
should make
the SpinOut
executable).
Also submit your log file as described on the assignment
index page.