Counting correct and misplaced digits - c++

This program is a "Codebreaker" game. In this section of the program, the computer checks the digits guessed by the player, compares each of them to every one of the digits in the secret code, and determines if the digit is "correct" or simply "misplaced." I can not get this section to work correctly. I wrote the code for "correct" and "misplaced" in different passes, and I know I need to replace the original variables with a letter so that one number is not checked as more than one and is instead replaced by either "y" or "z". When I run the program, the values for "correct" and "misplaced" are not correct. I am getting random values.
correct_digits = 0;
misplaced_digits = 0;
misplaced_digit = false;
/* Get and validate the player's guess using "get_player_code()"; increment guess counter */
player_code = get_player_code();
++num_guesses;
for(int x=0;x<CODE_LENGTH;x++){
if(player_code[x]==secret_code[x]){
correct_digits++;
secret_code[x]='y';
}
}
for(int x=0;x<CODE_LENGTH;x++){
for(int i=0;i<CODE_LENGTH;i++){
if(player_code[i]==secret_code[i]){
misplaced_digits++;
secret_code[i]='z';
}
}
}
/* Print player's guess and number of correct/misplaced digits */
cout << setw(40) << player_code << setw(15) << correct_digits << setw(15) << misplaced_digits << '\n';

Assuming player_code and secret_code will always be the same length (if player_code is less you will have undefined behavior) and assuming all of the code you're not showing us is correct, then all you need to do is fix this check:
if(player_code[i]==secret_code[i]){
You're checking the same character in each string. You want to compare a character in one of the strings to every character in the other. Your condition should be:
if(player_code[x]==secret_code[i]){

Related

C++ How to new line without chopping words

I am currently making a text game in c++. I am using a function that prints text one character at the time (to give a "narration" effect), which also goes to a new line to some condition defined by the function.
Here is the function:
void smart_print(const std::string& str, int spacer)//str is the printed message. spacer is the amount of space you want at the beginning and at the end of the cmd window
{
int max = Console::BufferWidth - (spacer * 2);
int limit = max;
ut.spacer(5);//this prints 5 spaces
for (int i = 0; i != str.size(); ++i)//this loop prints one character of the string every 50 milliseconds. It also checks if the limit is exceeded. If so, print new line
{
if (limit < 0)
{
cout << endl;
ut.spacer(5);
limit = max;
}
limit--;
std::cout << str[i];
Sleep(50);
}
}
The problem with this function, is that it chops the words, because it does a new line everytime the "limit" variable is less than 0, regardless if there is an incomplete word or not.
I made a sort of scheme to try to figure out how it should work correctly, but i can't manage to "translate" it into code.
1) Analyze the string, and check how long is the first word
2) Count the characters and stop counting when there is a space
3) Calculate if it can print the word (by subtracting the number of letters to max)
4) If the limit is exceeded, go to new line. Otherwise proceed to print the word one letter at the time
I really can't manage to make such function. I hope someone can help me out :P
Thanks in advance.
I think you should do something like checking if the current character is blank, using the std::isspace method like this:
// inside your for
if (limit < 0 && isspace(str[i]))
{
cout << endl;
ut.spacer(5);
limit = max;
}
limit--;
if(!isspace(str[i])) std::cout << str[i];
Sleep(50);
Note: I haven't tested the code so I am not 100% sure if it works correctly.

SetKeyboardState doesnt work properly

I have program, then it's running it asks stuffs and then user has to press 1 to proceed I use GetKeyState() function to decide if number was pressed and SetKeyboardState() to set keys states back to original, but it doesn't work after second attempt. Whats wrong?
Code:
BYTE States[256];
GetKeyboardState(States);
cout << press 1 << endl;
while(!Started)
{
if(GetKeyState(VK_NUMPAD1))
{
Started = true;
}
}
SetKeyboardState(States);
cout << "press 1" << endl;
while(!Name)
{
if(GetKeyState(VK_NUMPAD1))
{
Name = true;
}
}
SetKeyboardState(States);
cout << "press 1" << endl;
while(!Located)
{
if(GetKeyState(VK_NUMPAD1))
{
Located = true;
}
}
The code looks a bit odd to me. I have a feeling that you've not got the optimal solution to your problem. But I don't know enough of your problem to say so for sure.
One thing sticks out though. Your test of the return value of GetKeyState() is wrong you should test it like this:
if(GetKeyState(VK_NUMPAD1)<0)
From the documentation:
If the high-order bit is 1, the key is down; otherwise, it is up.
The simple way to test for high-order bit being 1 is that the value is negative. Your code tests for any bit being set which will evaluate true for states other than the key being down.
I am no expert, but as far as I can see,
Your while(!Name) checks if variables are false. Inside the loop you set them to true and loop ends which leaves you unable to check key more then once.

