I'm very new to coding and have hit a confusing spot...I have made a very basic ticTacToe game and when I am trying to check the value of the array to see if there are 3 in a row it is not grabbing the values (or maybe it is but im out of scope??).
Just wondering how I would go about checking the value of my multi array?
Here is the code.
user.cpp // check win function
void User::checkForWin()
{
board board;//construct board
if ((board.ticTacToeBoard[0][0] == getUser1Char()) && (board.ticTacToeBoard[0][1] == getUser1Char()) &&
(board.ticTacToeBoard[0][2] == getUser1Char()))//Check array values to see if they win. PROBLEM AREA
{
std::cout << getUserName(_user1Char) << "You Are The Winner!" << std::endl;
exit(0);
}
User.cpp // Game loop
void User::userGo(char userGo)
{
board board; //Construct board
board.initBoard(); //Initilize board
int quitGame = 1; //sets value of quit game loop...This isnt working either but a minor issue for now as im just using exit(); until i figure it out
while (quitGame == 1) //game loop
{
while (userGo == 'G') //loop to swap user goes
{
invalid1: //goto return point if user1 enters an invalid character.
cout << getUserName('A') << " Please enter a letter between A and I or Q for quit" << endl;
char player1Input; //
cin >> player1Input;
if ((player1Input == 'Q') || (player1Input == 'A') || (player1Input == 'B') || // If player input equals
(player1Input == 'C') || (player1Input == 'D') || (player1Input == 'E') || // any of these values
(player1Input == 'F') || (player1Input == 'G') || (player1Input == 'H') || // then run for loop
(player1Input == 'I'))
{
for (int iii = 0; iii < 3; iii++) // Looping through tictactoe board values
{ // values are set to A through I
for (int jjj = 0; jjj < 3; jjj++) // as there are 9 places in the array
{
switch (player1Input) // Checking user input against and placing into array in relevant spot.
{ // *Find More elegant way to right this maybe with a loop.
case 'Q':
cout << "Thanks for Playing! " << endl;
quitGame = 2;
exit(0);
case 'A':
board.ticTacToeBoard[0][0] = 'X';
break;
case 'B':
board.ticTacToeBoard[0][1] = 'X';
break;
case 'C':
board.ticTacToeBoard[0][2] = 'X';
break;
case 'D':
board.ticTacToeBoard[1][0] = 'X';
break;
case 'E':
board.ticTacToeBoard[1][1] = 'X';
break;
case 'F':
board.ticTacToeBoard[1][2] = 'X';
break;
case 'G':
board.ticTacToeBoard[2][0] = 'X';
break;
case 'H':
board.ticTacToeBoard[2][1] = 'X';
break;
case 'I':
board.ticTacToeBoard[2][2] = 'X';
break;
default:
break;
}
}
}
}
else
{
cout << "Sorry ";
getUserName('A'); // If none of the values are correct print out wrong value statement
cout << " This is not a valid move." << endl; // and send the user back to the invalid1 Marker.
goto invalid1;
}
checkForWin(); // Check for win - PROBLEM AREA
board.printBoard(); // Print board for user2 visual
userGo = 'F'; // swap to User2's Go.
}
while (userGo == 'F') //loop to swap user goes
{
invalid2: //goto return point if user2 enters an invalid character.
cout << getUserName('B') << " Please enter a letter between A and I or press Q to quit." << endl;
char player2Input;
cin >> player2Input;
if ((player2Input == 'Q') || (player2Input == 'A') || (player2Input == 'B') || // If player input equals
(player2Input == 'C') || (player2Input == 'D') || (player2Input == 'E') || // any of these values
(player2Input == 'F') || (player2Input == 'G') || (player2Input == 'H') || // then run for loop
(player2Input == 'I'))
{
for (int iii = 0; iii < 3; iii++) // Looping through tictactoe board values
{ // values are set to A through I
for (int jjj = 0; jjj < 3; jjj++) // as there are 9 places in the array
{
switch (player2Input) // Checking user input against and placing into array in relevant spot.
{ // *Find More elegant way to right this maybe with a loop.
case 'Q':
cout << "Thanks for Playing" << endl;
quitGame = 2;
exit(0);
break;
case 'A':
board.ticTacToeBoard[0][0] = 'O';
break;
case 'B':
board.ticTacToeBoard[0][1] = 'O';
break;
case 'C':
board.ticTacToeBoard[0][2] = 'O';
break;
case 'D':
board.ticTacToeBoard[1][0] = 'O';
break;
case 'E':
board.ticTacToeBoard[1][1] = 'O';
break;
case 'F':
board.ticTacToeBoard[1][2] = 'O';
break;
case 'G':
board.ticTacToeBoard[2][0] = 'O';
break;
case 'H':
board.ticTacToeBoard[2][1] = 'O';
break;
case 'I':
board.ticTacToeBoard[2][2] = 'O';
break;
default:
break;
}
}
}
}
else
{
cout << "Sorry " << _name2;
getUserName('B'); // If none of the values are correct print out wrong value statement
cout << " This is not a valid move." << endl; // and send the user back to the invalid2 Marker.
goto invalid2;
}
}
checkForWin(); // Check for win - PROBLEM AREA
board.printBoard(); // Print board for user1 visual
userGo = 'G'; // swap to User1's Go.
}
}
I know I have used a load of magic numbers/characters and my code isn't going to be the most elegant as I am just learning, please any advice is much appreciated and also and mainly the reason I posted.
Why won't checkForWin() do what its told?
You need to either add a member variable to User which represents the board, a global variable that can be seen by everything, or you need to make checkForWin take a board as a parameter.
checkForWin(Board& board)
{
//Board board; // << remove this line
You would then pass the local board to checkForWin each time:
checkForWin(board);
A better design, though, would be to make checkForWin a member function of Board rather than User so that you would call:
board.checkForWin();
There are other design critiques and code changes I could recommend but that goes well beyond the scope of answering your question, better to let you absorb all of this and continue your studies at an appropriate pace :)
In the checkForWin function, the variable board is a local variable. It exists only for that function and is default constructed.
If you have a User::board member variable, or a global board variable, your local definition shadows and overrides the member/global variable.
Same in the userGo function.
Related
I'm making a game that tests the ASCII strength of a user versus a bot. (There is also a 2 player mode but that's working fine.) The full description is given at the top of my .cpp file. As a basic breakdown, the bot opens a txt file with 500 common four letter words and inserts them into a size 500 array. It then randomly generates a number to pick a random one, and then goes through the process of tovalue() to recieve its ASCII value, where in tovalue() runs through chartoint() four times, one for each character of the word. My issue is that the program calculates the ASCII value perfectly fine of the user generated word, but always returns 0 (0000) for the botword, no matter what the word.
I've tried a few iterations of the generateword() function including using a vector but always get the same resutls. I've done a lot of digging about this and haven't quite found any solutions, although I suspect that the chartoint() function could be better optimized, just not sure how to impliment any better solutions for this specific case. Also, don't think the problem is with chartoint() since it works fine for user input, but I'm pretty sure the problem is with generateword(). Suggestions for making chartoint() would be helpful, but its not my main priority right now since I just need the program to 100% work first. Also, I've confirmed that all of the words in my .txt file are all caps and only four characters per line.
// Write the code for a game called “ASCII Strength” of a four-letter word selected by Player 1
// followed by a four-letter word selected by Player 2. The result would be the sum
//of the ASCII value of each of the letters of the selected words and whoever has higher sum (called ASCII strength) wins.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;;
int chartoint(char a) {
switch (a) {
case 'A':
return 1;
break;
case 'B':
return 2;
break;
case 'C':
return 3;
break;
case 'D':
return 4;
break;
case 'E':
return 5;
break;
case 'F':
return 6;
break;
case 'G':
return 7;
break;
case 'H':
return 8;
break;
case 'I':
return 9;
break;
case 'J':
return 10;
break;
case 'K':
return 11;
break;
case 'L':
return 12;
break;
case 'M':
return 13;
break;
case 'N':
return 14;
break;
case 'O':
return 15;
break;
case 'P':
return 16;
break;
case 'Q':
return 17;
break;
case 'R':
return 18;
break;
case 'S':
return 19;
break;
case 'T':
return 20;
break;
case 'U':
return 21;
break;
case 'V':
return 22;
break;
case 'W':
return 23;
break;
case 'X':
return 24;
break;
case 'Y':
return 25;
break;
case 'Z':
return 26;
break;
}
return 0;
}
int tovalue(string input) {
int first = chartoint(input[0]);
int second = chartoint(input[1]);
int third = chartoint(input[2]);
int fourth = chartoint(input[3]);
cout << first << second << third << fourth; // EXISTS TO TEST CALCULATION
int value = first + second + third + fourth;
return value;
}
string generateword() {
string arr[500];
ifstream file("words.txt");
if (file.is_open())
{
for (int i = 0; i < 500; i++) {
string temp;
getline(file, temp);
arr[i] = temp;
}
file.close();
}
else
{
cout << "Error: Unable to open file.";
exit(0);
}
srand(time(0));
int random_index = rand() % 500;
string random_word = arr[random_index];
return random_word;
}
int main()
{
cout << "Welcome to ASCII strength, a game where the strongest word wins!";
cout << "\nTo play, you must enter a four letter word. The program will calculate the 'ASCII strength' of your word and compare it to your opponent.";
cout << "\nWhoever has the higher sum will win!";
char another;
another = 'y';
while (another == 'y' || another == 'Y') {
cout << "\nWould you like to play against a friend, or against a bot? (F/B)";
char mode;
cin >> mode;
if (mode == 'F' || mode == 'f') {
cout << "\nPlayer 1, please input your four letter word in all caps: ";
string answer1;
cin >> answer1;
int value1;
value1 = tovalue(answer1);
cout << "\nPlayer 2, please input your four letter word in all caps: ";
string answer2;
cin >> answer2;
int value2;
value2 = tovalue(answer2);
if (value1 > value2) {
cout << "\nPlayer 1 wins!";
}
else if (value2 > value1) {
cout << "\nPlayer 2 wins!";
}
else if (value1 == value2) {
cout << "\nTie!";
}
}
else if (mode == 'B' || mode == 'b') {
cout << "\nPlease input your four letter word in all caps: ";
string answer;
cin >> answer;
int valueanswer;
valueanswer = tovalue(answer);
string botword;
botword = generateword();
cout << "\nThe bot generates a random word based on a list of popular four letter words.";
cout << "\nThe bot has generated this word: " << botword;
int valuebot;
valuebot = tovalue("botword");
cout << valueanswer << " " << valuebot; // THIS EXISTS PURELY TO TEST WHETHER THE VALUES ARE PROPERLY CALCULATING
if (valueanswer > valuebot) {
cout << "\nYou win!";
}
else if (valuebot > valueanswer) {
cout << "\nThe bot wins!";
}
else if (valueanswer == valuebot) {
cout << "\nTie!";
}
}
cout << "\nWould you like to start a new game? (y/n)";
cin >> another;
}
}
Your problem is this line:
valuebot = tovalue("botword");
Since all characters in "botword" are lowercase, you get all 0 score. You probably meant to write
valuebot = tovalue(botword);
I have been having an issue getting the if else statement to properly work in the code.
I have everything else where I need it, just we are supposed to have multiple entries input and it just automatically uses the responses and the else statements do not work.
int main ()
{
string dep = "Deposit";
string with = "Withdrawl";
string bal = "Balance";
char choice;
cout << "PLease enter options A, B, C, or Q to quit.\n";
cin >> choice;
switch (choice) //to make them all the same, same as using toUpper
{
case 'a':
case 'A':
cout << "";
break;
case 'b':
case 'B':
cout << "";
break;
case 'q':
case 'Q':
cout << "";
break;
}
int count = 1;
while (count <= 4)
{
if (choice == 'a' || 'A' )
cout << dep << endl;
else if (choice == 'b' || 'B' )
cout << with << endl;
else if(choice == 'c' || 'C' )
cout << bal << endl;
else
(choice !='a' && choice !='b' && choice !='c');
cout << "that is invalid, PLease enter options A, B, C, or Q to quit.\n";
++count ;
}
system ("PAUSE");
return 0;
}
You need to fix the conditional statements like this:
if (choice == 'a' || choice == 'A' )
What you have will always result in the first conditional being met because 'A' is equal to decimal 65.
if(choice == 'a'||'A'),the computers will run the 'a'||'A' first,and it's return 1 (in bool) ,and then run the
choice == 1,according to your codes, there are no choice == 1,so the codes in if will not be run.
So I'm trying to write an easy basic game here with basic C++, and when I try to execute this
// global variabless
const char UP = 'w', LEFT = 'a', DOWN = 's', RIGHT = 'd'; // player movement choices
char playerMove; // goes with askPlayer
void askPlayer()
{
char choice;
cout << "Use the WASD keys to move: ";
cin >> choice;
int worked;
do{
if (choice == 'w' || choice == 'W')
{
playerMove = UP;
worked = 1;
}
else if (choice == 'a' || choice == 'A')
{
playerMove = LEFT;
worked = 1;
}
else if (playerMove == 's' || playerMove == 'S')
{
playerMove = DOWN;
worked = 1;
}
else if (playerMove == 'd' || playerMove == 'D')
{
playerMove = RIGHT;
worked = 1;
}
else
{
cout << "Invalid entry." << endl;
worked = 0;
}
} while (worked != 1);
return;
}
It works up to the user entering a letter. Xcode says (lldb) then the page fills up with numbers, and after you stop the run, it says "Program ended with exit code: 9". It does this even if you enter one of the valid values
You never prompt for another value after the user enters the first one:
cin >> choice; // <==
int worked;
do {
// ..
} while (worked != 1);
Just move the input into the loop:
int worked;
do {
cin >> choice; // possibly with cout prompt too
// rest as before
} while (worked != 1);
Your input is outside the loop, your variable worked is uninitialized ( though it is not a error in your code but is cleaner to initialize your variables) and it should have bool type. Whole code can be simplified by the switch statement:
void askPlayer()
{
do {
char choice;
cout << "Use the WASD keys to move: ";
cin >> choice;
switch( choice ) {
case 'w' : case 'W' :
playerMove = UP;
break;
case 'a' : case 'A' :
playerMove = LEFT;
break;
case 's' : case 'S' :
playerMove = DOWN;
break;
case 'd' : case 'D' :
playerMove = RIGHT;
break;
default:
cout << "Invalid entry." << endl;
continue;
}
} while( false );
return;
}
To start, I'm trying to make a GPA calculator for my class.
I know how to compare strings, so I'm good there. The issue I'm having is that I'm trying to set up a situation so when the user inputs anything other than a letter grade value, it will return an error message. I've set up two arrays, one that stores string values and another that stores integral values. The idea was to use the string array to store the entered grade letter inputs, then use those to determine the GPA value for each class. It would then store that value into the integral array. I hate to be obnoxious, but here's the code for the first section alone:
void gpaCalSetClassNum5(){
string mathWeight5;
string scienceWeight5;
string historyWeight5;
string englishWeight5;
string elective1Weight5;
string elective2Weight5;
string gpaClassSet5[] = {"null", "null", "null", "null", "null"};
int gpaClassSet5int[] = {};
cout << "Enter the grade value of each of your classes." << endl;
/////////////////////////
MATH:
cout << "Math" << endl;
cin >> gpaClassSet5[0];
if (gpaClassSet5[0] == "A") {
gpaClassSet5int[0] = 4;
} else if (gpaClassSet5[0] == "a") {
gpaClassSet5int[0] = 4;
} else if (gpaClassSet5[0] == "B") {
gpaClassSet5int[0] = 3;
} else if (gpaClassSet5[0] == "b") {
gpaClassSet5int[0] = 3;
} else if (gpaClassSet5[0] == "C") {
gpaClassSet5int[0] = 2;
} else if (gpaClassSet5[0] == "c") {
gpaClassSet5int[0] = 2;
} else if (gpaClassSet5[0] == "D") {
gpaClassSet5int[0] = 1;
} else if (gpaClassSet5[0] == "d") {
gpaClassSet5int[0] = 1;
} else if (gpaClassSet5[0] == "F") {
gpaClassSet5int[0] = 0;
} else if (gpaClassSet5[0] == "f") {
gpaClassSet5int[0] = 0;
} else if (gpaClassSet5[0] != ){
cout << "Did you enter a letter grade value?" << endl;
goto MATH;
}
cout << "You have selected " << gpaClassSet5[0] << ", or " << gpaClassSet5int[0] << endl;
cout << "Is this class weighted? Use Y/N." << endl;
cin >> mathWeight5;
if (mathWeight5 == "Y" || "y") {
gpaClassSet5int[0] = gpaClassSet5int[0] + 1;
}
I'm looking for a simplified version of this. Why can't I use something like:
if(gpaClassSet5[0] == "A" || "a"){
//stuff//
}
I'm in need of a simplified version because, like a switch, I'd like to use different inputs to do different things -- but ultimately have a default in case any of the values listed weren't entered.
How can I do this? How can I set up a switch in C++?
Sorry if this question is a little dumb, I'm getting into C++ and these self-made programs are really my only practice.
Full program code here: http://justpaste.it/ee4u
Because that's not how C++ is specified to work, you need to do the comparison twice:
if(gpaClassSet5[0] == "A" || gpaClassSet5[0] == "a")
The logical OR operation means "if the left-hand expression is true, or the right-hand expression is true". In your case with the code as in your question, the right-hand side expression will always be true as "a" is not zero (i.e. false).
Operator precedence says you can't do it this way. gpaClassSet5[0] == "A" || "a" is the same as (gpaClassSet5[0] == "A") || ("a").
If you don't want to write gpaClassSet5[0] twice, you could use regular expressions if you don't mind a performance hit
std::regex_match(gpaClassSet5[0], std::regex("A|a"));
This gets more sensible if you test against a lot of possible matches:
std::regex_match(gpaClassSet5[0], std::regex("A|Grade A|1|Excellent|Outstanding|Perfect|Perfect Score)"));
If you are not using C++11 (don't have std::regex), you can use boost::regex from boost.org.
Or you could solve your specific code example with more compact logic:
char gradeLetter = std::tolower(gpaClassSet5[0])
if (gradeLetter >= 'a' && gradeLetter <= 'd')
gpaClassSet5int[0] = 4-(gradeLetter -'a');
else if (gradeLetter == 'f')
gpaClassSet5int[0] = 0;
else
{
cout << "Did you enter a letter grade value?" << endl;
goto MATH;
}
And extract a function to get rid of the goto and make the code easier to read:
int ConvertLetterToNumericGrade(char gradeLetter)
{
char lower = std::tolower(gradeLetter);
if (lower >= 'a' && lower <= 'd')
return 4-(lower -'a');
if (lower == 'f')
return 0;
throw std::runtime_error("cannot convert invalid grade letter");
}
void gpaCalSetClassNum5()
{
...
while (true)
{
cin >> gpaClassSet5[0];
try { gpaClassSet5int[0] = ConvertLetterToNumericGrade(gpaClassSet5[0]); }
catch (const std::runtime_error& )
{
cout << "Did you enter a letter grade value?" << endl;
continue;
}
break;
}
...
}
And with a switch (which is not supported for strings, but is supported for char and wchar):
int ConvertLetterToNumericGrade(char gradeLetter)
{
switch (gradeLetter)
{
case 'a':
case 'A':
return 4;
case 'b':
case 'B':
return 3;
case 'c':
case 'C':
return 2;
case 'd':
case 'D':
return 1;
case 'f':
case 'F':
return 0;
default:
cout << "Did you enter a letter grade value?" << endl;
throw std::runtime_error("cannot convert invalid grade letter");
}
}
Resp.
int ConvertLetterToNumericGrade(char gradeLetter)
{
switch (std::tolower(gradeLetter))
{
case 'a': return 4;
case 'b': return 3;
case 'c': return 2;
case 'd': return 1;
case 'f': return 0;
default:
cout << "Did you enter a letter grade value?" << endl;
throw std::runtime_error("cannot convert invalid grade letter");
}
}
Hello is there a different way to convert a int back to a char see comment about half way down the code. Im thinking the use of a switch or an if statement but i cannot figure out hot to apply it. i used char RPS[] = {'?', 'R', 'P', 'S'};
#include <iostream>
using namespace std;
#include <ctime>
#include <cstdlib>
//human choice function
int hchoice()
{
char entry;
int usrchoice = 0;
while (1)
{
cout <<"Choose R for Rock P for Paper, S for Sissors or Q for quit ";
cin >> entry;
cin.ignore(1000, 10);
switch (toupper(entry)){
case 'R':
usrchoice = 1;
break;
case 'P':
usrchoice = 2;
break;
case 'S':
usrchoice = 3;
break;
case 'Q':
usrchoice = -1;
break;
}
if (usrchoice != 0)break;
cout << "Invalid Entry" <<endl;
}
return usrchoice;
}
//Computer choice function
int compchoice()
{
return (1 + rand() % 3);
}
void printresults(int computer, int human)
{
//Number to char converter? Can i use a switch here?
char RPS[] = {'?', 'R', 'P', 'S'};
cout << "Computer:" << RPS[computer];
cout << ", Human:" << RPS[human];
cout << ", ";
if (computer == human){
cout <<"tie";
}
else if ( ( human==1 && computer == 2) || (human == 2 && computer == 3) || (human == 3 && computer == 1)){
cout << "computer wins!";
}
else {
cout <<"Human Wins!";
}
cout << endl;
}
int main()
{
// initialize the computer's random number generator
srand(time(0)); rand();
// declare variables
int human = 0, computer = 0;
// start loop
while (1)
{
// determine computer's choice
computer = compchoice();
// prompt for, and read, the human's choice
human = hchoice();
// if human wants to quit, break out of loop
if (human == -1) break;
// print results
printresults(computer, human);
cout << endl;
// end loop
}//while
// end program
return 0;
}
You could use a switch there, or a series of if statements. However, what you have right now is by far the most concise and -- I would argue -- the easiest to read.
One more general thing that I would suggest is to use symbolic constants (e.g. an enum) instead of the hard-coded numbers 1, 2 and 3 that you have in several places in your code.