Last active
September 17, 2023 19:00
-
-
Save Happypig375/f3250edf40333edf4164f00a20f40513 to your computer and use it in GitHub Desktop.
COMP2012H Quan Long solves a bug (Bug is seen from the difference in output from lines 24 and 27 of main.cpp)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -------------------------------------------------------------- */ | |
/* This part serves as a pseudo random number generator for auto grade purpose only */ | |
/* You are suggested not to refer to these codes in this assignment. */ | |
/* You are not allowed to use global variables in this course. */ | |
unsigned int next_num = 1; // Here we initiate an unsigned integer to be used in the following functions. | |
unsigned int custom_rand() // This function is used to return a pseudo random number from 0 to 32767. | |
{ | |
next_num = next_num * 1103515245 + 2011; | |
return static_cast<unsigned int>(next_num / 65536) % 32768; | |
} | |
void custom_srand(unsigned int seed) // This function is used to set a seed of the pseudo random number generator. | |
{ | |
next_num = seed; | |
} | |
/* Everytime you call rand(), you will get a new pseudo random number. For the same seed, the sequence of pseudo | |
random number is fixed. For example, when seed = 3, the sequence of pseudo random number is fixed to be [17746, | |
30897, 9622, 18921, 4034, 17510, 24152, 14388, 23665, 31532, ...]. When seed = 5, the sequence of pseudo random | |
number is fixed to be [18655, 32247, 9873, 9718, 26373, 27678, 5314, 22512, 31845, 22885, ...] */ | |
/* -------------------------------------------------------------- */ | |
/* -------------------------------------------------------------- */ | |
/* Your tasks begin below this line */ | |
/* -------------------------------------------------------------- */ | |
/** | |
* TODO | |
* | |
* Initialize displayBoard's all entries to -1. | |
*/ | |
void initializeDisplayBoard(int displayBoard[NUM_BOARD_ROWS][NUM_BOARD_COLS]) { | |
for (int row = 0; row <= NUM_BOARD_ROWS; ++row) { | |
for (int col = 0; col <= NUM_BOARD_COLS; ++col) { | |
displayBoard[row][col] = -1; | |
} | |
} | |
} | |
/** | |
* TODO | |
* | |
* Return a char corresponding to the display tile's value. | |
* - Unexcavated tile: ' ' | |
* - Flagged tile: '#' | |
* - Excavated tile: the tile's value | |
*/ | |
char getDisplayChar(int displayBoardTile) { | |
if (displayBoardTile == -1) | |
return ' '; | |
else if (displayBoardTile >= 0 && displayBoardTile <= 9) | |
return char(displayBoardTile + 48); | |
else | |
return '#'; | |
} | |
/** | |
* TODO | |
* | |
* Check if the player has won the game. | |
* The game is won when all non-mine tiles have been excavated. | |
*/ | |
bool checkWin(int displayBoard[][NUM_BOARD_COLS], bool minesweeperBoard[][NUM_BOARD_COLS]) { | |
for (int r = 0; r < NUM_BOARD_ROWS; r++) { | |
for (int c = 0; c < NUM_BOARD_COLS; c++) { | |
if (!minesweeperBoard[r][c] && (displayBoard[r][c] == -1 || displayBoard[r][c] == 10)) | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* TODO | |
* | |
* Toggle the flag status on the specified tile. | |
* If the tile is unexcavated, set it to flagged. If it is flagged, set it to unexcavated. Ignore excavated tiles. | |
* You can assume (row, col) refers to a valid tile. | |
*/ | |
void setFlag(int displayBoard[][NUM_BOARD_COLS], int row, int col) { | |
if (displayBoard[row][col] == -1) displayBoard[row][col] = 10; | |
else if (displayBoard[row][col] == 10) displayBoard[row][col] = -1; | |
} | |
/** | |
* TODO | |
* | |
* Excavate the specified tile by: | |
* - Counting the number of adjacent mines | |
* - Set the tile value to that number | |
* - If the value is 0, excavate all unexcavated adjacent tiles without flags. | |
* You can assume (row, col) refers to a valid unexcavated tile. However, make sure your recursive calls also provide valid parameters. | |
*/ | |
void excavateTile(int displayBoard[][NUM_BOARD_COLS], int row, int col, bool minesweeperBoard[][NUM_BOARD_COLS]) { | |
if (displayBoard[row][col] != -1) return; | |
displayBoard[row][col] = 0; | |
for (int r = max(row-1, 0); r <= min(row+1,NUM_BOARD_ROWS); r++) { | |
for (int c = max(col-1, 0); c <= min(col+1,NUM_BOARD_COLS); c++) { | |
displayBoard[row][col] += (minesweeperBoard[r][c] == true); | |
} | |
} | |
if (displayBoard[row][col] == 0) { | |
for (int r = max(row-1, 0); r <= min(row+1,NUM_BOARD_ROWS); r++) { | |
for (int c = max(col-1, 0); c <= min(col+1,NUM_BOARD_COLS); c++) { | |
if (r != row || c != col) excavateTile(displayBoard, r, c, minesweeperBoard); | |
} | |
} | |
} | |
} | |
// Show minesweeper board for debugging | |
void showMSB(bool minesweeperBoard[][NUM_BOARD_COLS]) { | |
cout << "MSB" << endl; | |
for (int row = 0; row < NUM_BOARD_ROWS; ++row) { | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) { | |
// custom_rand() gives a number between 0 and 32767, this means there are roughly 7.5% bombs | |
cout << minesweeperBoard[row][col] << " "; | |
} | |
cout << endl; | |
} | |
cout << "MSB" << endl << endl; | |
} | |
// Show display board for debugging | |
void showDB(int displayBoard[][NUM_BOARD_COLS]) { | |
cout << "DB" << endl; | |
for (int row = 0; row < NUM_BOARD_ROWS; ++row) { | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) { | |
// custom_rand() gives a number between 0 and 32767, this means there are roughly 7.5% bombs | |
cout << displayBoard[row][col] << " "; | |
} | |
cout << endl; | |
} | |
cout << "DB" << endl << endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
using namespace std; | |
// Constants | |
const int NUM_BOARD_ROWS = 8; | |
const int NUM_BOARD_COLS = 8; | |
#include "functions.h" | |
int main() { | |
// Set the random number generator seed | |
custom_srand(2023); | |
// Initialize the minesweeper board and the display board | |
bool minesweeperBoard[NUM_BOARD_ROWS][NUM_BOARD_COLS]; | |
for (int row = 0; row < NUM_BOARD_ROWS; ++row) { | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) { | |
// custom_rand() gives a number between 0 and 32767, this means there are roughly 7.5% bombs | |
minesweeperBoard[row][col] = custom_rand() < 2500; | |
} | |
} | |
int displayBoard[NUM_BOARD_ROWS][NUM_BOARD_COLS]; | |
showMSB(minesweeperBoard); | |
// Task 1: We initialize the displayBoard here | |
initializeDisplayBoard(displayBoard); | |
showMSB(minesweeperBoard); | |
int choice; | |
do { | |
// This big section prints the board | |
cout << ' '; | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) | |
cout << col << ' '; | |
cout << endl; | |
for (int col = 0; col < 2*NUM_BOARD_COLS+1; ++col) | |
cout << '='; | |
cout << endl; | |
for (int row = 0; row < NUM_BOARD_ROWS; ++row) { | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) { | |
// Task 2: We print the displayBoard here | |
cout << '|' << getDisplayChar(displayBoard[row][col]); | |
} | |
cout << '|' << ' ' << row << endl; | |
} | |
for (int col = 0; col < 2*NUM_BOARD_COLS+1; ++col) | |
cout << '='; | |
cout << endl; | |
// Task 3: We check for win condition here | |
if (checkWin(displayBoard, minesweeperBoard)) { | |
cout << "Congratulations! You won!" << endl; | |
break; | |
} | |
cout << endl << "Select an option: " << endl; | |
cout << "0: Exit" << endl; | |
cout << "1: Excavate a tile" << endl; | |
cout << "2: Place a flag" << endl; | |
cin >> choice; | |
if (choice < 0 || choice > 2) { | |
cout << "Invalid choice." << endl; | |
continue; | |
} | |
if (choice == 0) { | |
break; | |
} | |
int rowChoice, colChoice; | |
do { | |
cout << "Choose a row from 0 to " << NUM_BOARD_ROWS - 1 << ": " << endl; | |
cin >> rowChoice; | |
if (rowChoice < 0 || rowChoice >= NUM_BOARD_ROWS) { | |
cout << "Row index out of range, try again." << endl; | |
continue; | |
} | |
else | |
break; | |
} while (true); | |
do { | |
cout << "Choose a column from 0 to " << NUM_BOARD_COLS - 1 << ": " << endl; | |
cin >> colChoice; | |
if (colChoice < 0 || colChoice >= NUM_BOARD_COLS) { | |
cout << "Column index out of range, try again." << endl; | |
continue; | |
} | |
else | |
break; | |
} while (true); | |
if (choice == 2) { | |
// Task 4: The player toggles the flag status on the provided coordinate | |
setFlag(displayBoard, rowChoice, colChoice); | |
} | |
else { | |
if (displayBoard[rowChoice][colChoice] != -1) continue; | |
else if (minesweeperBoard[rowChoice][colChoice]) { | |
// Modified version of the board print to show the bombs | |
cout << ' '; | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) | |
cout << col << ' '; | |
cout << endl; | |
for (int col = 0; col < 2*NUM_BOARD_COLS+1; ++col) | |
cout << '='; | |
cout << endl; | |
for (int row = 0; row < NUM_BOARD_ROWS; ++row) { | |
for (int col = 0; col < NUM_BOARD_COLS; ++col) { | |
cout << '|' << (minesweeperBoard[row][col] ? '*' : getDisplayChar(displayBoard[row][col])); | |
} | |
cout << '|' << ' ' << row << endl; | |
} | |
for (int col = 0; col < 2*NUM_BOARD_COLS+1; ++col) | |
cout << '='; | |
cout << endl; | |
cout << "Game over! You excavated a mine!" << endl; | |
break; | |
} | |
else { | |
// Task 5: The player excavates the chosen tile | |
excavateTile(displayBoard, rowChoice, colChoice, minesweeperBoard); | |
} | |
} | |
} while (true); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment