Can't figure out Segmentation Fault for C++ code - c++

My code is below. The problem happens when I try and run the addArray() function. I am completely new to C++ so I have no idea what a segmentation fault means.
I also know that there is probably a better way to initialize and return the 2d arrays, but I am slowly figuring that out.
My main problem now is the segmentation fault. I am guessing that it has something to do with how I am accessing the variables?
#include <iostream>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <iomanip>
#include <time.h>
#include <stdlib.h>
using namespace std;
int c, q, w, row, coll, quit, qq, opt;
int** arr1;
int** arr2;
int** ans;
//Method Prototypes
int menu();
inline int** getArray(int opt);
inline void printArray(int** arr, int height, int width);
void addArray();
void subtractArray();
void multiplyArrays();
void determArray();
void transposeArray();
void inverseArray();
//Prints out the menu for choosing which option to go with
int menu() {
cout << "Press 1 for Addition\n";
cout << "Press 2 for Subtraction\n";
cout << "Press 3 for Multiplication\n";
cout << "Press 4 for Determinant\n";
cout << "Press 5 for Transpose\n";
cout << "Press 6 for Inverse\n";
cout << "Press 0 to quit\n\n";
cin >> c;
return c;
}
//Main method
int main(void) {
cout << "C++ 2d Matrix Operations Menu\n";
c = menu();
while (c != 0) {
if (c == 1) {
addArray();
} else if (c == 2) {
subtractArray();
} else if (c == 3) {
void multiplyArrays();
} else if (c == 4) {
void determArray();
} else if (c == 5) {
void transposeArray();
} else if (c == 6) {
}
c = menu();
}
cout << "Press Enter to Quit. GOOD BYE";
cin >> quit;
return 0;
}
/*
Prints out the specified array.
It's arguments are the actual array and the height/weight
*/
inline void printArray(int** arr, int height, int width) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
std::cout << arr[i][j] << ' ';
}
std::cout << std::endl;
}
}
//Returns an array.
inline int** getArray(int opt) {
if (opt == 0) {
cout << "How many rows and columns should be in the array?\n";
cin >> q >> w;
} else {
q = 3;
w = 3;
}
int** ary = new int*[q];
for (int i = 0; i < q; ++i) {
ary[i] = new int[w];
}
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
cout << "What should the value be for item" << row << "," << coll << "\n";
cin >> ary[row][coll];
}
}
return ary;
}
//Adds arrays
void addArray() {
arr1 = getArray(0);
int h1 = q;
int w1 = w;
arr2 = getArray(0);
int h2 = q;
int w2 = w;
if ((h1 != h2) || (w1 != w2)) {
cout << "Both arrays must be the same size.";
return;
}
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr1[row][coll] + arr2[row][coll];
}
}
printArray(ans, q, w);
}
//Subtracts Arrays
void subtractArray() {
arr1 = getArray(0);
int h1 = q;
int w1 = w;
arr2 = getArray(0);
int h2 = q;
int w2 = w;
if ((h1 != h2) || (w1 != w2)) {
cout << "Both arrays must be the same size.";
return;
}
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr2[row][coll] - arr1[row][coll];
}
}
printArray(ans, q, w);
}
//Calculate the determinate of an array.
void determArray() {
arr1 = getArray(1);
printArray(arr1, q, w);
//There must be a better/more efficient way to do this using loops.
int determinant = arr1[0][0]*((arr1[1][1] * arr1[2][2]) - (arr1[2][1] * arr1[1][2])) - arr1[0][1]*(arr1[1][0] * arr1[2][2] - arr1[2][0] * arr1[1][2]) + arr1[0][2]*(arr1[1][0] * arr1[2][1] - arr1[2][0] * arr1[1][1]);
printf("\nDeterminant of vector using method 1 is: %d\n", determinant);
}
//Transpose an array.
void transposeArray() {
cout << "IN TRANS";
arr1 = getArray(0);
printArray(arr1, 3, 3);
//Flip the values
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr1[coll][row];
}
}
cout << "----------" << endl << "The new vector looks like: \n";
printArray(ans, q, w);
}
/*
Multiply arrays. One option is to just multiply it by a number and the other is to multiply it by another array.
*/
void multiplyArrays() {
arr1 = getArray(0);
int h1 = q;
int w1 = w;
cout << "Do you wish to multiply the first vector by a number(Enter 1), or by a second vector(Enter 2)?";
cin >> qq;
int mu;
//First Option is to multiply it by a single number
if (qq == 1) {
cout << "What number do you wish to multiply the vector by?";
cin >> mu;
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr1[row][coll] * mu;
}
}
printArray(ans, h1, w1);
//Multiply two arrays
} else if (qq == 2) {
arr2 = getArray(0);
int h2 = q;
int w2 = w;
int n1 = h1;
int n2 = w2;
int nCommon = n1;
if (n2 == nCommon) {
cout << "Amount of columns for vector 1 must match amount of rows for vector 2";
return;
}
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
for (int k = 0; k < nCommon; k++) {
ans[i][j] += arr1[i][k] * arr2[k][j];
}
}
}
printArray(ans, n1, n2);
}
}

