CSCI1120 Assignment 5: Dual-Knight’s Tour Solved

35.00 $

Category:

Description

5/5 - (1 vote)

Introduction

In the game of chess, a knight (馬) is a piece moving like the letter L (「日」字) on a chessboard.

That is, it moves either two squares horizontally and one square vertically, or two squares vertically and one square horizontally. A dual-knight’s tour is to put two knights on a chessboard, each making moves, such that they never visit a square more than once. For simplicity in this assignment, we use a smaller 6 × 6 chessboard. Note that the two knights can eventually end up in squares where both can have no more possible moves but other squares remain unvisited. Figure 1 shows one dualknight’s tour, in which both knights ♘ at (rol,col) = (5,4) and ♞ at (0,1) have no more moves eventually. You are going to write a program, using object-oriented programming, to let users put two knights somewhere on a chessboard and moves them until no more moves can be made.

col 0          1          2          3          4          5 row

Figure 1: An example 𝟔×𝟔 dual-knight’s tour. The symbols and denotes the starting positions of the two knights.

Program Specification

You have to write your program in two source files DualKnightsTour.cpp and tour.cpp. The former is the implementation of the class DualKnightsTour, while the latter is a client program of class DualKnightsTour which performs the program flow. You are recommended to finish the DualKnightsTour class first before writing the client program. When you write the DualKnightsTour class, implement the member functions and test them individually one by one. Your two files will be graded separately, so you should not mix the functionalities of the two files.

Class DualKnightsTour (DualKnightsTour.cpp)

You are given the interface of the DualKnightsTour class in the header file DualKnightsTour.h. Do not modify this header file. Descriptions of the class are given below.

class DualKnightsTour { public:

DualKnightsTour(int r1, int c1, int r2, int c2);     void print() const;     bool isValid(char knight, int r, int c) const;     bool hasMoreMoves() const;

    bool move(char knight, int r, int c); private:

char board[6][6];     int posR1, posC1, posR2, posC2;     int steps1, steps2;     int consec1, consec2;

};

Private Data Members

char board[6][6];

The configuration of a dual-knight’s tour is represented by a 6 × 6 two-dimensional char-array. The elements board[0][0], board[0][5], board[5][0], and board[5][5] denote the top-left, top-right, bottom-left, and bottom-right corners of the board respectively. Each array element stores either a dot ‘.’ or a letter ‘A’–‘Z’/‘a’–‘z’. A dot ‘.’ means that the square was not visited by any knight before. Uppercase letters ‘A’–‘Z’ denote the move sequence of the one knight ♘: A à B à C à …, where ‘A’ is the starting position of ♘. Lowercase letters ‘a’–‘z’ denote similarly for the other knight ♞. For example, the tour in Figure 1 would be stored in the array board as shown in Figure 2.

col 0          1          2          3          4          5 row

. i . B I .
. A J E . b
h F f c C H
. K D G a d
. g M e . .
L . . . N .

0

1

2

3

4

5

Figure 2: The contents of data member board for the dual-knight’s tour in Figure 1.

int posR1, posC1, posR2, posC2;

Denote the current positions of the two knights on the chessboard. (posR1,posC1) is the current position of ♘, while (posR2,posC2) is the current position of ♞.

int steps1, steps2;

The data members steps1 and steps2 store respectively the number of moves that ♘ and ♞ have already done since the beginning.

int consec1, consec2;

To balance the two knights, we restrict that one knight cannot move three consecutive steps. That is, if a knight has moved twice consecutively, then the next move must be by the other knight. The data members consec1 and consec2 store the number of consecutive moves by ♘ and ♞ respectively.

Public Constructor and Member Functions

DualKnightsTour(int r1, int c1, int r2, int c2);

This constructor creates a dual-knight’s tour where the knights ♘ and ♞ are initially positioned at

(r1,c1) and (r2,c2) respectively. You have to set all array elements of the data member board as ‘.’ (unvisited) except the initial position, which should be set as ‘A’ for ♘ and ‘a’ for ♞. You also have to set the data members (a) posR1, posC1, posR2, and posC2 using the parameters r1, c1, r2, and c2 respectively, and (b) all the other data members as 0. You can assume that parameters r1, c1, r2, and c2 are always in [0 … 5], and the two positions are always different.

void print() const;

Prints the configuration of the dual-knight’s tour in the format shown in Figure 3. Note that the current positions of ♘ and ♞ are specially printed as @ and # respectively. (The actual board contents would still be letters; they are just printed specially to easily identify the current positions.)

  • 1 2 3 4 5 0 . # . B I .
  • . A J E . b
  • h F f c C H
  • . K D G a d 4 . g M e . .

5 L . . . @ .

Figure 3: Printing format of a dual-knight’s tour.

bool isValid(char knight, int r, int c) const;

Checks whether the parameter knight in the tour can be moved from its current position to the destination at (r,c). Note that the knight is not actually moved in this member function; it just checks if the move is valid or not. It should return true if all the following conditions are satisfied:

  • knight is either ‘@’ or ‘#’ (meaning ♘ and ♞ respectively);
  • r and c form a proper position (0 ≤ r,c < 6);
  • the proposed destination is an unvisited square;
  • the proposed move is not a third consecutive one for the same knight; Ø the destination is an L-shape move.

If any of the above conditions is false, the member function should return false.

bool hasMoreMoves() const;

