代做CSCI1120 Introduction to Computing Using C++, Fall 2024/25 Assignment 4: Mathable代做C/C++编程
- 首页 >> DatabaseCSCI1120 Introduction to Computing Using C++, Fall 2024/25
Assignment 4: Mathable
Due: 23:59, Sat 2 Nov 2024
File name: mathable.cpp
mathable-game.cpp
mathable.h
Full marks: 100
Introduction
The objective of this assignment is to practice (1) the use of 1-D and 2-D arrays, and (2) the use of pointers for passing 1-D arrays as arguments between functions.
You will write a program to simulate a boardgame called Mathable, which is commonly described as being like playing Scrabble but using numbers instead of letters. Its detailed game rules can be found on websites like [1] [2] [3]. An iPad or iPhone app of this game is available on App Storeif you have interest to try it for better ideas on how to play the game. Here we give a brief introduction.
The boardgame consists of:
• Gameboard: a square gameboard of N × N cells or squares where players place their tiles.
• Tokens (or tiles): each tile or numbered token displays a 1-digit or 2-digit number.
• Racks (or token holders): each player owns a rack for privately holding a handful (R) of tokens.
• Bag: a bag contains all the rest of the tokens. A player can draw tokens from it to refill their rack after a turn or can swap (some of) the tokens on their rack with the ones in the bag randomly if they find it hard to forman equation on the board using their current tokens.
• Score pad: used to track players' scores throughout the game.
Note that a variant of the game tailored to younger children, known as Mathable Junior, consists of a smaller gameboard and fewer tokens. SeeTable 1below for their differences.
Game Board Representation
As we implement this game as a console application, the game board is represented by a text-based grid formed from characters | and _ as shown and compared in Figure 1 below.
Figure 1: A GUI screenshot of the Mathable app versus our text-based game board representation
Each cell in the grid is addressed by an Excel-like addressing scheme, e.g., the cell located at row 2 and column 3 is referred to by a cell address C2. The initial configuration of the game board has fixed four tokens, valued 1, 2, 3, 4, in the center of the board. Token 1 is located at G7, token 2 at H7, token 3 at G8, and token 4 at H8. In the program, we use a 2-D int array called board to store the tokens placed on the game board. Corresponding to these initial 4 tokens, we have:
board[6][6] = 1; board[6][7] = 2; board[7][6] = 3; board[7][7] = 4;
Game Logic
The game supports 2 to 4 players, who take turns to put their tokens onto the board to form. valid math equations and score the points indicated by the tokens. The one who attains the highest total score at the end of the game is the winner.
In each turn, the player can make a series of moves (at most R moves, where R is the rack size). In each move, the player chooses one token,c, from their rack and places it onto the board to form. a simple math equation with two adjacent tokens, a and b, already existent on the board:
a ? b = c
where? is one of the four arithmetic operators (+, −, ×, or ÷).
Recap the official game instruction: “A math equation is completed by adding, subtracting, multiplying or dividing two adjacent numbers putting a token with the result on the next empty square, be it to the right or left, below or above the two original tokens. Equations may be made horizontally or vertically, but never diagonally.”
For example, for the initial game board, if your rack has token 7, you can play it at cell F8 or cell I8 (refer toFigure 1) to form. the equation 3 + 4 = 7. If you don’thave token 7 but token 1, you can also put it at cell F8 or cell I8 because this can form. the equation 4 – 3 = 1. You can put it next to token 4 or token 3, on either side of the two tokens, it doesn't matter. Similarly, you may also put token 12 at these two cells to form. the equation 3 × 4 = 12. An equation can also be formed vertically. See
Figure 2 for more examples of valid positions for placing a token onto the board.
Figure 2: Example valid token placements
Remember that the token you are going to place is always the result of the math operation. It is illegal to place it between the two adjacent tokens (operands) as we can see in Figure 3. Equations are also never formed diagonally. A token placement is valid as long as it can form. at least one equation with two consecutively adjacent tokens in any of the 4 directions (left, right, above, below). See Figure 4. Now, placing token 7 between 3 and 4 is valid because it can forman equation with 2 and 5 vertically. For the example on the right, although 7 cannot form. an equation with 1 and 2 vertically, it does with 3 and 4 horizontally. So, it is valid to place token 7 there.
Figure 3: Example invalid token placements
Figure 4: More examples of valid token placements
Once a move is made, the player scores the points indicated on the token they just placed on the board. So, you can score higher points if you can find locations to place a larger token (usually the result of multiplication of two existing tokens) on the board.
Bonus for multiple equations: Another strategy to score higher is to gain bonus points due to simultaneously forming multiple equations by one move. If a token, when being placed, completes more than one equation, the points are gained for each equation completed. See an example in Figure 5, which is actually the first move (placing token 4 at cell H4) in Round 13 Player 1’sturn in the Mathable Junior sample run 1 logged on macOS (mathable-jr-run1-mac.txt).
Figure 5: One move completing 3 equations, scoring 12 points (3 times 4 points)
Total Score: The total amount of points earned per turn is the total sum of the points scored by all moves made (i.e., all tokens placed plus bonuses) in that turn.
Rack Refill: At the end of his turn, each player draws tokens randomly from the bag, to bring the number of tokens on their rack back toR (e.g., 7 in classical Mathable). If there are fewer tokens left in the bag than the empty slots on the rack to fill up, the player will take all the remaining tokens and the bag becomes empty. The next player cannot refill (or swap) tokens anymore.
Game-over Conditions: The game continues until (1) there are no tokens left in the bag, and one of the players has used up all the tokens on his rack, or until (2) no more equations can be made. Since detecting condition (2) is a bit clunky, our program design will give players an option (T) to terminate the game anytime they want to. When players see no more possible moves, one of them will select this option to determine the game winner. A draw game can happen if more than one players attain the same highest score.
Simplifying the Game
The original Mathable game board has two special types of cells called restriction squares and award squares. Restriction squares are those blue squares (inFigure 1GUI) marked with an addition, subtraction, multiplication or division sign. To occupy a square of this kind, the player must make an equation that corresponds to the sign of that square. For award squares,a purple square marked 2x doubles the amount of point of the token on that square, an orange square marked 3x triples the number of points. In this assignment, we will skip their implementation. So, there are no special cells in our program. Some tedious game rules below are also cancelled:
• “Extra Bonus. If a player manages to place all the tokens he has on his holder in one turn, he earns an extra bonus of 50 points.”
• “At the end of the game, each player deducts the value of the tokens still on his holder from the total amount of points accumulated during the game.
Program Specification
This section describes the basic requirements, starter code, player actions, some necessary functions, and program flow.
Basic Requirements
• Apart from our given global constants in the mathable.h header file, you cannot declare any global variables in all files.
• Your program is scalable to board size (8 ≤ N ≤ 14, even number only), player size (2 ≤ P ≤ 4), rack size (4 ≤ R ≤ 8), token amount (either T = 60 or T = 106), which could be changed at compile time (not hardcoded in the program code).
• You cannot use any vectors or self-defined classes (they will be used in later assignments).
Starter Code
• To help you get started, you are provided with all the required source files:
Filename |
What’s inside |
mathable.h |
Several global constants defining the board size, rack size, player count, total number of tokens and the function prototypes of the functions required by the client’s main() function. |
mathable.cpp |
The source file implementing all the functions needed by the game,e.g., printing the game board, rack, drawing tokens from bag, validating and making moves on the board. |
mathable-game.cpp |
The client source file implementing the main() function which contains the main game loop for alternating turns across players. It includes the header file and calls the functions provided by the above source file. |
• Basically, you need not change the header file unless you need to add extra functions to mathable.cpp and their function prototypes to the header file.
• To achieve the second requirement mentioned above, the header file has defined some global constant integers for scaling board size, player count, rack size and token count easily.
o We may grade your program with them changed to a different value within their valid range specified. When you test your program against smaller or bigger boards, you can change N to other values but remember to reset it to its original value before your submission.
o To make the program scalable, whenever you have need to use the board size, say, you should use the named constant N instead of hardcoded values throughout every source file. For simulating empty cells on the board, we can’t use 0 for the board array elements since token 0 may be placed on the board. A possible choice is to initialize the elements to -1. But instead of hardcoding -1 throughout the program, a more scalable implementation should use the global constant BLANK which is set to -1 in mathable.h.
o You may change the preprocessor flag JUNIOR on line 7 in mathable.h from 0 to 1 if you want to compile the program as the Mathable Junior variant, which uses a smaller board size and rack size, etc. This can already help testifyour program is scalable.
• The source files have organized the entire program into different functions with well-defined parameter lists. Your main task in this assignment is to search for all “TODO” comments and fill in the missing parts of code.
Player Actions:
There are 4 options of game actions that a player can choose in each turn:
1. Play (P): play a move, i.e., select a token on the rack to place at a specified cell on the board.
2. Swap (S): select some or all tokens from the rack to swap with random tokens in the bag.
3. End (E): end the current turn (if the player can’t see any more moves to make).
4. Terminate (T): terminate the game (prematurely). Then players’ current total scores are compared to see who wins the game.
Your program is to prompt the user to enter one of the four letters: P, S, E, or T (case-insensitive) to perform. one of the above actions for the current turn.
Playing a Token : If the player chooses P, the program prompts the player to enter a move, which consists of the target cell address, followed by the value of a token on his rack. The following shows an example where the player places token 4 at cell G9, and then places token 8 at cell H6. He may enter as many valid moves as possible based on the available tokens on his rack. The player then enters E to end the current turn and pass the turn to the next player.
Action (P/S/E/T): P↵ Enter move: G9 4↵ ... Action (P/E/T): p↵ Enter move: h6 8↵ |
Swapping Tokens: Note that the program implements the option S (Swap) is to support this feature
in the game rules: “A player may make use of his turn to exchange one or more tokens on his holder for new ones … To play, he must await his next turn.” So, a player who wants to swap for new tokens from the bag must choose S at the beginning of the turn. If the player has chosen P (Play), he cannot choose S anymore, and this option should be hidden throughout the current turn. See below for an example prompt for swapping tokens. It first asks for how many tokens on the rack are to be swapped out. Then the program loops that many times to prompt for each token and replace it on the rack with a randomly drawn token from the bag.
Player 2's turn Bag (83 tokens) ... Rack: [ 9 14 1 5 10 10 2 ] Action (P/S/E/T): S↵ How many to swap? 4↵ 1st token to swap: 14↵ 2nd token to swap: 10↵ 3rd token to swap: 5↵ 4th token to swap: 10↵ Swapped 14 -> 32, 10 -> 13, 5 -> 19, 10 -> 60 Rack swapped: [ 9 32 1 19 13 60 2 ] |
Provided and Required Functions (mathable.cpp and mathable.h)
Your program must contain the following functions. Most of them have been written for you already (Provided) and you shall not modify their contents. The others shall be written by you (Required). These functions shall be implemented in the source file mathable.cpp with their prototypes in the header file mathable.h. These functions shall be called somewhere in your program. You must not modify the prototypes of all these functions. You can design extra functions if you find necessary.
Besides, all the required functions below will be graded individually. That is, we shall connect your mathable.cpp with another source file with our testing code to call the functions one by one for grading. So, your code for each function shall implement the description of that function only. You shall not write any code in a function that is beyond that function’sdescription.
Provided Functions:
void shuffleTokens(int* bag)
Shuffle the tokens in the bag (elements in the bag array) using theFisher-Yates algorithm.
void fillBag(int* bag)
Fill up the bag with shuffled tokens based on official game's token listing.
int bagSize(int* bag)
Return the number of tokens in the bag.
int drawTokens(int* bag, int* rack)
Draw tokens from bag to fill up all empty slots in the specified rack as far as possible and return the count of tokens drawn.
void printBag(int* bag)
Print the content (tokens and empty slots) of the bag (to ease debugging if needed).
int rackSize(int* rack)
Return the number of tokens on the rack.
void printRack(int* rack)
Print the tokens on the rack of a player. All elements equal to BLANK are skipped from printing.
int tokenInRack(int* rack, int token)
Return the position or indexof token in the 1-D array pointed by rack if it exists and -1 otherwise.
void setupBoard(int board[][N])
Set up the game board with all elements of board set to BLANK except for the 4 central tokens which are set to 1, 2, 3, and 4.
void printBoard(int board[][N])
Print the gameboard in the format illustrated in Figure 1.
bool isValidCell(int y, int x)
Return true if the cell at row y and column x is within the board dimensions, and false otherwise (i.e., outside the board).
Required Functions with TODO Tasks
void swapTokens(int* bag, int* rack, int pos)
Swap the token indexed by pos in rack with a random token in bag.
bool isValidMove(int board[][N], int token, int y, int x, int& points)
Return true if putting the token on an empty cell at row y and column x can form. a valid equation with the token being the result of adding, subtracting, multiplying or dividing two adjacent tokens next to it, be they to the right or left, below or above the token, and false otherwise.
The function also accumulates the points gained by possible multiple equations formed by this move and passes it back to the caller via the points reference parameter.
A move placing token at board[y][x] is valid only if:
1. Location y, x lies within the board.
2. The cell at y, x is empty (not yet occupied by an existing token).
3. For 2 consecutive cells a and b adjacent to cell at y, x in any of the left, right, up, down directions, it is true that token equals a op b, or token equals b op a (where opis +, −, ×, or ÷).
Hint: the provided isValidCell() function is useful for saving some effort here.
bool possibleMoveExists(int board[][N], int* rack)
Return true if at least one possible valid move can be found on the game board using the tokens on the specified rack and false otherwise. Note: It always returns false if the rack has no tokens left.
Hint: one way to implement this function is to scan the entire board array and if any valid move is found on any of the empty cells on the board.
Hint: reuse the isValidMove() function to save effort here.