You never allocate memory for ans. Just like you need to allocate storage for the two input arrays before filling them, you need to allocate storage for the answer.
A segmentation fault is generated when you attempt to write to memory that you do not have access to. In this case, because the ans array was not initialized, it points to random memory. When you do ans[row][coll] = arr2[row][coll] - arr1[row][coll];, you get a segfault because ans[row][col] is pointing somewhere outside your program space.

The problem is that you have not allocated memory for the ans array, but you are writing to it in the following code:
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr2[row][coll] - arr1[row][coll];
}
}
This is why you have segmentation fault.
Try to add a block to allocate memory for ans at first.

Related

C++ Recursion to detect duplicates in row and column of grid

I'm coding a recursive algorithm to take a user input N and make a N x N grid where the same number does not appear twice on either a row or a column. Almost everything's working, and duplicates don't appear in columns, but I'm having trouble getting rows working.
My code for checking duplicates in rows is the function noRowDuplicates. Duplicates are still appearing, and occasionally it'll throw a segmentation fault, but I'm not sure why.
Thanks in advance for the help!
// Author: Eric Benjamin
// This problem was solved using recursion. fill() is the recursive function.
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
void fillOptions();
void fill(int arrayPosition);
int inputNum;
int gridSize;
int *grid;
int allOptionsSize = 0;
int *allOptions;
int main() {
cout << "Please enter a number!" << endl;
cin >> inputNum;
gridSize = inputNum * inputNum;
grid = new int[gridSize];
allOptions = new int[inputNum];
for (int i = 0; i < inputNum; i++) {
allOptions[i] = i + 1;
allOptionsSize++;
}
srand((unsigned)time(0));
fill(0);
delete[] grid;
delete[] allOptions;
return 0;
}
bool noColumnDuplicates(int arrPosition, int valueToCheck) {
for (int i = 1; i < inputNum; i++) {
if (arrPosition - (inputNum * i) >= 0) {
if (grid[arrPosition - (inputNum * i)] == valueToCheck) {
return false;
}
}
}
return true;
}
bool noRowDuplicates(int arrPosition, int valueToCheck) {
int rowPosition = arrPosition % inputNum; // 0 to num - 1
if (rowPosition > 0) {
for (int p = 1; p < rowPosition; p++) {
if (grid[arrPosition - p] == valueToCheck) {
return false;
}
}
}
return true;
}
void fill(int arrayPosition) {
if (arrayPosition < gridSize) {
int randomPosition = rand() % allOptionsSize;
grid[arrayPosition] = allOptions[randomPosition];
if (noColumnDuplicates(arrayPosition, grid[arrayPosition])) {
if (noRowDuplicates(arrayPosition, grid[arrayPosition])) {
if (arrayPosition % inputNum == 0) {
cout << endl;
}
cout << grid[arrayPosition] << " ";
fill(arrayPosition + 1);
} else {
fill (arrayPosition);
}
} else {
fill(arrayPosition);
}
}
}
noRowDuplicates never tests the first element of a row, which makes sense when you are trying to fill the first element of a row, but not any other time.

LRU c++ program