Checks whether either knight has more possible moves to make. This member function should return true if at least one knight can make at least one valid move; and should return false otherwise. This member function can be implemented by calling isValid(…) several times.

bool move(char knight, int r, int c);

Tries to move the parameter knight from its current position to the destination at (r,c). This member function should call isValid(…) in its implementation to verify whether the move can actually be made. If the destination forms a valid move, this member function should update all related data members to reflect the corresponding knight’s change of position, and returns true. Otherwise (that is, the move is invalid), this member function updates nothing and returns false.

(For example, a valid move by ♘ should: (a) update its move sequence and its current position, (b) increment steps1 and consec1, (c) reset consec2 to 0, and (d) return true.)

Client Program (tour.cpp)

Your main program is a client of the DualKnightsTour class. You create a DualKnightsTour object here and call its member functions to implement the following program flow.

  1. The program starts with prompting the user to enter the two knights’ starting positions. You can assume that this user input is always four integers, where the first two inputs are the row and column of ♘ (@), and the next two inputs are the row and column of ♞ (#).
  2. If either input position is invalid (row or column outside [0 … 5]) or the two positions coincide, display a warning and go back to step 1.
  3. Create a DualKnightsTour object using the input positions.
  4. Prompt the user to make a knight’s move. You can assume that the input is always a character followed by two integers, in which the character is the knight and the integers are the destination of the move. You need to check if a user input is valid or not. (See definition in the description of the isValid(…) member function of DualKnightsTour) You should call the isValid(…) or move(…) member functions to do the checking here.
  5. If the input is valid, you should move the corresponding knight to the destination. Otherwise, you should print a warning message and go back to step 4.
  6. After moving a knight, check if there are still more possible moves. (At least one knight can make at least one move.) If so, you should go back to step 4 to obtain the next user input destination.
  7. When there are no more possible moves, display the message “No more moves!”.

Some Points to Note

  • You cannot declare any global variables in all your source files (except const ones).
  • You can define extra functions in any source files if necessary. However, extra member functions (instance methods), no matter private or public, are not

Program Output

The following shows some sample output of the program. The blue text is user input and the other text is the program output. You can try the provided sample program for other input. Your program output should be exactly the same as the sample program (i.e., same text, same symbols, same letter case, same number of spaces, etc.). Otherwise, it will be considered as wrong, even if you have computed the correct result. Note that in the program output, only the chessboard is printed from the DualKnightsTour class (DualKnightsTour.cpp). All other program output (the prompts, warnings, ending message) are printed from the client program (tour.cpp).

Knights’ starting positions (row1 col1 row2 col2): 1 6 3 4↵

Invalid position(s)!

Knights’ starting positions (row1 col1 row2 col2): 1 1 -1 3↵

Invalid position(s)!

Knights’ starting positions (row1 col1 row2 col2): 2 3 2 3↵

Invalid position(s)!

Knights’ starting positions (row1 col1 row2 col2): 1 1 3 4↵

0        1 2 3 4 5 0 . . . . . .

1        . @ . . . .

2        . . . . . .

3        . . . . # .

4        . . . . . .

5        . . . . . .

 

Move (knight row col): @ -1 2↵

Invalid move!

Move (knight row col): @ 0 4↵

Invalid move!

Move (knight row col): @ 0 3↵

0        1 2 3 4 5 0 . . . @ . .

1        . A . . . .

2        . . . . . .

3        . . . . # .

4        . . . . . .

5        . . . . . .

Move (knight row col): @ 2 4↵

0        1 2 3 4 5 0 . . . B . .

1        . A . . . .

2        . . . . @ .

3        . . . . # .

4        . . . . . .

5        . . . . . .

Move (knight row col): @ 3 2↵

Invalid move!

Move (knight row col): # 1 5↵

0        1 2 3 4 5 0 . . . B . .

1        . A . . . # 2 . . . . @ .

3  . . . . a .

4  . . . . . .

5  . . . . . .

Move (knight row col): # 0 3↵

Invalid move!

Move (knight row col): @ 3 2↵

0        1 2 3 4 5 0 . . . B . .

1        . A . . . # 2 . . . . C .

3  . . @ . a .

4  . . . . . .

5  . . . . . .

 

⋮    (Some moves are skipped to save space. See Blackboard for full version.)

0        1 2 3 4 5 0 . . . B I .

1        . A J E . b

2        . F f c C H

3        . K D G a d 4 . # . e . .

5 @ . . . . .

Move (knight row col): # 2 0↵

 

0        1 2 3 4 5 0 . . . B I .

1        . A J E . b

2        # F f c C H

3        . K D G a d 4 . g . e . .

5 @ . . . . .

Move (knight row col): @ 4 2↵

0        1 2 3 4 5 0 . . . B I .

1        . A J E . b

2        # F f c C H

3        . K D G a d 4 . g @ e . .

5 L . . . . .

Move (knight row col): # 0 1↵

0        1 2 3 4 5 0 . # . B I .

1        . A J E . b

2        h F f c C H

3        . K D G a d 4 . g @ e . .

5 L . . . . .

Move (knight row col): @ 5 4↵

0        1 2 3 4 5 0 . # . B I .

1        . A J E . b

2        h F f c C H

3        . K D G a d 4 . g M e . .

5 L . . . @ .

No more moves!

 

  • assg5.zip