make permutations of an array of numbers, then turn them into a single int

Basic idea: Given an array, find all the permutations of that array. Then, take each of those arrays and put it all together. Eg the array {6,5,3,4,1,2} gives you 653412. The permutations work, but I cannot get the integers.
int main ()
{
int myints[] = {2,3,4,5,6,7,8,9};
int k;
int dmartin=0;
int powof10=1;
std::cout << "The 8! possible permutations with 8 elements:\n";
do {
for(k=0; k<8; k++){
std::cout << myints[k] << ' ';
dmartin=myints[8-k-1]*powof10+dmartin;
powof10=powof10*10;
}
cout << "\n" << dmartin << "\n";
} while ( std::next_permutation(myints,myints+8) );
dmartin=0;
return 0;
}
I also have some code that works when you just have one array, but in this case there are thousands. I though I needed to reset dmartin=0 at the end of each while loop so that it didn't keep adding to the previous answer, however when I tried that I got "0" for each of my answers. Without trying to reset, I get answers that seem random (and are negative).
The problem is that you're not resetting your two variables inside your loop, so they'll continue from the values they had during the previous iteration, which will just be wrong, and will quickly overflow, giving seemingly rubbish output. Try putting this at the beginning or the end of the do-while loop:
dmartin = 0;
powof10 = 1;
But you're really overcomplicating it a lot. It would be way simpler to just build the number from the most significant digit instead of the least significant one instead. This would eliminate the need for a powof10 variable. This new for-loop would look like this:
for(k = 0; k < 8; k++){
std::cout << myints[k] << ' ';
dmartin = 10*dmartin + myints[k];
}
That won't work for long, since your integer will soon overflow.
That's probably what you are experiencing when you get negative numbers.
Using an integer to store the result does not seem the most appropriate choice to me. Why not use a string, for instance? That would save you the hassle of reinventing base10 conversion in 2014, and you could easily derive a number from the string when needed.
That won't solve the overflow problem, though.
First point: the code to take a vector of digits and turn them into a single number should almost certainly be written as a function, not just code inside the loop.
Second point: you can use std::string like a container of char, and apply normal algorithms to it.
Seem to me, the lazy way would look like this:
std::string input="23456789";
do {
std::cout<<std::stoi(input)<<"\n";
} while (std::next_permutation(input.begin(), input.end()));

Check multiple OR operators in IF statement