I've been working on a program in one of my college classes. I have been having trouble with the implementation of my LRU code as it is not displaying any errors or anything, but compiles. There are two parts. The main that we input the values into, which we then specify which algorithm we want to use to find page faults. I know the main works, along with the FIFO algorithm, but I'm not getting anything with my LRU code (It compiles and "runs" but displays nothing as if I did not click to use the algorithm). Can anyone help me figure out what is wrong?
main.cpp
#include <iostream>
#include <string>
//#include "fifo.cpp"
#include "lru.cpp"
//#include "optimal.cpp"
using namespace std;
int main() {
// List of different variables
string pagestring;
int fs,pn[50], n;
// Prompt for page references
cout<<"Virtual Memory Simulation\nBy blah\n----------\nEnter the number of pages : " << endl;
cin >> n;
cout<<"\n-------------\nPlease enter a list of page numbers separated by commas.\n"<< endl;
cin>>pagestring;
// algorithm to use
char algo;
while (true) {
// Prompt algorithm to use
cout<<"----------\nPlease select an algorithm to use.\n\n1: First-In-First-Out (FIFO)\n2: Least-Recently-Used (LRU)\n3: Optimal\n0: Quit\n"<<endl;
cin>>algo;
if (algo == '1') {
//fifo(pagestring);
}
else if (algo == '2'){
LRU_Execute(pagestring, n);
}
else if (algo == '3'){
cout<<"Optimal Not yet coded"<<endl;
}
else if (algo == '0'){
break;
}
else {
cout<<"Invalid choice. Please try again."<<endl;
}
}
cout<<"Goodbye!!"<<endl;
};
LRU.cpp
#include <iostream>
#include <string>
using namespace std;
class pra
{
int fs,z;
int frame[50], frame1[50][2], pn[50], n, cnt, p, x;
public:
pra();
void init(string pagestring);
void getdata(string pagestring, int n);
void lru(int* pn, int n, string pagestring);
};
pra::pra()
{
int i;
for (i = 0; i < fs; i++)
{
frame[i] = -1;
}
for (i = 0; i < fs; i++)
{
frame1[i][0] = -1;
frame1[i][1] = 0;
}
p = 0;
cnt = 0;
}
void pra::init(string pagestring)
{
int i;
for (i = 0; i < fs; i++)
{
frame[i] = -1;
}
for (i = 0; i < fs; i++)
{
frame1[i][0] = -1;
frame1[i][1] = 0;
}
p = 0;
cnt = 0;
}
void pra::getdata(string pagestring, int n)
{
fs=3;
// index to loop through input string
int i = 0;
// current input string character
char z = pagestring[i];
int x = 0;
//cout << "\nEnter the page numbers : ";
while (z != '\0'){
// skip over commas and spaces
if (!(z == ',')) {
pn[x] = z;
x++;
// cout<<pn[x]<<"-This is pn[x]\n";
}
z = pagestring[++i];
}
//cout<<pn[x]<<"-This is pn[x] AGAIN\n";
this->lru(pn, n, pagestring);
}
void pra::lru(int* pn, int n, string pagestring)
{
init(pagestring);
int ind = 0, fault = 0, pi = 0, j, fn;
char i, z;
p = 0;
cnt = 0;
int min;
cout<<n<<"---"<<i<<" - "<<j<<" - "<<" - "<<fn<<" - "<<z;
for (i = 0; i < fs; i++)
{
frame1[i][0] = -1;
frame1[i][1] = 0;
}
pi = 0;
for (i = 0; i < n; i++)
{
j = 0;
if (ind > fs - 1)
ind = 0;
fault = 1;
min = 999;
while (j < fs)
{
if (frame1[j][0] = pn[pi])
{
fault = 0;
p++;
frame1[j][1] = p;
goto l2;
}
if (frame1[j][1] < min)
{
min = frame1[j][1];
fn = j;
}
j++;
}
j = 0;
while (j < fs)
{
if (frame1[j][0] = -1)
{
fault = 1;
fn = j;
goto l2;
}
j++;
}
ind++;
l2:
if (fault == 1)
{
p++;
frame1[fn][0] = pn[pi];
frame1[fn][1] = p;
cnt++;
}
cout << "\nElement: " << pn[pi];
pi++;
for (z = 0; z < fs; z++)
{
cout << "\t" << frame1[z][0];
}
if (fault == 1)
cout << "\t**Page Fault**";
else
cout << "\t--No Page Fault--";
}
cout << "\nTotal number of page faults: " << cnt;
cout << "\n";
}
void LRU_Execute(string pagestring, int n)
{
pra p;
int j, fault = 0, i, pi, z, fn, ind = 0, ans, ch;
p.getdata(pagestring, n);
//p.lru();
while (ans == 1);
//return 1;
}

C++ Passing class Object to function

