Logic Error in TicTacToe game - c++

here's a simple logic error I can't quite wrap my head around:
Why does the following statement always equate to true?
if ( (grid[i][0] && grid[i][1] && grid[i][2]) == ('X' || 'x') ) return true;
It works flawlessly for
if ( (grid[i][0] && grid[i][1] && grid[i][2]) == ('X') return true;

Do it like this:
create a function to check a character of being x:
bool isX(char c)
{
return c == 'X' || c == 'x';
}
and the you can write:
if ( isX(grid[i][0]) && isX(grid[i][1]) && isX(grid[i][2]))
return true;

That's because the expressions
'X' || 'x'
and
grid[i][0] && grid[i][1] && grid[i][2]
use the || and && operators between non-zero integer-typed values (because char is an integer type) and so they both evaluate to true.
To translate into C++ (or almost any other somewhat similar language, for that matter) that you want characters x, y and z to be equal to either of the characters c and C, you must compute
(x == c || x == C) && (y == c || y == C) && (z == c || z == C)
so apply that to your problem.
More importantly though, learn about boolean operators and programming in general before you try to tackle C++.

In the first case, it returns true because none of the grid elements has the value of zero. The && operator produces 0 or 1, depending on the values that you pass.
In the second case, it does not work as expected either: you wouldn't get an 'X' by &&-ing values together.
The proper way of checking if three items are equal to 'X' or not would be as follows:
if (toupper(grid[i][0]) == 'X'
&& toupper(grid[i][1]) == 'X'
&& toupper(grid[i][2]) == 'X') {
return true;
}
To generalize the concept of "win" in TiCTacToe, write a function that returns true when a sequence of three items with a specific step in each direction holds a sequence of a given character, like this:
bool isWin(int r, int c, int dr, int dc, char ch) {
return toupper(grid[r+0*dr][c+0*dc] == ch
&& toupper(grid[r+1*dr][c+1*dc] == ch
&& toupper(grid[r+2*dr][c+2*dc] == ch;
}
bool isWin(char ch) {
return isWin(0,0,0,1,ch)
|| isWin(0,0,1,0,ch)
|| isWin(1,0,0,1,ch)
|| isWin(0,1,1,0,ch)
|| isWin(2,0,0,1,ch)
|| isWin(0,2,1,0,ch)
|| isWin(0,0,1,1,ch)
|| isWin(2,0,-1,1,ch);
}

Related

Why does || operator work in my situation

Why is this an infinite loop using || logical operator
char c;
std::cin >> c;
while( c != 'y' || c != 'Y' || c != 'N' || c != 'n')
but this is not
while( c != 'y' && c != 'Y' && c != 'N' && c != 'n')
I don't understand why && operator work here because logically thinking || operator is better fit.
Lets just look at the very smallest part:
c != 'Y' || c != 'N'
If c is 'Y' then it is not 'N', if it is 'N' then it is not 'Y'. Aka:
c | c != 'Y' || c != 'N'
Y | 1 || 0 = 1
N | 0 || 1 = 1
? | 1 || 1 = 1
If your logic always returns 1 no matter what, the loop will run forever. I assume you are looking to wait until you get c as one of these values, so write it logically.
I want to wait until c is one of ['y', 'Y', ...]
And you might be able to write some nicer code:
std::array<char> options = {{'y', 'Y', 'n', 'N'}};
while (std::none_of(std::begin(options), std::end(options),
[&c](char check) { return check == c; };)) {
std::cout << "Hey write the correct character!\n";
}
Untested!
You are checking the condition which is always true by using || operator,
( c != 'y' || c != 'Y' || c != 'N' || c != 'n')
This is always true ,because it would always satisfy at-least 3 conditions in your conditional statement .
if your char is n then it would satisfy remaining conditions
c!='y' , c!='Y' , c!='N' and similarly for any other character

How to Rewrite "IF CONDITION " for ON for 3min and OFF for 10min until 4Hr (240min)

I want shorten the if condition. How can I simplify this?
Where step = 1 to 240 in min
I want 1st 3 min ON= 1, second 10 min OFF = 0, It will repeated until 248 min
I wrote "if condition" which is consist of many condition. How to rewrite the code with simple expression
#include "udf.h"
DEFINE_PROFILE(ON_3min_OFF_10min_4Hr,thread,position)
{
face_t f;
real step,hf_3min,hf_10min;
hf_3min = 1; /*ON */
hf_10min = 0; /*OFF */
step=N_TIME;
begin_f_loop(f,thread)
{
if ((step<=3) || ((step>13) && (step<=16)) || ((step>26) && (step<=29)) || ((step>39) && (step<=42)) || ((step>52) && (step<=55)) || ((step>65) && (step<=68)) || ((step>78) && (step<=81)) || ((step>91) && (step<=94)) || ((step>104) && (step<=107)) || ((step>117) && (step<=120)) || ((step>130) && (step<=133)) || ((step>143) && (step<=146)) || ((step>156) && (step<=159)) || ((step>169) && (step<=172)) || ((step>182) && (step<=185)) || ((step>195) && (step<=198)) || ((step>208) && (step<=211)) || ((step>222) && (step<=225)) || ((step>235) && (step<=238)))
{
F_PROFILE(f,thread,position)=hf_3min;
}
else
{
F_PROFILE(f,thread,position)=hf_10min;
}
}
end_f_loop(f,thread)
}
From the bounds that you are checking, it seems your code is equivalent to:
if ((step - 1) % 13 < 3) {
F_PROFILE(f, thread, position) = hf;
} else {
F_PROFILE(f, thread, position) = hf2;
}
You need to be careful about the missing lower bound on the first condition, and the change of the bounds at the last 2 conditions, in case that's intentional.

How can a char value be converted to a specific int value

I have an assignment where I have to make a program that allows a person to input a seven letter word and converts it to a telephone number (1-800-PAINTER to 1-800-724-6837 for example). I'm trying to make each letter convert to a specific number to be outputted to the user, with each letter corresponding to its number on a telephone keypad (so a, A, b, B or c, C equals 1, i.e, more info: https://en.wikipedia.org/wiki/Telephone_keypad).
Currently I have it set up so that each letter of the input word represents a char variable of one, two, three, four, five, six, or seven respectively. Then, using switch and if statements, the idea was to convert a char to an int variable of xtwo = 2, xthree = 3, etc. This isn't working however. Is there a better way to do this?
Example of code (up to first switch, though mostly it's a repeating pattern like so):
int main()
{
char one, two, three, four, five, six, seven;
cout << "Enter seven letter word (1-800-***-****): " << "\n";
cin >> one >> two >> three >> four >> five >> six >> seven;
int xtwo = 2; int xthree = 3; int xfour = 4; int xfive = 5; int xsix = 6; int xseven = 7; int xeight = 8;
int xnine = 9;
switch (one)
{
case 1:
if (one == 'a' || one == 'b' || one == 'c' || one == 'A' || one == 'B' || one == 'C')
{
one = xtwo;
}
break;
case 2:
if (one == 'd' || one == 'e' || one == 'f' || one == 'D' || one == 'E' || one == 'F')
{
one = xthree;
}
break;
case 3:
if (one == 'g' || one == 'h' || one == 'l' || one == 'G' || one == 'H' || one == 'L')
{
one = xfour;
}
break;
case 4:
if (one == 'j' || one == 'k' || one == 'l' || one == 'J' || one == 'K' || one == 'L')
{
one = xfive;
}
break;
case 5:
if (one == 'm' || one == 'n' || one == 'o' || one == 'M' || one == 'N' || one == 'O')
{
one = xsix;
}
break;
case 6:
if (one == 'p' || one == 'q' || one == 'r' || one == 's' || one == 'P' || one == 'Q' || one == 'R' || one == 'S')
{
one = xseven;
}
break;
case 7:
if (one == 't' || one == 'u' || one == 'v' || one == 'T' || one == 'U' || one == 'V')
{
one = xeight;
}
break;
case 8:
if (one == 'w' || one == 'x' || one == 'y' || one == 'z' || one == 'W' || one == 'X' || one == 'Y' || one == 'Z')
{
one = xnine;
}
break;
}
So, in essence, how can a char variable of a letter be converted to a specific int variable?
You could use a std::map.
For example, you could have
std::map<char,int> char_to_dig {
{'a',1}, {'b',1}, {'c',1},
{'d',2}, {'e',2}, {'f',2}
};
Then
char_to_dig['a']
will give you 1.
Alternatively, you could write a function that does the mapping. Something along the lines of this:
int char_to_dig(char c) {
static const char _c[] = "abcdefghi";
static const int _i[] = { 1,1,1,2,2,2,3,3,3 };
for (unsigned i=0; i<9; ++i) {
if (_c[i]==c) return _i[i];
}
return -1; // some value to signal error
}
Or, instead of using arrays, you could perform arithmetic on the chars (since they are just small integers).
int char_to_dig(char c) {
c = std::toupper(c);
if (c < 'A' || c > 'Z') return -1;
if (c == 'Z') return 9;
if (c > 'R') --c;
return ((c-'A')/3)+2;
}
This will give you numbers like on this pad:
Apparently, there's been a similar code golf question.
It has been years since I wrote any c/c++ code and I don't even have a compiler installed to test with .. but this should get you started on the right track
Check functions and syntax...all out of my head. Needs checking.
//
int numArray[7];
char inputStr[10];
cout << " give me 7 characters";
cin >> input;
/*
use a for loop to read the string letter by letter (a string in c is an
array of characters)
convert the characters to uppercase
fall through case statements for each group of letters
assing value to output array to do wiht as you like.
*/
for(i=0; i < 7; i++){
inputStr[i] = toupper(inputStr[i]);
switch(input[i]){
case 'A':
case 'B':
case 'C':
numArray[i] = 2;
break;
case 'D':
case 'E':
case 'F':
numArray[i] = 3;
break;
and so on and so foth....
}
}

C++: Boolean Expression Causing Infinite While Loop

In my introductory computer science class, a prompt asked us:
"Given  a char variable  c that has already  been declared , write some code that repeatedly reads a value  from standard input into c until  at last a 'Y' or 'y' or 'N' or 'n' has been entered."
The code I entered causes an infinite loop, but the logic makes sense to me. Can somebody please explain why the following Boolean expression is faulty?
while (c != ('n' || 'N' || 'y' || 'Y'))
cin >> c;
Because that expression does not do what you think it does. The correct is
while (c !='n' && c != 'N' && c!= 'y' && c != 'Y')
But what happens with the one you present above?
('n' || 'N' || 'y' || 'Y')
This is a series of 4 boolean ORs. The first one is 'n' || 'N', where the chars 'n' and 'N' are converted to booleans (both true), therefore the whole expression is true.
So you are left with
while (c != true)
which is the same as c != 1, and goes into a loop until you input the character with ASCII value 1. Since that is not a printable character, no input from the keyboard is going to get you out of the loop.
This:
while (c != ('n' || 'N' || 'y' || 'Y'))
is equivalent to:
while (c != true )
because any group of values ORd together is going to evaluate to true when one or more of them is non-zero. What you're probably looking for is:
while ( c != 'n' && c != 'N' && c != 'y' && c != 'Y' )
The condition in your loop is incorrect.
The correct condition is:
while ( c != 'n' && c != 'N' && c != 'y' && c != 'Y' )
{
// ...
}
When you write:
while (c != ('n' || 'N' || 'y' || 'Y'))
You ask if c is different from ('n' || 'N' || 'y' || 'Y'). But this expression itself will be evaluated as true because non-zero values ORd together are always evaluated as true. So your condition is equivalent to:
while( c != true )
Wich will lead to an infinite loop...
Try
while (c !='n' && c!='N' && c!= 'y' && c!='Y')
cin >> c;
You are "OR"ing 'n','N','y','Y' which always equals to true ( non zero). This is reason The loop is not terminating.

Conditional not working, returns first case always

The result prints out 'c' 3 times, anyone know why it always meets the first condition?
#include <iostream>
using namespace std;
char x(char y)
{
if (y == 'a' || 'b')
{
return 'c';
}
else if (y == 'c' || 'd')
{
return 'e';
}
else
{
return 'g';
}
}
int main()
{
cout << x('a') << endl;
cout << x('c') << endl;
cout << x('p') << endl;
return 0;
}
You need something of the form
if (y == 'a' || y == 'b')
This is because in this expression
(y == 'a' || 'b')
you are evaluating an OR of y == 'a' and 'b', and since 'b' evaluates to true by virtue of being non-zero, the whole expression evaluates to true.
(y == 'a' || true)
This line:
if (y == 'a' || 'b')
is equivalent to:
if ((y == 'a') || ('b'))
That's because the == operator has higher precedence than the || operator.
Since 'b' is non-zero, it always evaluates as true, and so (y == 'a' || 'b') always evaluates as true.
You need to write this:
if (y == 'a' || y == 'b')
Of course, even if the precedence was the other way around,
if (y == ('a' || 'b'))
would not have been what you intended either!
Please check the operator precedence (priority) here: http://en.cppreference.com/w/cpp/language/operator_precedence
In your case the condition expression is:
(y == 'a' || 'b')
So the “y == 'a'” part is evaluated first which may be true/false depending on the value of "y". Let's call the value of "y=='a'" as "t". And then the expression is evaluated as " t || 'b'" in this case 'b' is actually the ASCII code value of character 'b' (98) which is surely larger than 0, so the result of the boolean expression is always true.
To dismiss any ambiguity caused by operator precedence, I think it's a good habit to use brackets to explicitly express your priority in the evaluation. In your case, as suggested by earlier post, it should be:
if ((y=='a') || (y=='b'))