I am creating a simple command line, tic-tac-toe game in C++. Whenever I reun the code I get no compiler errors but then VSCode tells me once I have given input that there is a Segmentation Fault. I will paste my code below:
#include <iostream>
#include <cmath>
using namespace std;
void print_board(string board[3][3])
{
cout << " | | " << endl;
cout << " " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " " << endl;
cout << "_____|_____|_____" << endl;
cout << " | | " << endl;
cout << " " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " " << endl;
cout << "_____|_____|_____" << endl;
cout << " | | " << endl;
cout << " " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " " << endl;
cout << " | | " << endl;
}
string turn(string board[3][3], bool xturn)
{
int position;
cout << "Where would you like to go (1 - 9): ";
cin >> position;
if (xturn)
{
string player_turn = "X";
}
else
{
string player_turn = "O";
}
board[(int)floor(position / 3)][(position % 3) - 1] = "X";
return board[3][3];
}
int main(void)
{
string board[3][3] = {{" ", " ", " "}, {" ", " ", " "}, {" ", " ", " "}};
bool xturn = true;
while (true)
{
print_board(board);
board[3][3] = turn(board, xturn);
xturn = !xturn;
}
return 0;
}
Any help is much is much appreciated. Thanks! If it helps I am using the GCC compiler.
void print_board(string board[3][3])
why are you using a string[3][3] ? you basically just need a 3x3 character array
board[(int)floor(position / 3)][(position % 3) - 1] = "X";
make sure you keep yourself in range 0..2, -1 is outside and will
cause undefined behavior
return board[3][3];
No that is wrong in more ways than one, and in any case there is no need to return a copy
board[3][3] = turn(board, xturn);
this will not go well, you return a board of 3x3 strings but assign
it to at best, an undefined place.
since you already pass the address of the board to your turn function, that is that is all needed. change it in place.
turn(board, xturn);
arrays are addresses in memory, it is the starting address where in memory some data is stored
if you pass an array/matrix to a function you are letting the function know where in memory it is stored, so any changes to the array/matrix will be done in place, therefore you do not need to return a copy.
Related
I am making a hangman game on my own and I have ran into a problem where I need to know if the guess is in the secret word. if it is I will change the bool innum to true, if it is not it will stay false. i have looked it up and cannot find anything that works. also the name printe is just the name of the string its just what I've named it.
here is the code I am working with:
using namespace std;
#include <iostream>
#include <conio.h>
void title();
void rightanswer();
void try1();
void try2();
void try3();
void try4();
void try5();
void try6();
void spacer();
int main()
{
bool innum = false;
int printe = 0, attempts_wrong = 0, trynum = 6;
char guess;
string secretword, hint1, hint2;
title();
// the welcoming senteces
cout << "Welcome to HANG MAN\n\n" << endl;
cout << "Please enter the secret word (no spaces): ";
cin >> secretword;
// the hints
cout << "\nenter the first hint: ";
cin >> hint1;
cout << "\nenter the second hint: ";
cin >> hint2;
//explanation for hints
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; //so guesser cant see word
cout << "\nthe hints will be used as the guesser runs out of attemptts" << endl;
cout << "the first hint will be used immediately\n\n" << endl;
cout << "press any button to start...";
_getch();
cout << "\n\n" << endl;
for (int i = 0; secretword[i] != '\0'; ++i)
{
printe++;
}
rightanswer();
cout << "\nyour word is " << printe << " letters long" << endl;
if (attempts_wrong == 0)
{
cout << "your first hint is: ";
cout << hint1 << endl;
}
if (attempts_wrong == 3)
{
cout << "your second hint is: ";
cout << hint2 << endl;
}
cout << "enter a letter: ";
cin >> guess;
// im gonna have the code go here
// <-----------------------------
if (innum == true)
{
spacer();
cout << guess << " is in the secret word" << endl;
rightanswer();
}
else if (innum == false)
{
spacer();
cout << guess << " is not in the secret word" << endl;
rightanswer();
attempts_wrong++;
}
return 0;
}
void title() {
cout << "*****************************************" << endl;
cout << "* _____ *" << endl;
cout << "* | | /\\ |\\ | | *" << endl;
cout << "* |_____| /__\\ | \\ | | ___ *" << endl;
cout << "* | | / \\ | \\ | | | *" << endl;
cout << "* | | / \\| \\| |_____| *" << endl;
cout << "* *" << endl;
cout << "* |\\ /| /\\ |\\ | *" << endl;
cout << "* | \\ / | /__\\ | \\ | *" << endl;
cout << "* | \\ / | / \\ | \\ | *" << endl;
cout << "* | V | / \\| \\| *" << endl;
cout << "* *" << endl;
cout << "*****************************************" << endl;
}
//head, body, 2 arms, 2 legs - 6 in total
void rightanswer() {
//if the guess is right and the start
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " | " << endl;
cout << " __|__ " << endl;
}
void try1() {
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " O | " << endl;
cout << " | " << endl;
cout << " __|__ " << endl;
}
void try2() {
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " O | " << endl;
cout << " | | " << endl;
cout << " __|__ " << endl;
}
void try3() {
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " O | " << endl;
cout << " /| | " << endl;
cout << " __|__ " << endl;
}
void try4() {
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " O | " << endl;
cout << " /|\ | " << endl;
cout << " __|__ " << endl;
}
void try5() {
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " O | " << endl;
cout << " /|\ | " << endl;
cout << " / __|__ " << endl;
}
void try6() {
cout << " ___ " << endl;
cout << " | | " << endl;
cout << " O | " << endl;
cout << " /|\ | " << endl;
cout << " / \__|__ " << endl;
cout << " YOU LOSE" << endl;
cout << "you have run out of guesses";
exit(0);
}
// it creates a line to differ one try from the other
void spacer() {
cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;
}
I don't know how much to show so that is all of it, its probably not the best but it works. I know that I don't some of the voids functions at the bottom but it works for now. if you have any suggestions tell me them. also don't be to harsh, I'm a beginner.
There are a few ways of approaching this. If you actually want to simply find if a string contains a character, the following works:
char needle;
haystack.find(needle) != string::npos;
As others have correctly answered. However, in this case, I think you are looking for something slightly different. Its a game of hangman so what you actually may want to do is show the portions of the word that the individual has actually guessed correctly.
Efficient
If we assume that: display is a string initialised with _ (or some character that is not a valid letter in a guessable word) as each character to the length of the string, you can work with this to partially display it.
If we have a map<char, vector<size_t>> that tells us exactly the indices that each character occurs at, which is easy to compute, we can take the guess and iterate through the corresponding vector of indices and replace characters in display with the actual character and then remove the character from the map. Once the map is empty, then the entire string has been guessed. You may also want to maintain a set of characters that have already been guessed to ensure that the same character can only be guessed once.
I will leave it as an exercise for you to implement this as it shouldn't be too difficult. If you'd like some pointers, let me know.
Less Efficient
This second way is less efficient, but since its a real-time game it won't make a difference unless these strings are really long.
Simply hold a copy of the string and iterate through it. Every time check which character you are checking against then replace the character at the index you are at in the _ word with the correct character. You can also keep a flag which checks whether or not any replacements happen and if not, you know that the character does not exist in the word.
You may use std::string::find method to find the given character (returns the position of the character or std::string::npos if it is not found): http://www.cplusplus.com/reference/string/string/find/
Example:
std::string str = "Hello.World";
auto found = str.find('.');
if (found != std::string::npos)
std::cout << "Period found at: " << found << std::endl;
In your case, it could look as such:
innum = (secretword.find(guess) != std::string::npos);
Try string.find.
auto i =secretword.find(guess); gives you the index. If it equals std::string::npos it isn't there.
Also, std::string has a size() method you can rrplace your letter counting with.
I am writing in C++ and the errors I am having are:
E0120 return value type does not match the function type
C4700 uninitialized local variable 'name' used
C2562 interact 'void function returning a value
And a warning error of C4447.
My code is down below:
#include <limits>
#include <cstdlib>
#include <fstream>
#include <iostream>
using namespace std;
void readFile(char sudokuBoard[][9]);
void writeFile(char sudokuBoard[][9]);
void display(char sudokuBoard[][9]);
void interact();
void getOption(char sudokuBoard[][9]);
void editSquare(char sudokuBoard[][9]);
void showValues();
void openingMessage();
void openingQuestion();
//opening message to the game and pause
void openingMessage()
{
std::cout << "Welcome to Sudoku"
<< endl << "Press any key to continue.";
cin.ignore();
}
//Questions to determine whether the user will play the game
void openingQuestion()
{
char response; // users input to the question below
cout << "Would you like to play Sudoku ? " << endl << "1 for yes, 2 for no";
cin >> response;
if (response == 1) //if there answer is yes
{
//return main();
}
else if (response == 2) //if answer is no
{
cout << "are you sure you do not want to play ?" << endl << "1 for yes and 2 for no";
//if user answers no
char eResponse; //response to the next question
if (eResponse == 2) // 2 equals no
{
return main();
}
// if user answers yes
if (eResponse == 1) // 1 equals yes
{
//return exit();
}
}
}
//Makes other functions function
int main()
{
//Declaring array
char sudokuBoard[9][9];
//calling the other functions
readFile(sudokuBoard);
interact();
display(sudokuBoard);
return 0;
}
//Asks the user for a fulename to read a gamebaord
//in from that file name and then places it in an array
void readFile(char sudokuBoard[][9])
{
//Declare filename
char sourceFile[256];
//Declaring file input
ifstream fin;
//Getting the filename from the user
cout << "Where is your board located? ";
cin >> sourceFile;
//Open file error checking
fin.open(sourceFile);
if (fin.fail())
{
cout << "Input file opening failed. " << endl;
exit(1);
}
//Read file into array
for (int col = 0; col < 9; col++)
{
for (int row = 0; row < 9; row++)
{
fin >> sudokuBoard[row][col];
if (sudokuBoard[row][col] == '0')
{
sudokuBoard[row][col] = ' ';
}
}
}
//close the file
fin.close();
}
//displays the result to the screen
void display(char sudokuBoard[][9])
{
//Declare variables
char option;
//Display Column Title
cout << " A| B| C| D| E| F| G| H| I" << endl;
//Row 1
cout << "1 "
<< sudokuBoard[0][0]
<< " " << sudokuBoard[1][0]
<< " " << sudokuBoard[2][0]
<< "|"
<< sudokuBoard[3][0]
<< " " << sudokuBoard[4][0]
<< " " << sudokuBoard[5][0]
<< "|"
<< sudokuBoard[6][0]
<< " " << sudokuBoard[7][0]
<< " " << sudokuBoard[8][0]
<< endl;
//Row 2
cout << "2 "
<< sudokuBoard[0][0]
<< " " << sudokuBoard[1][1]
<< " " << sudokuBoard[2][1]
<< "|"
<< sudokuBoard[3][1]
<< " " << sudokuBoard[4][1]
<< " " << sudokuBoard[5][1]
<< "|"
<< sudokuBoard[6][1]
<< " " << sudokuBoard[7][1]
<< " " << sudokuBoard[8][1]
<< endl;
//Row 3
cout << "3 "
<< sudokuBoard[0][2]
<< " " << sudokuBoard[1][2]
<< " " << sudokuBoard[2][2]
<< "|"
<< sudokuBoard[3][2]
<< " " << sudokuBoard[4][2]
<< " " << sudokuBoard[5][2]
<< "|"
<< sudokuBoard[6][2]
<< " " << sudokuBoard[7][2]
<< " " << sudokuBoard[8][2]
<< endl;
//Separator
cout << " -----_-----_-----" << endl;
//Row 4
cout << "4 "
<< sudokuBoard[0][3]
<< " " << sudokuBoard[1][3]
<< " " << sudokuBoard[2][3]
<< "|"
<< sudokuBoard[3][3]
<< " " << sudokuBoard[4][3]
<< " " << sudokuBoard[5][3]
<< "|"
<< sudokuBoard[6][3]
<< " " << sudokuBoard[7][3]
<< " " << sudokuBoard[8][3]
<< endl;
//Row 5
cout << "5 "
<< sudokuBoard[0][4]
<< " " << sudokuBoard[1][4]
<< " " << sudokuBoard[2][4]
<< "|"
<< sudokuBoard[3][4]
<< " " << sudokuBoard[4][4]
<< " " << sudokuBoard[5][4]
<< "|"
<< sudokuBoard[6][4]
<< " " << sudokuBoard[7][4]
<< " " << sudokuBoard[8][4]
<< endl;
//Row 6
cout << "6 "
<< sudokuBoard[0][5]
<< " " << sudokuBoard[1][5]
<< " " << sudokuBoard[2][5]
<< "|"
<< sudokuBoard[3][5]
<< " " << sudokuBoard[4][5]
<< " " << sudokuBoard[5][5]
<< "|"
<< sudokuBoard[6][5]
<< " " << sudokuBoard[7][5]
<< " " << sudokuBoard[8][5]
<< endl;
//Separator
cout << " -----_-----_-----" << endl;
//Row 7
cout << "7 "
<< sudokuBoard[0][6]
<< " " << sudokuBoard[1][6]
<< " " << sudokuBoard[2][6]
<< "|"
<< sudokuBoard[3][6]
<< " " << sudokuBoard[4][6]
<< " " << sudokuBoard[5][6]
<< "|"
<< sudokuBoard[6][6]
<< " " << sudokuBoard[7][6]
<< " " << sudokuBoard[8][6]
<< endl;
//Row 8
cout << "8 "
<< sudokuBoard[0][7]
<< " " << sudokuBoard[1][7]
<< " " << sudokuBoard[2][7]
<< "|"
<< sudokuBoard[3][7]
<< " " << sudokuBoard[4][7]
<< " " << sudokuBoard[5][7]
<< "|"
<< sudokuBoard[6][7]
<< " " << sudokuBoard[7][7]
<< " " << sudokuBoard[8][7]
<< endl;
cout << "9 "
<< sudokuBoard[0][8]
<< " " << sudokuBoard[1][8]
<< " " << sudokuBoard[2][8]
<< "|"
<< sudokuBoard[3][8]
<< " " << sudokuBoard[4][8]
<< " " << sudokuBoard[5][8]
<< "|"
<< sudokuBoard[6][8]
<< " " << sudokuBoard[7][8]
<< " " << sudokuBoard[8][8]
<< endl
<< endl;
getOption(sudokuBoard);
}
//Allows the user to interact and manipulate the game board
void interact()
{
cout << "Options:" << endl
<< " ? Show these instructions" << endl
<< " D Display the board" << endl
<< " X Edit one square" << endl
<< " H Help show the possible values for one of the squares"
<< endl
<< " Q Save and Quit" << endl
<< endl;
return getOption;
}
//gets the user's input
void getOption(char sudokuBoard[][9])
{
char option;
cout << "> ";
cin >> option;
if (option == 'x' || option == 'X')
editSquare(sudokuBoard);
else if (option == '?')
interact();
else if (option == 'd' || option == 'D')
display(sudokuBoard);
else if (option == 'h' || option == 'H')
showValues();
else if (option == 'q' || option == 'Q')
writeFile(sudokuBoard);
else
cout << "ERROR: Invalid command";
return;
}
//edits one square with coordinates entered by the user
void editSquare(char sudokuBoard[][9])
{
//Declare variables
char letter;
int number;
int value = 0;
//Get letter and number coordinates
cout << "What are the coordinates of the square: ";
cin >> letter >> number;
//Converts letter to uppercase
letter = toupper(letter);
//if square is full, display "read only" message
if (sudokuBoard[letter - 65][number - 1] != ' ')
{
cout << "ERROR: square \'" << letter
<< number << "\' is a read-only" << endl;
getOption(sudokuBoard);
}
else
{
//get value to place in the coordinates
cout << "what is the value at \'" << letter
<< number << "\': ";
cin >> value;
//makes sure value is within the right range
if (value < 1 || value > 9)
{
cout << "Try Again: Value |'" << value << "| in square |'"
<< letter << number << "|' is invalud" << endl;
cout << endl;
getOption(sudokuBoard);
}
// Check for duplicate in column
for (int row = 0; row < 9; ++row)
if (sudokuBoard[row][number - 1] == value)
{
cout << "ERROR: square \'" << letter
<< number << "\' you typed a duplicate number" << endl
<< "Please try again" << endl;
}
// Check for duplicate in row
for (int col = 0; col < 9; ++col)
if (sudokuBoard[letter - 65][col] == value)
{
cout << "ERROR: square \'" << letter
<< number << "\' you typed a duplicate number" << endl
<< "Please try again" << endl;
}
cout << endl;
sudokuBoard[letter - 65][number - 1] = value;
getOption(sudokuBoard);
}
return;
}
//writes the content of the board to a file to be picked up later
void writeFile(char sudokuBoard[][9])
{
//File output
ofstream fout;
char destinationFile[256];
//user input
cout << "What file would you like to write your board to: ";
cin >> destinationFile;
//Open destination file & error checking
fout.open(destinationFile);
if (fout.fail())
{
cout << "Output file opening failed" << endl;
exit(1);
}
else
cout << "Board written successfully";
//Write board to file
for (int col = 0; col < 9; col++)
{
for (int row = 0; row < 9; row++)
{
if (sudokuBoard[row][col] == ' ')
{
sudokuBoard[row][col] = '0';
}
fout << sudokuBoard[row][col];
//Makes sure it's a 9x9 grid
if (row % 9 == 0)
{
fout << endl;
}
}
}
//close file
fout.close();
}
//Show all the possible values for a given coordinates
void showValues()
{
//variables
char letter;
int number;
//letter/number coordinates
cout << "What are the coordinates of the square: ";
cin >> letter >> number;
//Coinverts letter to uppercase
letter = toupper(letter);
return;
}
I am using Visual Studio 2019 for this.
A couple notes to point out
first of all, you can not return the main function
in your line
if (eResponse == 2) // 2 equals no
{
return main();
}
next
you have a lot of void function with return statements
because the function is void you can not return anything
instead of
void getOption(char sudokuBoard[][9])
{
char option;
cout << "> ";
cin >> option;
if (option == 'x' || option == 'X')
editSquare(sudokuBoard);
else if (option == '?')
interact();
else if (option == 'd' || option == 'D')
display(sudokuBoard);
else if (option == 'h' || option == 'H')
showValues();
else if (option == 'q' || option == 'Q')
writeFile(sudokuBoard);
else
cout << "ERROR: Invalid command";
return;
}
use
char getOption(char sudokuBoard[][9])
{
char option;
cout << "> ";
cin >> option;
if (option == 'x' || option == 'X')
editSquare(sudokuBoard);
else if (option == '?')
interact();
else if (option == 'd' || option == 'D')
display(sudokuBoard);
else if (option == 'h' || option == 'H')
showValues();
else if (option == 'q' || option == 'Q')
writeFile(sudokuBoard);
else
cout << "ERROR: Invalid command";
return option;
}
go through your functions and ask yourself, do i need to return a value? if yes then change from void to what ever type you are using and if no then remove the return statement.
for your warning issue
char sudokuBoard[9][9];
is not being initialised.
you can do something like
char sudokuBoard[9][9] = {};
Program's Aim:
The program is a hangman game which get a list of planets from our solar system, saves it to an array then randomly selects one word from the array and subsequently prints two letters of the word on the board. The program runs perfectly in a windows environment, but fails in runtime on linux.
Problem:
The program replaces the first character in the output stream with the last character of that stream. That happens when printing the word on the board and also when the word is displayed when it is correctly or wrongly guessed.
e.g.:
word = Mars
For 6 wrong guess it's supposed to print, Too bad you didn't guess right. It was "mars".
Instead, it prints: "oo bad you didn't guess right. It was "mars
Here are the files:
wordlist.yx:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Pluto
Hangman.h:
#pragma once
#include <iostream>
using namespace std;
// Check for OS
#ifdef _WIN32
#define SYS "MS"
#else
#define SYS "LINUX"
#endif
class Hangman {
private:
int version = 3;
string release_date = "01/05/2016";
int &v = version;
string &r = release_date;
static const int WORDLIST_SIZE = 10;
string wordlist[WORDLIST_SIZE];
string word, hidden_word, wordfile = {"wordlist.yx"};
int word_length, tries_left;
bool is_match;
public:
Hangman();
~Hangman();
//attributes
string user_input, arch;
char choice;
// Game functionality methods
void printMenu(Hangman &);
void info(Hangman &) const;
void startGame(Hangman &);
void reset();
void getWordlist();
void getWordAndSetHidden();
int getTries();
void printHangman(int);
void printBoard();
void getInput(Hangman &);
int validateInput(char);
void decideFate(Hangman &);
void decision(Hangman &);
// Invalid input and screen clearing methods
void invalidInput1(Hangman &, char &);
void invalidInput2(Hangman &, string &);
void cls() const;
};
Hangman.cpp:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <limits>
#include <algorithm>
#include <string>
#include "Hangman.h"
using namespace std;
//Constructor
Hangman::Hangman(){
//Get's OS
// Microsoft
if(SYS == "MS"){
arch = "cls";
} else{
//linux, unix, OSX
arch = "clear";
}
hidden_word = "";
tries_left = 6;
}
// De-constructor
Hangman::~Hangman(){
//Destroy objects
}
// Menu Options
void Hangman::printMenu(Hangman &s){
cls();
cout << " _____Hangman (v7)_____ " << endl;
cout << "| |" << endl;
cout << "| Play - P |" << endl;
cout << "| Info - I |" << endl;
cout << "| Quit - Q |" << endl;
cout << "------------------------" << endl;
cout << "Choice: ";
getline(cin, user_input);
// Pass first character of string to char
choice = user_input[0];
switch(choice){
case 'p':
case 'P':
startGame(s);
break;
case 'i':
case 'I':
info(s);
break;
case 'q':
case 'Q':
cls();
cout << "Thank you for playing..." << endl;
exit(EXIT_SUCCESS);
break;
default:
invalidInput1(s, choice);
}
}
void Hangman::info(Hangman &m) const{
string ic;
cls();
cout << "+--------------------------------------------------------------------+\n"
<< "| Hangman Instructions |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| This Hangman game is played by entering a guessed letter at a time.|\n"
<< "| 6 wrong guesses are given by default and decrements by 1 (one) on |\n"
<< "| each wrong guess. |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| In-game options |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| restart - Start a new game |\n"
<< "| menu - Display main menu |\n"
<< "| quit - Exit game |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| Game Information |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| Version: " << v << " |\n"
<< "| Date: " <<r<< " |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| Author |\n"
<< "+--------------------------------------------------------------------+\n"
<< "| Philan James (Zoutiyx) |\n"
<< "| zoutiyx#gmail.com |\n"
<< "+--------------------------------------------------------------------+\n\n";
cout << "Press enter to close... ";
getline(cin, ic);
m.printMenu(m);
}
void Hangman::startGame(Hangman &h){
cls();
h.reset();
h.getWordlist();
h.getWordAndSetHidden();
h.decideFate(h);
do {
h.printHangman(h.getTries());
h.printBoard();
h.getInput(h);
h.decideFate(h);
} while(h.getTries() != 0);
}
//Gets the wordlist from a file and stores it into an array
void Hangman::getWordlist(){
fstream in_words(wordfile, ios::in);
if(!in_words.is_open()){
cerr << "Error 0: " << wordfile << " isn't found in current directory!\n";
} else{
for(int i = 0; (i < WORDLIST_SIZE - 1) && !in_words.eof(); i++){
getline(in_words, *(wordlist + i), '\n');
}
}
in_words.close();
}
void Hangman::getWordAndSetHidden(){
srand(time(NULL));
int word_index, p1, p2;
word_index = rand() % (WORDLIST_SIZE - 1) + 0;
word = wordlist[word_index];
// Sets the hidden word letters to underscores
for(unsigned int i = 0; i < word.length(); i++){
if(word[i] == ' ') {
hidden_word.push_back(' ');
} else {
hidden_word.push_back('_');
}
}
//selecting the random two indexes of the word
p1 = rand() % word.length();
p2 = rand() % word.length();
while (p1 == p2 || p2 == p1){
p1 = rand() % word.length();
p2 = rand() % word.length();
}
// Assigning the letter to the corresponding index
for(int i = 0; i < (int)word.length(); i++){
if (i == p1){
hidden_word[i] = word[i];
} else if( i == p2){
hidden_word[i] = word[i];
}
// If a certain letter is the same as the on at the p1 or p2,
// It is also printed on the board, making it more than (2) default letters
if (tolower(word[p1]) == tolower(word[i])){
hidden_word[i] = word[i];
}
if (tolower(word[p2]) == tolower(word[i])){
hidden_word[i] = word[i];
}
}
}
// Get lives remaining
int Hangman::getTries(){
return tries_left;
}
// Print's hangman state based on lives left
void Hangman::printHangman(int ll){
cls();
cout << "Planets in our solor system...\n\n";
cout << "Tries left: " << tries_left << endl;
switch (ll){
case 6:
cout << " |----| " << endl;
cout << " | " << endl;
cout << " | " << endl;
cout << " | " << endl;
cout << " | " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
case 5:
cout << " |----| " << endl;
cout << " | 0 " << endl;
cout << " | " << endl;
cout << " | " << endl;
cout << " | " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
case 4:
cout << " |----| " << endl;
cout << " | 0 " << endl;
cout << " | | " << endl;
cout << " | | " << endl;
cout << " | " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
case 3:
cout << " |----| " << endl;
cout << " | 0 " << endl;
cout << " | /| " << endl;
cout << " | | " << endl;
cout << " | " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
case 2:
cout << " |----| " << endl;
cout << " | 0 " << endl;
cout << " | /|\\ " << endl;
cout << " | | " << endl;
cout << " | " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
case 1:
cout << " |----| " << endl;
cout << " | 0 " << endl;
cout << " | /|\\ " << endl;
cout << " | | " << endl;
cout << " | / " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
case 0:
cout << " |----| " << endl;
cout << " | 0 " << endl;
cout << " | /|\\ " << endl;
cout << " | | " << endl;
cout << " | / \\ " << endl;
cout << "____|____ " << endl;
cout << endl;
break;
}
}
// Display hidden word
void Hangman::printBoard(){
for(unsigned int i = 0; i < hidden_word.length(); i++){
if(word[i] == ' '){
cout << word[i];
} else if(i != hidden_word.length()){
cout << hidden_word[i] << " ";
} else{
cout << hidden_word[i];
}
}
cout << endl << endl;
}
// Get letter choice and assign position 0 to character
void Hangman::getInput(Hangman &c){
cout << "Letter choice: ";
getline(cin, user_input);
transform(user_input.begin(), user_input.end(),
user_input.begin(), ::tolower);
if(user_input == "restart"){
c.reset();
c.startGame(c);
} else if(user_input == "menu"){
printMenu(c);
} else if(user_input == "quit"){
cout << "\nThank you for playing...\n";
exit(EXIT_SUCCESS);
} else{
choice = user_input[0];
user_input = "";
validateInput(choice);
}
}
// test character for validity
int Hangman::validateInput(char choice){
for(unsigned int i = 0; i < hidden_word.length(); i++){
//Checks if entered character is already on the board
if(toupper(choice) == hidden_word[i] || tolower(choice) == hidden_word[i]){
--tries_left;
return 0;
}
// Checks if character is a valid input
if(toupper(choice) == word[i] || tolower(choice) == word[i]){
hidden_word[i] = word[i];
is_match = true;
}
// If end of loop and character is invalid, lives left -=1
if(i == hidden_word.length() -1 && is_match != true){
--tries_left;
return 0;
}
}
is_match = false;
return 0;
}
// Checks if the word was found or not
void Hangman::decideFate(Hangman &f){
if(hidden_word == word){
cls();
cout << "Congrats, \"" << word << "\" it is.\n\n";
f.decision(f);
}
if(tries_left == 0 && hidden_word != word){
cin.ignore();
f.printHangman(f.getTries());
cout << "Too bad you didn't guess right. It was \""
<< word << "\"" << endl << endl;
f.decision(f);
}
}
void Hangman::decision(Hangman &c) {
cout << "+----------------------+" << endl;
cout << "| Alternatives |" << endl;
cout << "+----------------------+" << endl;
cout << "\"restart\" or a new game\n"
<< "\"help\" for help information\n"
<< "\"quit\" to exit\n\nChoice: ";
getline(cin, user_input);
transform(user_input.begin(), user_input.end(),
user_input.begin(), ::tolower);
if(user_input == "restart"){
c.startGame(c);
} else if(user_input == "help"){
info(c);
} else if(user_input == "quit"){
cls();
cout << "Thank you for playing..." << endl;
exit(EXIT_SUCCESS);
} else{
invalidInput2(c,user_input);
}
}
void Hangman::invalidInput1(Hangman &i1, char &i){
//cin.clear();
cerr << "' " << i << " ' is not a valid input."
<< " Press <Enter> to try again.";
getline(cin, user_input);
Hangman::printMenu(i1);
}
void Hangman::invalidInput2(Hangman &i2, string &i){
//cin.clear();
cerr << "\" " << i << " \" is not a valid input."
<< " Press <Enter> to try again.";
getline(cin, user_input);
cls();
Hangman::decision(i2);
}
// Reset game
void Hangman::reset(){
tries_left = 6;
hidden_word = "";
}
// Calls clear screen command
void Hangman::cls() const{
// passes cls or clear string as character pointer
system(arch.c_str());
}
main.cpp:
#include "Hangman.h"
int main() {
Hangman hangman;
hangman.printMenu(hangman);
}
Tried:
Running the program in a lower standard (11) from 14.
Online compiler from tutorialspoint.
Manually setting the word.
Observation:
I observed that if I manually set the word, that situation is resolved. How do I narrow in on this issue further?
Edit:
Added wordlist and removed a stray backslash which prevented compiling..
Try running dos2unix on your wordlist.yx file. If it was created on Windows, the newlines are probably \r\n, not just \n. And if that \r is interpreted literally, that will return to the beginning of the line prior to continuing to output to cout, thus overwriting your first character.
Reference to dos2unix can be found here.
To avoid using dos2unix, you could strip the \r characters from your wordlist array. One approach would be to loop through each word in the array and processing them like so:
currWord.erase( std::remove(currWord.begin(), currWord.end(), '\r'), currWord.end() );
I'm new to C++. I have been following an online course that teaches you how to make a Hangman game in C++. For the most part the code was working, every time I debugged it ran fine. I completed the entire code and double checked it, but I'm getting an error on one of the 'else' the errors I'm getting is "error C2181: illegal else without matching if.
Here's my code.
// Hangman game
// CN
// Header file
#include "stdafx.h"
// Input/Output
#include <iostream>
// Text
#include <string>
// Information storage
#include <vector>
// Figuring out the information storage
#include <algorithm>
// Converts lower cased letters to higher case letters
#include <cctype>
// Reads computers time and distributes a word from a list accordingly
#include <ctime>
// Library for system
#include <cstdlib>
using namespace std;
int main()
{
// Constant data type which is a fixed value, MaxWrong in Pascal Text and the max number of guesses.
const int MaxWrong = 6;
vector<string> words;
words.push_back("SANTA CLAUSE");
words.push_back("REINDEER");
words.push_back("PRESENT");
words.push_back("TREE");
words.push_back("MILK");
words.push_back("COOKIE");
// Parenthesis must always match
srand(static_cast<unsigned int>(time(0)));
random_shuffle(words.begin(), words.end());
const string theWord = words[0];
int wrong = 0;
string soFar(theWord.size(), '_');
string used = "";
cout << "\n******** Welcome to Chaye's Hangman ********\n\n";
cout << " __ \n";
cout << " | | \n";
cout << " | \n";
cout << " | \n";
cout << " | \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
// Loop
while ((wrong < MaxWrong) && (soFar != theWord))
{
cout << "\n You have " << (MaxWrong - wrong);
cout << " incorrect tries left.\n";
cout << "\n You've used these letters:\n" << used << endl;
char guess;
cout << "\n\n Enter your guess: ";
cin >> guess;
guess = toupper(guess);
while (used.find(guess) != string::npos)
{
cout << "\n You've already tried " << guess << endl;
cout << " Enter your guess: ";
cin >> guess;
guess = toupper(guess);
}
used += guess;
if (theWord.find(guess) != string::npos)
{
cout << " That's right " << guess << " is in the word,\n";
for (int i = 0; i < theWord.length(); ++i)
{
if (theWord[i] == guess)
{
soFar[i] = guess;
}
}
}
else
{
cout << " sorry. " << guess << " isn't in the word.\n";
++wrong;
}
// If one is wrong
if (wrong == 1)
{
cout << " __ \n";
cout << " | | \n";
cout << " | O \n";
cout << " | \n";
cout << " | \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
}
else
{
cout << endl;
}
// If one is wrong
if (wrong == 2)
{
cout << " ___ \n";
cout << " | | \n";
cout << " | O \n";
cout << " | # \n";
cout << " | \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
}
else
{
cout << endl;
}
// If one is wrong
if (wrong == 3)
{
cout << " ___ \n";
cout << " | | \n";
cout << " | O \n";
cout << " | /# \n";
cout << " | \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
}
else
{
cout << endl;
}
// If one is wrong
if (wrong == 4)
{
cout << " ___ \n";
cout << " | | \n";
cout << " | O \n";
cout << " | /#\ \n";
cout << " | \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
}
else
{
cout << endl;
}
// If one is wrong
if (wrong == 5)
{
cout << "\n You've been hung \n";
cout << " ___ \n";
cout << " | | \n";
cout << " | O \n";
cout << " | /#\ \n";
cout << " | / \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
}
else
{
cout << "\n I'm suprised you've got this far\n";
}
cout << "\n The word was " << theWord << endl;
}
// If one is wrong
if (wrong == MaxWrong)
{
cout << "\n You've been hung \n";
cout << " ___ \n";
cout << " | | \n";
cout << " | O \n";
cout << " | /#\ \n";
cout << " | / \ \n";
cout << " | \n";
cout << " ___|____ \n\n";
cout << " Do Your Best Human \n\n";
}
else
{
cout << "\n I'm suprised you've got this far\n";
}
cout << "\n The word was " << theWord << endl;
// Pause Console
system("pause");
// Kills the application once done
return 0;
}
There should be no semicolon in this line:
if (theWord.find(guess) != string::npos);
this semicolon terminates the whole if statement and the following {...} block is executed unconditionally. Following else is therefore no longer matched with the if statement.
And you are also missing closing ) bracket in your while statement:
while (used.find(guess) != string::npos
{
...
}
Change
** else **
to
else
Your compiler is interpreting that as an operator. If it still fails, edit your post w/ the error. Also worth noting, if you compile w/ the -g flag you get some debug output which can be beneficial.
Im trying to build a tic tac toe game, and for some reason seem to be getting hit by a bug when I try and put a value into any values, it seems to give the selected character(say its player 1, and thus an 'X'), into the values selected by the user(where he wants it to be) but also annoyingly into [1][2] and [2][0] of the array. The code is attached.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace System;
using namespace std;
string game_board[2][2];
bool exit_condition = false;
int x_coords;
int y_coords;
int current_player;
string cp_char;
int returnxwin();
int returnowin();
int main()
{
cout << "Welcome to Tic-Tac-Toe Console!\n" << endl;
//Start of game
while(exit_condition != true){
cout << "This is the game board: " << endl;
cout << " - | 1 | 2 | 3 | " << endl;
cout << " 1 | " << game_board[0][0] <<" | " <<game_board[1][0] << " | " << game_board[2][0] << " | " <<endl;
cout << " 2 | " << game_board[0][1] <<" | " <<game_board[1][1] << " | " << game_board[2][1] << " | "<<endl;
cout << " 3 | " << game_board[0][2] <<" | " <<game_board[1][2] << " | " << game_board[2][2] << " | \n"<<endl;
//TESTING PURPOSES BE SURE TO REMOVE!
current_player = 1;
//Says which player is first
cout << "Player " << current_player << " is first!" << endl;
//Determines which player is first, and if so, which character to give to them.
if(current_player == 1)
{
cp_char = "X";
} else if(current_player == 2)
{
cp_char = "Y";
}
bool valid_input = false;
while(valid_input != true){
cout << "Where would you like to place your " << cp_char << " ? (X co-ordinates(top row))\n" ;
cin >> x_coords;
cout << "Where would you like to place your " << cp_char << " ? (Y co-ordinates(side row))\n" ;
cin >> y_coords;
if((x_coords <= 3) && (y_coords <=3))
{
if(game_board[x_coords-1][y_coords-1] == "")
{
game_board[1][2] = "";
game_board[2][0] = "";
//Problem Here!
game_board[x_coords-1][y_coords-1] = cp_char;
break;
valid_input = true;
}
else
{
cout << "Invalid Input! Somebody has already taken the slot!" << endl;
}
}
else
{
cout << "Invalid input! Please enter a number from 1 to 3" << endl;
}
}
//End of Valid Input Loop
//make sure to remove break;
// break;
}
system("pause");
return 0;
}
I haven't finished the game yet, but was at a loss as to why this is happening :s
On another side note, Im also looking for a way to randomly decide whether player 1 or 2 goes first.
Edit: I tried doing [3][3], as suggested but it still gives me an error. Ideas?
game_board is defined as an array of 2x2 strings, should it be 3x3?
string game_board[3][3]
I guess you are going over the array so you get undefined results..
Regarding having a way to randomly choose which player will start just use the rand() function:
srand(time(NULL)); // to initialize the random sequence
current_player = rand()%2 + 1; //player will be either 1 or 2
string game_board[2][2];
This allocates a game board 2 entries wide by 2 entries tall. That's one smaller than a USTTTA / IOCTTT - sanctioned tournament game board. Try this:
std::string game_board[3][3];