I'm new to C++ programming.
Now I have the state class. I want to create neighboring states with this class, so I add the function getNeighboringStates() to my class. In this function I pass in "neighboring_states" to function set_neighboring_state(), this function change "neighboring_states"'s value.
In this function, I set a for loop to test. It print out "7 1 0 3 6 4 5 2 8", which is the value I want. But In the function getNeighboringStates(), I also set a for loop that has the same mission as in set_neighboring_state(), but the screen display "0 1 4716672 2686652 2686528 0 4716676 4519501 4716676".
I don't know what's wrong with my code. What do I need to do now?
int n; // The number of columns as well as rows of the board
int k; // The kind of heuristic function to use
int tilesCount; // The number of tiles, including the blank one
int statesCount; // The number of states generated
int* m_initTiles;
int* m_goalTiles;
int tmpTile;
const int UP = 0;
const int DOWN = 1;
const int RIGHT = 2;
const int LEFT = 3;
int* direction;
class State {
public:
State(){}
int getBlankTilePosition() {
for (int i = 0; i < n * n; i++) {
if (stateTiles[i] == 0)
return i;
}
}
void set_neighboring_state(State* neighboring_state, int direction) {
int blankPosition = getBlankTilePosition();
int neighbor_tiles[n * n];
for (int i = 0; i < n * n; i++) {
neighbor_tiles[i] = getStateTiles()[i];
}
switch(direction) {
case UP:
if (blankPosition/n < 1) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition - n]);
neighboring_state->set_tiles(neighbor_tiles);
// This for loop print out "7 1 0 3 6 4 5 2 8"
for (int i = 0; i < n * n; i++)
cout << neighboring_state.getStateTiles()[i] << " "; cout << endl;
}
break;
case DOWN:
if (blankPosition/n == n - 1) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition + n]);
neighboring_state->set_tiles(neighbor_tiles);
}
break;
case LEFT:
if (blankPosition % n == 0) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition - 1]);
neighboring_state->set_tiles(neighbor_tiles);
}
break;
default:
if ((blankPosition + 1) % n == 0) return;
else {
swap(neighbor_tiles[blankPosition], neighbor_tiles[blankPosition + 1]);
neighboring_state->set_tiles(neighbor_tiles);
}
break;
}
}
/*
The maximum number of neighboring state that can be created is 4.
This function return the neighboring states of a certain state.
The first state represents for the "left" neighbor, the second,
the third and the fourth represent the "right", "up, and "down"
neighbor, respectively.
*/
State* getNeighboringStates() {
State* neighboring_states;
neighboring_states = new State[4];
for (int i = 0; i < 4; i++)
set_neighboring_state(&neighboring_states[i], direction[i]);
// This print out "0 1 4716672 2686652 2686528 0 4716676 4519501 4716676"
cout << endl;
for (int i = 0; i < n * n; i++)
cout << neighboring_states[0].getStateTiles()[i] << " ";
cout << endl;
return neighboring_states;
}
State(int* pStateTiles) {
stateTiles = pStateTiles;
}
void set_tiles(int* tiles) {
stateTiles = tiles;
}
int* getStateTiles() {
return stateTiles;
}
private:
int* stateTiles;
};
void input(const char* fileName) {
ifstream fin;
fin.open(fileName);
// read n, k from file
fin >> n >> k;
// allocate m_initTiles and m_goalTiles memory
m_initTiles = new int[n * n];
m_goalTiles = new int[n * n];
for (int i = 0; i < n * n; i++)
fin >> m_initTiles[i];
for (int i = 0; i < n * n; i++)
fin >> m_goalTiles[i];
for (int i = 0; i < n * n; i++)
cout << m_initTiles[i] << " ";
cout << endl;
for (int i = 0; i < n * n; i++)
cout << m_goalTiles[i] << " ";
cout << endl;
fin.close();
}
void initDirection() {
direction = new int[4];
direction[0] = UP;
direction[1] = DOWN;
direction[2] = RIGHT;
direction[3] = LEFT;
}
int main() {
input("nPuzzle.inp");
initDirection();
State init_state (m_initTiles);
State goal_state (m_goalTiles);
State* init_neighbor = init_state.getNeighboringStates();
// int* state_tile = init_neighbor[0].getStateTiles();
// for (int i = 0; i < n * n; i++)
// cout << state_tile[i] << " ";
return 0;
}
int blankPosition = getBlankTilePosition();
int neighbor_tiles[n * n];
Remove int neighbor_tiles[n * n]; line from above code segment and make it global available to all function , so declare it as data of a class not for function i.e. add int neighbor_tiles[n * n]; to class as an data type .

Debugging a merge sort

