Trying to compare a randomly generated array to user filled array - c++

I am currently working on a project to create a game of Mastermind. The user must input 3 colors and the program will compare which are the correct color and in the proper place,which are the correct color but in the wrong place, and which are the wrong color. All seems well except I'm unable to properly compare the info within the randomly generated array with the user filled array. I'm sure I'd have to use a loop to accomplish this.
-Things that I feel may be the issue:
*The information within both arrays are not being stored properly.
*conflicting types.
void gameS() {
int close, right, attempts = 0;
string choice[3],code; // holds user input
const int arrySize = 5;
srand(time(0)); //random numbers
string ranColor[arrySize] = { "R", "B", "W", "Y", "G" }; // possible color options
for (int i = 0; i < arrySize - 2; i++) //generat random colors
{
int rcolor = rand() % arrySize;
code = ranColor[rcolor];
cout << code << endl;
}
while (attempts < 10) {
cout << "You should input your color choices below. Your options are - R : Red, B : Blue, W : White, Y : Yellow, G : Green.\n" << "Please choose 3 for your " << attempts+1 << " attempt.\n" << "******************************************************\n\n";
cout << "\n\nPlease enter the color of the first peg: "; //user input to choice array spot : 1
cin >> choice[0];
cout << "\nPlease enter the color of the second peg: "; //user input to choice array spot : 2
cin >> choice[1];
cout << "\nPlease enter the color of the third peg: "; //user input to choice array spot : 3
cin >> choice[2];
attempts++; // proceeds to next turn/attempt
//checks for correct colors in correct places
for (int i = 0; i < 3; i++)
{
if (code == choice[i])
{
right++;
choice[i] = "X";
}
}
//Determin the number of right colors in the wrong place
for (int i = 0; i < 3; i++)
{
for (int y = 0; y < 3; y++) {
if (code[i] == choice[y]) {
close++;
choice[i] = "Y";
}
}
}
}
}
I receive errors for the following lines:
*'argument':conversion from tim_t to unsigned in' possible loss of data
srand(time(0));
*Using uninitialized memory 'right'
`if (code == choice[i])
{
right++;
choice[i] = "X";
}`
*Using uninitialized memory 'close'
`for (int i = 0; i < 3; i++)
{
for (int y = 0; y < 3; y++) {
if (code == choice[y])
{
close++;
choice[i] = "Y";
}
}
}
*no operator "==" matches these operands.
*Binary '==':o global operator found which takes type 'std::string'(or there is no acceptable conversion)
`for (int y = 0; y < 3; y++) {
if (code[i] == choice[y])
{
close++;
choice[i] = "Y";
}`
Any tips would be appreciated.

From what I can see there is some initialization problems.
First
int close, right, attempts = 0;
Will leave close and right empty, simply initialize them properly
int close = 0, right = 0, attempts = 0;
It looks like you want to use code as an array, but the problem is, it is not initialized as an array
string choice[3],code; // holds user input
A quick fix is
string choice[3],code[3]; // holds user input
Now, where you generate the answer, there is another syntax problem
code = ranColor[rcolor];
since you want to store the answer in the code array, an index must be specified, in this case
code[i] = ranColor[rcolor];
The final problem lies in
//checks for correct colors in correct places
for (int i = 0; i < 3; i++)
{
if (code == choice[i])
{
right++;
choice[i] = "X";
}
}
Since code is an array now, simply change the condition statement to
if (code[i] == choice[i])

Related

Tesseract OCR (C++) Cannot Evaluate Output String

I am attempting to extract output string from an OpenCV Matrix window and evaluate it, but it seems to return something similar to "someString\n" rather "someString". This renders it difficult to compare knowing there are (x) amounts of white spaces.
I tried:
creating a char array that omits the white spaces (I am aware that I'm only evaluating 5 indexes)
std::string redef;
char charArr[100] = {NULL};
strcpy_s(charArr, str.c_str());
for (int i = 0; i < 5; i++)
{
if (charArr[i] != ' ')
{
redef += charArr[i];
}
}
std::cout << "analyseAction ran:" << redef << "white-space?";
but the string returns something like
analyseAction ran:redefString
white-space?
Relevant code running in main function:
api->Recognize(0);
outText = api->GetUTF8Text();
analyseAction(outText);
bellow, just take note that the else statement runs since redef doesn't equal to "long" when long is shown visually in window.
void analyseAction(std::string str)
{
std::string redef;
char charArr[100] = {NULL};
strcpy_s(charArr, str.c_str());
for (int i = 0; i < 5; i++)
{
if (charArr[i] != ' ')
{
redef += charArr[i];
}
}
std::cout << "analyseAction ran:" << redef << "white-space?";
//alot of missing code, trying to show what is relevant
if (redef == "long") //check if it has white space after long, seems like it new line's
{
//NOTE FOR FUTURE: Stop being lazy and make this a function of its own
//BUY
std::cout << "Long ran";
for (int i = 0; i < a; i++) //no comma with first line so 0 element
{
context += inData[i];
}
x = std::stoi(context);
for (int i = a+1; i < a1; i++)
{
context += inData[i];
}
y = std::stoi(context);
simClick(x,y);
//BUY CONFIRM
for (int i = a1+1; i < b; i++) //starting from pipeline??
{
context += inData[i];
}
x = std::stoi(context);
for (int i = b+1; i < b1; i++) //starting with comma? +1 to fix
{
context += inData[i];
}
y = std::stoi(context);
simClick(x, y);
}
else
{
std::cout << "long does not match";
}
}
I am confused, why does the string appear to new line? And how can I successfully evaluate the output? I am a noobie in C++ so any help will be greatly appreciated.
As for why it's returning a string and a line break, I cannot answer that. But I can provide you an alternative system to what you are trying to accomplish. Remove your first for loop in the analyseAction function and in your if statement for "long" pass in... if(charArr[0] == 'l') {//do stuff} This does have a limit if you are assessing many words that start with "l", in this case assess the first two or three letters of the word so long they aren't less than 2 or 3 letter words. PS. this was written on mobile.

(C++) I have to use magic numbers to display values in the correct position in an array. How can I get rid of it?

Sorry if the code is too long. I just wanted to give a detailed description of the situation I am facing
I'm coding a game called Battle Ship. The following code is a simpler version, I did eliminate all the unnecessary logic, cause I just want to indicate the problem with the magic numbers.
Here are my struct and enum
// the dimension of the 10 + 2 game grid for detection of the neighboring ship
// (its usage comes later in the game, not at this stage)
const int SIZE = 12;
// the number of warships
const int NBSHIP = 5;
string ships[NBSHIP] = {"Carrier", "Cruiser", "Destroyer", "Submarine", "Torpedo" };
// available warships and their size on the grid
enum Ship {
CARRIER=5,
CRUISER=4,
DESTROYER=3,
SUBMARINE=3,
TORPEDO=2,
NONE=0
};
// the different states that a grid cell can take and their display
enum State {
HIT='x',
SINK='#',
MISS='o',
UNSHOT='~'
};
// a grid cell
// the ship present on the space
// the state of the box
struct Cell {
Ship ship;
State state;
};
// the player with
// his name
// his score to determine who lost
// his game grid
struct Player {
string name;
int score;
Cell grid[SIZE][SIZE];
};
// the coordinates of the cell on the grid
// its column from 'A' to 'J'
// its line from 1 to 10
struct Coordinate {
char column;
int line;
};
// the placement of the ship on the grid
// its coordinates (E5)
// its direction 'H' horizontal or 'V' vertical from the coordinate
struct Placement {
Coordinate coordi;
char direction;
};
Basically, at the beginning of the game, I have to initialize a grid with the appropriate state for each cell (in this case, UNSHOT and NONE). Then I have to display the grid and start placing the ships. The weird thing here is I have to use "magic numbers" to place the ships in the correct position according to the player's input. But I don't even know why I need it as well as how to get rid of it.
Utilization of magic number appears in placeShip function.
void initializeGrid (Cell aGrid[][SIZE])
{
for (int i = 0; i < SIZE - 2; i++)
{
for (int j = 0; j < SIZE - 2; j++)
{
aGrid[i][j].ship = NONE;
aGrid[i][j].state = UNSHOT;
}
}
}
void displayGrid(Player aPlayer)
{
cout << endl;
cout << setw(10) << aPlayer.name << endl;
// Letter coordinates
char a = 'A';
cout << " ";
for (int i = 0; i < SIZE - 2 ; i++)
{
cout << " " << char (a+i);
}
cout << endl;
// Number coordinates
for (int i = 0; i < SIZE - 2; i++)
{
// Player
if(i + 1 >= 10) // To align the first column
cout << i + 1;
else
cout << " " << i + 1;
for (int j = 0; j < SIZE - 2; j++)
{
if (aPlayer.grid[i][j].ship) // Check if there are ships
cout << " " << (aPlayer.grid[i][j].ship);
else
cout << " " << char (aPlayer.grid[i][j].state);
}
cout << endl;
}
}
void placeShip(Cell aGrid[][SIZE], Placement aPlace, Ship aShip)
{
if (aPlace.direction == 'h' || aPlace.direction == 'H')
{
for (int i = 0; i < aShip; i++) // To change the value of a cell according to the size of the boat
{
// Utilization of magic number
aGrid[aPlace.coordi.line - 9][aPlace.coordi.column + i - 1].ship = aShip; // Horizontal so we don't change the line
}
}
else if (aPlace.direction == 'v' || aPlace.direction == 'V')
{
for (int i = 0; i < aShip; i++)
{
// Utilization of magic number
aGrid[aPlace.coordi.line + i - 9][aPlace.coordi.column - 1].ship = aShip; // Vertical so we don't change the column
}
}
}
void askPlayerToPlace(Player& aPlayer)
{
Ship battleships[NBSHIP] = { CARRIER, CRUISER, DESTROYER, SUBMARINE, TORPEDO};
for (int i = 0; i < NBSHIP; i++)
{
string stringPlace;
string stringShip = ships[i];
Ship aShip = battleships[i];
string inputDirection;
Coordinate coordi;
cout << "\n" << aPlayer.name << ", time to place your carrier of length "
<< to_string(battleships[i])
<< " (" << ships[i] << ")\n"
<< "Enter coordinates (i.e. B5): ";
cin >> stringPlace;
coordi = { stringPlace[0], int(stringPlace[1]) - 48 };
cout << "Direction: ";
cin >> inputDirection;
Placement aPlace = {
coordi,
inputDirection[0]
};
placeShip(aPlayer.grid, aPlace, aShip);
displayGrid(aPlayer);
}
}
int main()
{
Player aPlayer;
cout << "Player's name: ";
getline (cin, aPlayer.name);
initializeGrid(aPlayer.grid);
displayGrid(aPlayer);
askPlayerToPlace(aPlayer);
return 0;
}
The weird thing here is I have to use "magic numbers" to place the ships in the correct position according to the player's input.
If these are numbers, which tend to appear frequently you should define another constant for these like:
const int GRID_SIZE_MARGIN = 2;
and use it
void initializeGrid (Cell aGrid[][SIZE]) {
for (int i = 0; i < SIZE - GRID_SIZE_MARGIN; i++) {
for (int j = 0; j < SIZE - GRID_SIZE_MARGIN; j++) {
aGrid[i][j].ship = NONE;
aGrid[i][j].state = UNSHOT;
}
}
}
If there are other numbers, which appear in calculations, but can't be reasonably named, it's OK to leave the numeric values. I'll try to give you an example:
The formula to calculate degrees from radians is
deg = rad * 180° / π
For π we have a constant definition (PI), but is 180 a magic number which deserves a constant definiton?
How should we name it? HUNDREDEIGHTY_DEGREES??
So it's not always reasonable to get rid of numeric constants appearing in code.
But I don't even know why I need it as well as how to get rid of it.
That's probably part ot the task, to find out.

C++ : How do I only look at one dimension of a 2-Dimensional array?

I'm writing a battleship game in the console, and I'm writing a function that will draw one grid based on a 2-dimensional array. The approach I'm taking is such:
--> Draw 1 row which contains a character X amount of times (like 10)
--> Draw that row, putting a newline at the end of the drawing process, 10 times to get a nice field.
Now, I do need to insert a newline at the end of 1 row, right? But how do I compare only the x-element of the array, and not the y-element?
Here's my code:
// Includes
#include <iostream> // For IO
#include <cstdlib> // For rand()
// Important game stuff
const int empty = 0; // Water
const int occupied = 1; // Ship
const int hit = 2; // Hit a ship
const int missed = 3; // Missed
// Variables
const int fields = 10;
// We want a 10x10 field
int board[fields][fields]; // board[x][y]
// Initialize board
void initb(int array[fields][fields]);
// Draw board x-axis
void drawbx(int array[fields][fields]);
int main(void)
{
drawbx(board;)
// game(Players);
return 0;
}
// Initialize the board, make everything hit
void initb(int array[fields][fields])
{
for(int x = 1; x <= 10; x++)
{
for(int y = 1; y <= 10; y++)
{
array[x][y] = hit;
}
}
}
void drawbx(int array[fields][fields])
{
for(int i = 1; i <= fields; i++)
{
if(array[i][] == empty || array[i][] == occupied)
{
if(i == 10)
std::cout << " X\n";
else if(i == 1)
std::cout << "X ";
else
std::cout << " X ";
}
}
}
Take a look specifically at the drawbx() function. I want to draw something like
X X X X X X X X X X\n
The syntax that I tried, if(array[i][] == empty || array[i][] == occupied), doesn't work. There must be an expression in the second pair of square brackets. Can someone help me?
I see two major problems:
1) Array indexing is out of range. You use index 1 to 10. It shall be 0 to 9.
2) Code array[i][] == empty is illegal syntax. You can't leave one index empty.
If you want a function that draw one row, perhaps pass the row number to the function like:
void draw_one_row(int array[fields][fields], int row_to_draw)
{
for(int i = 0; i < fields; i++)
{
if(array[row_to_draw][i] == empty || array[row_to_draw][i] == occupied)
{
...
}
}
}
To draw the whole board:
void draw_board(int array[fields][fields])
{
for(int i = 0; i < fields; i++)
{
draw_one_row(array, i);
}
}
BTW: Since you write C++, I'll recommend that you use vector instead of arrays.

If Statement not working, input unrecognised (C++)

My program runs without issues, compiles no errors.
The aim of my if statement is to choose if letters are shifted left/right which I have tried to achieve with an if statement leading to 2 functions, however no matter the input from cin >> z; it will always utilize CipherR. Can anyone help me figure this out?
//Start of Document
#include <WinUser.h> //Gives access to windows form library
#include "StdAfx.h" //Standard prefix for vb to save
#include <iostream> //Enables I/O stream cin/cout
#include <string> //Ensures that string data can be assigned
#include <Windows.h> //Gives access to windows library Included libraries, above <winuser.h>
using namespace std;
//Variables
char cipherR(char);
char cipherL(char);
int y;
const string LEFT = "1";
const string RIGHT = "0";
//Main Code
int main()
{
string input; //Declares string variable for temp storage
//MessageBox
int WinUserMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); //defines MessageBox parameters
const int message = MessageBox(NULL, L"Is your location secure?", L"Warning", MB_YESNOCANCEL); //sets up listener for messagebox response
//Switch Response
switch (message) //Initialise case study
{
case IDYES: //Runs this if Yes is selected
//cipher code block
do {
cout << "Enter text to be ciphered/deciphered." << endl;
cout << "Enter blank line to quit." << endl;
getline(cin, input); //Prompts for User Input, stores into temporary var
string output = ""; //Checks for blank input
cout << "Shift Left(1) or Right(0)? \n";
string z; //L or R definer
std::cin >> z;
cout << "Enter number to shift\n";
cin >> y;
if (z == LEFT)
{
for (int x = 0; x < input.length(); x++) // Loops until string.length is reached.
{
output += cipherR(input[x]);
}
} //Adds the value of expression to the value of a variable and assigns the result to the variable.
else if (z == RIGHT)
{
for (int x = 0; x < input.length(); x++) // Loops until string.length is reached.
{
output += cipherL(input[x]); //Adds the value of expression to the value of a variable and assigns the result to the variable.
}
};
cout << output << endl; // If input is blank will end process
} while (!input.length() == 0); //Loops while input.length is NOT equal to 0
break;
//alternate message responses
case IDNO: //Runs this if No is selected
MessageBox(NULL, L"Agents are converging on your location now.", L"Run!", NULL);
return 0;
break;
case IDCANCEL: //Runs this if cancel is selected
MessageBox(NULL, L"Why open this is you're gonna back out?", L"Alert", NULL);
return 0;
break;
}
}
//functions
char cipherR(char c) //function caesar, called into main
{
if (isalpha(c)) //checks if is part of the alphabet
{
c = toupper(c); //ignores casing of input for universal input
c = (((c - 65) + y) % 26) + 65; //performs caesar cipher with algebraic equation
return c; //returns encrypted data
}
if (!isalpha(c)) //if is not alphabetic will make blank
{
return 0; //returns blank
}
// if c isn't alpha, just send it back
}
char cipherL(char c) //function caesar, called into main
{
cout << "This Is left";
if (isalpha(c)) //checks if is part of the alphabet
{
c = toupper(c); //ignores casing of input for universal input
c = (((c - 65) - y) % 26) + 65; //performs caesar cipher with algebraic equation
return c; //returns encrypted data
}
if (!isalpha(c)) //if is not alphabetic will make blank
{
return 0; //returns blank
}
// if c isn't alpha, just send it back
}
//end of sheet
I believe you have your functions swaped. In
if (z == LEFT)
{
for (int x = 0; x < input.length(); x++) // Loops until string.length is reached.
{
output += cipherR(input[x]);
}
} //Adds the value of expression to the value of a variable and assigns the result to the variable.
else if (z == RIGHT)
{
for (int x = 0; x < input.length(); x++) // Loops until string.length is reached.
{
output += cipherL(input[x]); //Adds the value of expression to the value of a variable and assigns the result to the variable.
}
};
When you go into the "left" if statement you are calling cipherR() when you should be calling cipherL(). You also need to fix "right" as you are calling cipherL(). Fixed version:
if (z == LEFT)
{
for (int x = 0; x < input.length(); x++) // Loops until string.length is reached.
{
output += cipherL(input[x]);
// ^ L here
}
} //Adds the value of expression to the value of a variable and assigns the result to the variable.
else if (z == RIGHT)
{
for (int x = 0; x < input.length(); x++) // Loops until string.length is reached.
{
output += cipherR(input[x]); //Adds the value of expression to the value of a variable and assigns the result to the variable.
// ^ R here
}
};
It looks like you think -1 % 26 is 25.
It's not - it's either 1 or -1, depending on the implementation.
In your implementation, it's apparently positive since you get the same result for both shifts.
You can't use the modulus for the left shift.
Instead, use repeated addition:
c = c - y;
while (c < 'A')
{
c += 26;
}
You also want to look over which function you're calling for each case, as you have them switched around.

c++ Genetic Algorithm Mutation error

I Have a problem with the mutation function within my genetic Algorithm. I can't quite see what I am doing wrong either. I've looked at this code for a while and I think the logic is correct, it's just not producing the results i want.
The problem
When i output the Binary array located in the Child Struct, If mutation has occured on any of the bits, then a random number will be changed, and not the one that should be.
for example
0000000 is the binary string
mutation has occured on the second
bit
0001000 would be the result
This section is located within the main.
for (int Child = 0; Child < ParentNumberInit; Child++)
{
cout << endl;
mutation(child[Child],Child);
}
This is the mutation function
void mutation(struct Parent Child1,int childnumber)
{
int mutation; // will be the random number generated
cout << endl << "Child " << (childnumber+1) << endl;
//loop through every bit in the binary string
for (int z = 0; z < Binscale; z++)
{
mutation = 0; // set mutation at 0 at the start of every loop
mutation = rand()%100; //create a random number
cout << "Generated number = " << mutation << endl;
//if variable mutation is smaller, mutation occurs
if (mutation < MutationRate)
{
if(Child1.binary_code[z] == '0')
Child1.binary_code[z] = '1';
else if(Child1.binary_code[z] == '1')
Child1.binary_code[z] = '0';
}
}
}
It's being outputted in the main like this
for (int childnumber = 0; childnumber < ParentNumberInit; childnumber++)
{
cout<<"Child "<<(childnumber+1)<<" Binary code = ";
for (int z = 0; z < Binscale; z ++)
{
cout<<child[childnumber].binary_code[z];
}
cout<<endl;
}
You can't throttle the multation rate this way. You need to separate the mutated bit from the probability of the mutation occuring.
for (int z = 0; z < Binscale; z++)
{
if (rand() % 100 < MutationRate)
{
// flip bit
Child1.binary_code[z] += 1;
Child1.binary_code[z] %= 2;
}
}
Even simpler way to flip bit:
Child1.binary_code[z] ^= 1;
try this:
void mutation(Parent& Child1,int childnumber)