I have the following C++ code:
if(x==y||m==n){
cout<<"Your message"<<endl;
}
If x is equal to y or m is equal to n, the program prints "Your message". But if both conditions are true,the program tests only one of them and eventually prints one "Your Message".
Is there a way to print each "Your message" independently based on each condition using a single if statement?
The output would be identical to the below using multiple if statements.
if(x==y){
cout<<"Your message"<<endl;
}
if (m==n){
cout<<"Your message"<<endl;
}
Not that I'd ever do it this way, but ...
for(int i = 0; i < (x==y)+(m==n); ++i) {
std::cout << "Your message\n";
}
Let me expand on this. I'd never do it this way because it violates two principles:
1) Code for maintainability. This loop is going to cause the maintainer to stop, think, and try to recover your original intent. A pair of if statements won't.
2) Distinct input should produce distinct output. This principle benefits the user and the programmer. Few things are more frustrating than running a test, getting valid output, and still not knowing which path the program took.
Given these two principles, here is how I would actually code it:
if(x==y) {
std::cout << "Your x-y message\n";
}
if(m==n) {
std::cout << "Your m-n message\n";
}
Aside: Never use endl when you mean \n. They produce semantically identical code, but endl can accidentally make your program go slower.
I don't think that's possible. What you have inside your bracket is a statement which is either true or false, there's no such thing like a true/true or true/false statement. What you could do is a do/while loop with a break statement. But I don't think that's the way to go. Why do you want to avoid two if statements?
single "|" or "&" gaurantees both side evaluation even if the result can be determined by left side operator alone.
You could do something like this, to build up the "message":
string msg = "Your Message\n";
string buildSt = x == y ? m == n ? msg + msg : msg : m == n ? msg : "";
Compiler checks only one condition when both are true because you've connected your conditions with OR.
If even one condition in ORs chain is true there is no need to check others as a result already true and will be false if one of them is false. So if you think that your logic is right then there is no need to do multiple checks. Your code is asking that you will print a message if one of the conditions is true and program doing it. If you want something special for a case when both conditions are true then add it separately. Shortly you should never expect from the compiler to do all checks in the expressions connected by OR.
Regards,
Davit
Tested code:
#include <iostream>
#include <string>
using namespace std;
void main() {
int x=1;
int y=1;
int m=1;
int n=1;
string mess1="Your message 1\n";
string mess2="Your message 2\n";
cout<<((x==y)?mess1:"")+((m==n)?mess2:"");
getchar();
}
If you are trying to see if both statements are true an && is what you will want to use.
Take a look at Boolean Operators to see all of the possible options when comparing boolean (true/false) values.
To answer your question:
if ((x==y) && (m==n))
{
cout<<"Your Message"<<endl<<"Your Message"<<endl;
}
else if((x==y) || (m==n))
{
cout<<"Your Message"<<endl;
}

C++ input of type char, output of type int

I am taking my very first C++ class and I am stuck. I would really appreciate some help from you experienced programmers.
The assignment is creating a blackjack-scoring program. Not a very realistic one, but hey. The user inputs how many cards he wants and then the values of each of those cards. The assignment specifies that the inputs should be in type char. So if the user has a 2 card they enter 2, but that 2 is actually char and must be converted to int. Or they would enter "Q" if they have a queen and my program is supposed to convert that Q to ten points for scoring. I cannot figure out what is the right way to do this. The assignment suggests I will use either a switch statement or nested if-else statement, but I am afraid I don't understand switch very well from the book examples.
So here's a tiny bit of my attempts at switch. *points_for_card* is of type char and *number_value* is int.
switch (points_for_card)
{
case '2':
number_value = 2 ;
break;
case '3':
number_value = 3 ;
break;
// ETC
}
So what I am going for here is: if the user enters '3' as a char, it becomes int 3. But maybe this is not how switch works at all.
The thing is, my program compiles and works, but returns weird crazy huge numbers. If I move points_for_card to int instead of char, then the arithmetic works perfectly for whatever numbers I enter, because at that point it's just adding them together.
I hope I explained this ok, will clarify as much as possible if necessary.
it can be something like this code:
if (points_for_card >= '1' && points_for_card <= '9'){
number_value = points_for_card - '0'; // convert to number
}else if (points_for_card == 'Q'){
...
}
A map comes to mind. You can store the scores directly, or you can make one map to look up the card type and other maps to associate other information (like score) to each card. Here's the baby example:
std::map<char, int> scores;
scores['Q'] = 10; scores['A'] = 13; scores['2'] = 2; // etc.
char c;
std::cout << "Please enter a card: ";
std::cin >> c;
std::cout << "Your card has score " << scores[c] << std::endl;
Oftentimes when your heart says "switch", your brain should say "map" :-)
Personnally I'd define an enum ECardType { Card_2, ..., Card_10, Card_Jack, ... }; and have one map be std::map<char, ECardType>, and then other maps from card type to secondary information like scores.
How are you taking inputs into points_for_card ?
Your input should be cin >> points_for_card;
Instead of comparing a character to a character, you can also compare it to the ASCII value of a character.
For example,
char letter = 'A'
if(letter == 65){
cout << "Match";
}
The above code will output "Match!".
Also, your switch statements are perfectly worded. The problem lies elsewhere in your program, so please provide the relevant source.
Another point related to your program but not your problem: How are you dealing with Aces ? You know that they can be counted as either 1 or 11, depending on the player's hand value, right ?