void CensusData::mergeSort(int type) {
if(type == 0)
MERGE_SORT(type, 0, data.size());
}
void CensusData::MERGE_SORT(int type, int p, int r){
//int q;
//cout << "data size " << data.size() << endl;
std::cout << "MERGE_SORT START ///("<< p << ", " << r << ")" <<std::endl;
if(p < r)
{
int q = (p + r)/2;
MERGE_SORT(type, p, q);
MERGE_SORT(type, q + 1, r);
MERGE(type, p, q ,r);
}
}
void CensusData::MERGE(int type, int p, int q, int r){
if(type == 0)
{
std::cout << "MERGING" << std::endl;
//int n1;
//int n2;
int n1 = q - p + 1;
int n2 = r - q;
int L[n1 + 1];
int R[n2 + 1];
for(int i = 1; i < n1; i++)
{
cout << "filling Left Array" << endl;
L[i] = data[p + i - 1]->population;
}
for(int j = 1; j < n2; j++)
{
cout << "filling Right Array" << endl;
R[j] = data[q + j]->population;
}
int i = 1;
int j = 1;
for(int k = p; p < r; p++)
{
cout << "for loop: " << endl;
if(L[i] <= R[j])
{
cout << "TRUE" << endl;
data[k]->population = L[j];
i = i + 1;
}
/*else if(data[k]->population == R[j])
{
cout << "FALSE" << endl;
j = j + 1;
}*/
else
{
data[k]->population = R[j];
j = j + 1;
}
}
}
}
do not worry about type, it wont effect this program at all. basically i am trying to make a merge sort that will take a vector containing an integer, the vector looks like this:
class Record { // declaration of a Record
public:
std::string* city;
std::string* state;
int population;
Record(std::string&, std::string&, int);
~Record();
};
std::vector<Record*> data;
basically i have been trying to get it to actually sort, but it doesn't seem to work at all, i have even seen garbage in the program.
example input:
237 812826 68642
output:
4484540 812826 68642
Note: all of the rest of the program works fine (tested it with an insertion sort) only this part is not working.
Take a look at lecture 15 of the excellent Stanford Universities course Programming Abstractions. It covers all kinds of sorts including merge:
http://see.stanford.edu/see/lecturelist.aspx?coll=11f4f422-5670-4b4c-889c-008262e09e4e
You can even get the source code from SourceForge:
http://sourceforge.net/projects/progabstrlib/files/

2D Array Help C++

OK so heres the scoop: I am building a minesweeper style program for my c++ class, I'm using a 2D array to create the board,and a second 2d array to store guesses. For each value in the board array, I run a random number gen and assign it a value between 0 and 99. Each value in the array is considered a bomb if its value is greater than 85. The program accepts user input and determines if it is a bomb. If it is not the corresponding bool array (isGuessed) position is changed to true. This bool array is then sent to the reDraw function to be redrawn. All false bools are displayed as '?' and all true are displayed as 'X'. However, when I reDraw, it changes multiple locations in the array to an X with only one guess. My thought is that the board is not drawn in connection with the array positions. Could someone help. Just to be clear, I'm trying to understand why the function reDraw is not working properly. Here is ALL my code.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
//Function Prototypes
void reDraw (bool guessed [] [10], int rows, int columns);
void newBoard (int rows, int columns);
int main(int argc, const char * argv[])
{
//Declare Variables
const int ROWS = 10;
const int COLUMNS = 10;
int board [ROWS][COLUMNS];
bool wasGuessed [10] [10];
bool playAgain = true;
char newGame;
int rowGuess, columnGuess, numOfBombs = 0, score = 0;
bool bomb = false;
srand((unsigned) time(0));
// Welcome User, Give Direction
cout<<"\n\n\t\tWelcome To Matt's Minesweeper\n\n";
while (playAgain) {
//function to randomly populate array elements
for (int row = 0; row < ROWS; row++) {
for (int column = 0; column < COLUMNS; column++) {
board [row] [column] = rand() % 100;
if (board [row] [column] >= 85) { //counter for bombs
numOfBombs++;
}
}
}
// Create a new Display Board
newBoard(10, 10);
//Begin Game
cout<<"\nTotal Bombs In This Game: "<<numOfBombs;
// Process Guesses
do {
cout<<"\nPlease Input your ROW & COLUMN Guess coordinate (i.e. 3 2): ";
cin>>rowGuess>>columnGuess;
if (board [rowGuess] [columnGuess] >= 85) {
bomb = true;
cout<<"\n\n\t\tXXXXXX BOMB HIT XXXXXXX\n\t\t\tGame Over.\n\n";
cout<<"Your Score Score: "<<score;
cout<<"\n\n Play Again (y/n):";
cin>>newGame;
switch (newGame) {
case 'y':
cout<<"\n\n";
playAgain = true;
break;
default:
playAgain = false;
break;
}
} else {
wasGuessed [rowGuess] [columnGuess] = true;
score++;
reDraw(wasGuessed, 10, 10);
}
} while (!bomb);
}
return 0;
}
void reDraw (bool guessed [] [10], int rows, int columns)
{
// Format row and column headers
cout<<" 0 1 2 3 4 5 6 7 8 9\n";
cout<<"0";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if ((j+1) % 10 == 0)
if ((i+1) == 10) {
if (guessed [i] [j])
cout<<"X "<<" \n";
else
cout<<"? "<<" \n";
}else{
if (guessed [i] [j])
cout<<"X "<<" \n"<<i+1;
else
cout<<"? "<<" \n"<<i+1;
}
if ((j+1) % 10 != 0)
if (guessed [j] [i])
cout<<" X"<<" ";
else
cout<<" ?"<<" ";
}
}
}
void newBoard (int rows, int columns)
{
cout<<" 0 1 2 3 4 5 6 7 8 9\n";
cout<<"0";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if ((j+1) % 10 == 0)
if ((i+1) == 10) {
cout<<"? "<<" \n";
}else
cout<<"? "<<" \n"<<i+1;
if ((j+1) % 10 != 0)
cout<<" ?"<<" ";
}
}
}
Thanks For Your Help Guys!
Ok it's fixed. Check out the new code:
Changes - Added reset() and moved wasGuessed [rowGuess] [columnGuess] = true; to the top after cin<<.
It works like a charm and draws X's where the ?'s once stood before the guess.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
//Declare Variables
const int ROWS = 10;
const int COLUMNS = 10;
int board [ROWS][COLUMNS];
bool wasGuessed [ROWS] [COLUMNS];
bool playAgain = true;
char newGame;
int rowGuess, columnGuess, numOfBombs = 0, score = 0;
bool bomb = false;
//Function Prototypes
void reDraw (bool guessed [] [10], int rows, int columns);
void newBoard (int rows, int columns);
void reset();
int main(int argc, const char * argv[])
{
srand((unsigned) time(0));
reset();
// Welcome User, Give Direction
cout<<"\n\n\t\tWelcome To Matt's Minesweeper\n\n";
while (playAgain) {
//function to randomly populate array elements
for (int row = 0; row < ROWS; row++) {
for (int column = 0; column < COLUMNS; column++) {
board [row] [column] = (rand() % 100) + 0;
if (board [row] [column] >= 85) { //counter for bombs
numOfBombs++;
}
}
}
// Create a new Display Board
newBoard(10, 10);
//Begin Game
cout<<"\nTotal Bombs In This Game: "<<numOfBombs;
// Process Guesses
do {
cout<<"\nPlease Input your ROW & COLUMN Guess coordinate (i.e. 3 2): ";
cin>>rowGuess>>columnGuess;
wasGuessed [rowGuess] [columnGuess] = true;
if (board [rowGuess] [columnGuess] >= 85) {
bomb = true;
cout<<"\n\n\t\tXXXXXX BOMB HIT XXXXXXX\n\t\t\tGame Over.\n\n";
cout<<"Your Score Score: "<<score;
cout<<"\n\n Play Again (y/n):";
cin>>newGame;
switch (newGame) {
case 'y':
cout<<"\n\n";
playAgain = true;
reset();
break;
default:
playAgain = false;
break;
}
} else {
wasGuessed [rowGuess] [columnGuess] = true;
score++;
reDraw(wasGuessed, 10, 10);
}
} while (!bomb);
}
return 0;
}
void reDraw (bool guessed [] [10], int rows, int columns)
{
// Format row and column headers
cout<<" 0 1 2 3 4 5 6 7 8 9\n";
cout<<"0";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if ((j+1) % 10 == 0)
if ((i+1) == 10) {
if (guessed [i] [j])
cout<<"X "<<" \n";
else
cout<<"? "<<" \n";
}else{
if (guessed [i] [j])
cout<<"X "<<" \n"<<i+1;
else
cout<<"? "<<" \n"<<i+1;
}
if ((j+1) % 10 != 0)
if (guessed [j] [i])
cout<<" X"<<" ";
else
cout<<" ?"<<" ";
}
}
}
void newBoard (int rows, int columns)
{
cout<<" 0 1 2 3 4 5 6 7 8 9\n";
cout<<"0";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if ((j+1) % 10 == 0)
if ((i+1) == 10) {
cout<<"? "<<" \n";
}else
cout<<"? "<<" \n"<<i+1;
if ((j+1) % 10 != 0)
cout<<" ?"<<" ";
}
}
}
void reset()
{
for (int row = 0; row < ROWS; row++)
{
for (int column = 0; column < COLUMNS; column++)
{
wasGuessed [row] [column] = false;
}
}
}
I was bored so I made your program better. It's all in one file, but it would be easy enough to split it into multiple. Just separate out the members and class definitions for each class, and put them in their own files, and put main in its own file.
I do a few things that might strike you as peculiar. If you see something, ask about it in a comment and I'll explain myself
// include all of the things
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <string>
// use all of the things
using std::rand;
using std::srand;
using std::time;
using std::cout;
using std::cin;
using std::endl;
using std::right;
using std::left;
using std::setw;
using std::string;
// MineSweepBoard.h
class MineSweepBoard
{
public:
MineSweepBoard(int rows, int cols, float per);
MineSweepBoard(int rows, int cols);
MineSweepBoard();
virtual ~MineSweepBoard();
static const int ROW_DEFAULT, COL_DEFAULT;
static const float CHANCE_DEFAULT;
static const unsigned char MINE_MASK, UNCOVERED_MASK;
static void Randomize();
void RandomizeBoard();
bool IsMine(int r, int c);
bool IsUncovered(int r, int c);
int UncoverSpace(int r, int c);
int GetAdjMineCount(int r, int c);
bool IsOnBoard(int r, int c);
char GetBoardSquare(int r, int c);
int GetRows();
int GetCols();
float GetPercentage();
int GetMineCount();
int GetSafeCount();
private:
int rowcount, colcount;
int minecount, safecount;
float percentage;
char * board;
bool safedummy;
void Init(int rows, int cols, float per);
};
// MineSweeper.h
class MineSweeper : public MineSweepBoard
{
public:
MineSweeper();
MineSweeper(int rows, int cols, float difficulty);
MineSweeper(int rows, int cols, float difficulty, char mchar, char bchar, char uchar);
static const char MINE_DEFAULT, BLANK_DEFAULT, UNKNOWN_DEFAULT;
void PrintBoard();
char GetCharForSpace(int r, int c);
void Play();
bool WonGame();
private:
char minechar, blankchar, unknownchar;
int cleared;
void Init(char mchar, char bchar, char uchar);
};
// MineSweepBoard.cpp
const int MineSweepBoard::ROW_DEFAULT = 10, MineSweepBoard::COL_DEFAULT = 10;
const float MineSweepBoard::CHANCE_DEFAULT = 0.85;
const unsigned char MineSweepBoard::MINE_MASK = 0x1, MineSweepBoard::UNCOVERED_MASK = 0x2;
void MineSweepBoard::Randomize()
{
srand(time(NULL));
}
int MineSweepBoard::GetRows()
{
return rowcount;
}
int MineSweepBoard::GetCols()
{
return colcount;
}
float MineSweepBoard::GetPercentage()
{
return percentage;
}
int MineSweepBoard::GetMineCount()
{
return minecount;
}
int MineSweepBoard::GetSafeCount()
{
return safecount;
}
MineSweepBoard::MineSweepBoard()
{
Init(ROW_DEFAULT, COL_DEFAULT, CHANCE_DEFAULT);
}
MineSweepBoard::MineSweepBoard(int rows, int cols)
{
Init(rows, cols, CHANCE_DEFAULT);
}
MineSweepBoard::MineSweepBoard(int rows, int cols, float per)
{
Init(rows, cols, per);
}
MineSweepBoard::~MineSweepBoard()
{
delete[] board;
}
void MineSweepBoard::Init(int rows, int cols, float per)
{
minecount = 0;
safecount = rows * cols;
percentage = per;
rowcount = rows;
colcount = cols;
board = new char [rows * cols];
RandomizeBoard();
}
char MineSweepBoard::GetBoardSquare(int r, int c)
{
return board[r * colcount + c];
}
void MineSweepBoard::RandomizeBoard()
{
for (int i = 0, j = rowcount * colcount; i != j; ++i)
{
float r = (((float) rand()) / ((float) RAND_MAX));
board[i] = (percentage < r);
if (board[i]) ++minecount;
}
safecount -= minecount;
}
bool MineSweepBoard::IsOnBoard(int r, int c)
{
return (
(r >= 0 && r < rowcount) &&
(c >= 0 && c < colcount)
);
}
bool MineSweepBoard::IsMine(int r, int c)
{
return (
(IsOnBoard(r, c)) &&
(GetBoardSquare(r, c) & MINE_MASK)
);
}
bool MineSweepBoard::IsUncovered(int r, int c)
{
return (
(IsOnBoard(r, c)) &&
(GetBoardSquare(r, c) & UNCOVERED_MASK)
);
}
int MineSweepBoard::UncoverSpace(int r, int c)
{
int uncovered = 0;
while (IsOnBoard(r, c) && !IsUncovered(r, c))
{
board[r * colcount + c] |= UNCOVERED_MASK;
if (!(GetBoardSquare(r, c) & MINE_MASK)) ++uncovered;
else break;
if (GetAdjMineCount(r, c) == 0)
{
uncovered += UncoverSpace(r + 0, c + 1);
uncovered += UncoverSpace(r + 0, c - 1);
uncovered += UncoverSpace(r + 1, c + 0);
uncovered += UncoverSpace(r - 1, c + 0);
}
break;
}
return uncovered;
}
int MineSweepBoard::GetAdjMineCount(int r, int c)
{
return IsMine(r + 0, c + 1) + IsMine(r + 0, c - 1) +
IsMine(r + 1, c + 0) + IsMine(r - 1, c + 0) +
IsMine(r + 1, c + 1) + IsMine(r - 1, c - 1) +
IsMine(r + 1, c - 1) + IsMine(r - 1, c + 1);
}
// MineSweeper.cpp
const char MineSweeper::MINE_DEFAULT = 'X', MineSweeper::BLANK_DEFAULT = ' ', MineSweeper::UNKNOWN_DEFAULT = '?';
MineSweeper::MineSweeper() : MineSweepBoard()
{
Init(MINE_DEFAULT, BLANK_DEFAULT, UNKNOWN_DEFAULT);
}
MineSweeper::MineSweeper(int rows, int cols, float difficulty) : MineSweepBoard(rows, cols, difficulty)
{
Init(MINE_DEFAULT, BLANK_DEFAULT, UNKNOWN_DEFAULT);
}
MineSweeper::MineSweeper(int rows, int cols, float difficulty, char mchar, char bchar, char uchar) : MineSweepBoard(rows, cols, difficulty)
{
Init(mchar, bchar, uchar);
}
void MineSweeper::Init(char mchar, char bchar, char uchar)
{
minechar = mchar;
blankchar = bchar;
unknownchar = uchar;
}
void MineSweeper::PrintBoard()
{
for (int i = 0; i < GetCols(); ++i) cout << setw(4) << right << i;
cout << left << endl << endl;
for (int r = 0; r < GetCols(); ++r)
{
cout << setw(3) << r;
for (int c = 0; c < GetRows(); ++c)
{
cout << setw(4) << GetCharForSpace(r, c);
}
cout << endl;
}
}
char MineSweeper::GetCharForSpace(int r, int c)
{
if (IsUncovered(r, c))
{
if (IsMine(r, c))
return minechar;
int count = GetAdjMineCount(r, c);
if (count == 0)
return blankchar;
else
return '0' + count;
}
else
return unknownchar;
}
void MineSweeper::Play()
{
int score = 0;
PrintBoard();
cout << "Total Bombs In This Game: " << GetMineCount() << endl;
while (true)
{
string dummy;
int inputrow = -1, inputcol = -1;
cout << "Please Input Your ROW & COLUMN Guess Coordinate (i.e. 3 2): ";
cin >> inputrow >> inputcol;
if (!cin || IsUncovered(inputrow, inputcol) || !IsOnBoard(inputrow, inputcol))
{
cout << "Invalid Selection! ";
if (!cin)
{
cin.clear();
cin >> dummy;
}
continue;
}
int uncovered = UncoverSpace(inputrow, inputcol);
PrintBoard();
if (IsMine(inputrow, inputcol))
{
cout << endl << endl << "\t\tXXXXXX BOMB HIT XXXXXX" << endl << "\t\t\tGame Over." << endl << endl;
break;
}
else
{
score += uncovered;
cleared += uncovered;
if (WonGame())
{
cout << endl << endl << "\t\t------ ALL BOMBS CLEARED ------" << endl << "\t\t\tYou Win!" << endl << endl;
break;
}
}
}
cout << "your Score: " << score << endl;
}
bool MineSweeper::WonGame()
{
return (cleared == GetSafeCount());
}
// main.cpp
int main(int argc, char * argv[])
{
MineSweepBoard::Randomize();
cout << endl << endl << "\t\tWelcome To Wug's Minesweeper" << endl << endl;
while(true)
{
char again = 'n';
MineSweeper m;
m.Play();
cout << endl << "Play Again? (y/n) ";
cin >> again;
if (again == 'y')
{
cout << endl << endl;
continue;
}
else break;
}
return 0;
}
This code exhibits the following traits that your original version did not:
you can win games
as with windows minesweeper, picking a piece in the middle of an empty space clears the whole space
input validation
memory management (yours just used memory on the stack, it didn't have to new and delete anything
inheritance
the indentation is consistent (reading code with inconsistent indentation is not fun)