This question already has answers here:
Output non-null terminated char array behaviours?
(3 answers)
Closed 3 months ago.
I am trying to make my own WORDLE game with C++. I have gotten to the point where I can check if a character is in the right spot but I do not know how to check if a letter is in the word but in a different place. This is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <cstdlib>
using namespace std;
string pickword();
string checkword(string ans, string word);
int main() {
string guess;
cout << "Hi welcome to WORDLE\n\n*Hit enter to start*";
cin.ignore();
string word = pickword();
cout << endl << word;
cout << "\nEnter a 5-letter word: ";
cin >> guess;
checkword(guess, word);
}
string pickword() {
srand((unsigned) time(NULL));
int random = 1 + (rand() % 1999);
string string;
ifstream ReadFile;
ReadFile.open("words.txt");
for (int i = 1; i <= random; i++) {
getline(ReadFile, string);
}
ReadFile.close();
return string;
}
string checkword(string ans, string word) {
char anslst[5];
char wrdlst[5];
for (int i = 0; i <= 4; i++) {
anslst[i] = ans[i];
wrdlst[i] = word[i];
}
//Green = \033[32m
//Red = \033[31m
//Yellow = \033[33m
for (int i = 0; i <= 4; i++) {
if (anslst[i] == wrdlst[i]) {
cout << "\033[32m" << anslst[i];
}
else if (anslst[i] != wrdlst[i]) {
cout << "\033[31m" << anslst[i];
}
}
return word;
}
the part relevent to the question is the bottom of checkword(). how can I see if the letters in the player's guess are in the the list containing the letters of the answer?
This main problem you're faced with isn't so much a question about C++, but instead an algorithmic question of "what to do with repeated letters?" For example, my understanding of the rules of Wordle are that a guess of "APPLE" when the answer was "PASTE", your first "P" should be yellow, but your second "P" should be grey. But if the answer had been "SPIPE", then "APPLE"'s second "P" should be yellow (because its first "P" is now green).
If we were to extend your C++ example with some of the programming choices you've already made, the central part of your checkword() might be written something like this:
EResult result[5];
for (int i = 0; i <= 4; i++) {
if (anslst[i] == wrdlst[i]) {
result[i] = GREEN;
}
else {
result[i] = GREY;
}
}
for (int i = 0; i <= 4; i++) {
if (result[i] != GREEN) {
bool searchingForYellow = true;
for (int j = 0; j <= 4 && searchingForYellow; j++) {
if (result[j] == GREY && anslst[i] == wrdlst[j]) {
result[j] = YELLOW;
searchingForYellow = false;
}
}
}
}
for (int i = 0; i <= 4; i++) {
if (result[i] == GREEN) {
cout << "\033[32m" << wrdlst[i];
}
else if (result[i] == YELLOW) {
cout << "\033[33m" << wrdlst[i];
}
else { // GREY
cout << "\033[31m" << wrdlst[i];
}
}
Notice that I've assumed you have an enumeration type named EResult with values GREEN or YELLOW or GREY (I haven't defined that type in my example code). You might need to study a bit about C++ enumerations if that is a new concept for you. Also consider using a "switch" statement instead of the condition at the end (but I'm not sure if you're familiar with "switch", so I wrote it this way for you instead). Also, consider using a "break" statement instead of the boolean variable (but again, I'm not sure how familiar you are with that programming element).
Related
It's my first question in stack overflow so if there is some mistakes sorry about that. I'm trying to fill a 2d char array and then access each letter. I complied my code, there is no error but when I try to run it doesn't work. Here it's my code.
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main() {
char ch[] = "Welcome text in a separate line.";
char strWords[5][7];
int counter = 0;
int a = 0;
for (int i = 0; i < sizeof(ch); i++) {
if (ch[i] == ' ') {
strWords[counter][a] = '\0';
counter++;
a = 0;
}
else
{
strWords[counter][a] += ch[i];
a++;
}
}
for (int i = 0; i <= 5; i++) {
for (int a = 0; a <= 7; a++) {
cout << strWords[i][a] << " ";
}
}
return 0;
}
A few things wrong with your code
int main() {
char ch[] = "Welcome text in a separate line.";
// char strWords[5][7]; <<<=== i would change to be larger that you need, just in case
char strWords[20][20];
int counter = 0;
int a = 0;
for (int i = 0; i < strlen(ch); i++) { // sizeof is wrong, you need strlen
if (ch[i] == ' ') {
strWords[counter][a] = '\0';
counter++;
a = 0;
}
else
{
//strWords[counter][a] += ch[i];
strWords[counter][a] = ch[i]; // you do not need to try to concatenate, you are already walking down the buffer with 'a'
a++;
}
}
for (int i = 0; i < counter; i++) { // use 'counter' as it has the number of lines
// since you 0 terminated the string you do not need to walk character by character
cout << strWords[i] << " ";
}
return 0;
}
You are also not detecting and terminating the last word (since there is no space after it). I will leave that to you. The code I show does not print the word 'line.'
You should really have tests to make sure you do not overflow the length or number of words.
Plus you should ideally use std::string and std::vector
Note - if, for experimentation, you do want to walk through char by char to output the strings you should look for the terminating '0' character and exit the inner loop
I'm pretty new to C++, and I'm trying to code a Wordle-like game, for 2 players using Visual Studio, to run in the windows cmd.
I want the user string input to be replaced with a '' or '*' character/symbol whilst it's being typed. I want to do this only using iostream, I have come across various solutions online, but none without importing any additional libraries (the solutions online usually use getch(), which needs an additional library)
My relevant (pretty bare) code is as follows:
#include <iostream>
using namespace std;
char a[5];
string str;
int main()
{
cout << "\nSet your Wordle first: ";
cin >> str;
for (int x = 0; x < 5; x++) {
a[x] = str[x];
}
return 0;
}
So I guess, as characters for 'str' are being typed, a '*' would be outputted on the windows console instead.
Any help or hints would be greatly appreciated, Thanks!
Note: Scroll down for updated code.
There is no way of achieving this without using external libraries. However, the closest you can achieve is this:
#include <iostream>
#include <Windows.h>
#include <conio.h>
// Positions the cursor 'home'. Visually clears the screen. Using this to avoid flickering
void cls()
{
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), COORD());
}
void input(std::string& str) // Asks the user for the word
{
int char_count = 0;
while (true)
{
cls();
std::cout << "Set your Wordle first: ";
for (int i = 0; i < char_count; i++)
{
std::cout << "*";
}
if (_kbhit())
{
char c = _getch();
if (c == '\r') // The character '\r' means enter
{
return;
}
char_count++;
str.push_back(c);
}
}
}
int main()
{
char a[5]{};
std::string str;
input(str);
for (int x = 0; x < 5; x++) // Constrain to 5 characters
{
if (x < str.size()) a[x] = str[x];
else break;
}
std::cout << std::endl; // Debug start
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
std::cout << a[i];
} // Debug end
}
This code works as you wanted. You may see the mouse flickering but as I said, there is no proper way to do this in C++. Also, this is not the complete wordle game, and the code between // Debug start and // Debug end is just for testing purposes.
Edit: I played around with it and fixed the blinking issue:
#include <iostream>
#include <Windows.h>
#include <conio.h>
int prev_char_count = 0;
// Positions the cursor 'home'. Visually clears the screen. Using this to avoid flickering
void cls()
{
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), COORD());
}
void input(std::string& str) // Asks the user for the word
{
int char_count = 0;
cls();
std::cout << "Set your Wordle first: ";
for (int i = 0; i < char_count; i++)
{
std::cout << "*";
}
while (true)
{
if (_kbhit())
{
cls();
std::cout << "Set your Wordle first: ";
char c = _getch();
if (c == '\r') // The character '\r' means enter
{
return;
}
char_count++;
str.push_back(c);
for (int i = 0; i < char_count; i++)
{
std::cout << "*";
}
}
}
}
int main()
{
char a[5]{};
std::string str;
input(str);
for (int x = 0; x < 5; x++) // Constrain to 5 characters
{
if (x < str.size()) a[x] = str[x];
else break;
}
std::cout << std::endl; // Debug start
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
std::cout << a[i];
} // Debug end
}
I want to generate a random string with letters a,b,c,d then let the user guess it.
My output should be which positions the user guessed correctly and how many letters the user guessed correctly but put them in the wrong position.
Current attempt:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
int main()
{
char lettres[4] =
{
'a',
'b',
'c',
'd'
};
char rString[4];
int i = 0;
srand(time(0));
while (i < 4)
{
int temp = rand() % 4;
rString[i] = lettres[temp];
i++;
}
int u = 0;
char t[4];
while (u < 10)
{
cout << "Enter your guess:\n ";
cin >> t;
for (int z = 0; z < 4; z++)
{
cout << rString[z] << ", "; //printing random string
}
cout << "\n";
int k;
int compteur = 0;
int t2[4];
int compteur2 = 0;
for (k = 0; k < 4; k++)
{
if (rString[k] == t[k]) //rString is my random string
{
t2[compteur2] = k;
compteur2++;
}
}
for (int y = 0; y < 4; y++)
for (int j = 0; j < 4; j++)
{
if (t[y] == rString[j] && y != j) //checking correct letters at wrong positions
{
compteur++;
t[y] = 'z'; //I put this line to avoid counting a letter twice
}
}
if (compteur2 == 4)
{
cout << "bravo\n";
u = 10;
} else
{
cout << "Positions with correct letters:\n ";
if (compteur2 == 0)
{
cout << "None";
cout << " ";
} else
for (int z = 0; z < compteur2; z++)
c out << t2[z] << ", ";
cout << " \n";
cout << "You have a total of " << compteur << " correct letters in wrong positions\n";
}
u++;
}
return 1;
}
Sample output:
Enter your guess:
abcd
b, a, b, a, //note this is my random string I made it print
Positions with correct letters:
None
You have a total of 1 correct letters in wrong positions
for example here I have 2 correct letters in the wrong position and I am getting 1 as an output
To clarify more about why I put t[y]='z'; if for example the random string was "accd" and my input was "cxyz" I would get that I have 2 correct letters at wrong positions, so I did that in attempt to fix it.
Any help on how to do this?
You should implement like this
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
int main() {
srand(time(0));
char lettres[4] = {'a','b','c','d'};
char rString[4];
int i = 0;
//making random string
while (i < 4) {
int temp = rand() % 4;
rString[i] = lettres[temp];
i++;
}
int u = 0;
char t[4];
while (u < 10) {
cout << "Enter your guess:\n ";
cin >> t;
//printing random string
for (int z = 0; z < 4; z++) {
cout << rString[z] << ", ";
}
cout << "\n";
int correctPositions = 0;
cout << "Correct Position Are:\n";
for (int z = 0; z < 4; z++) {
if (rString[z] == t[z]) {
cout << (z + 1) << ", ";
correctPositions++;
}
}
if (correctPositions == 4) {
cout << "\nBingo!" << "\nThat's Right!";
return 0;
}
if (correctPositions == 0) {
cout << "None";
}
cout << "\n";
//finding no of correct letters in wrong position:
int correctLetters = 0;
for (int i = 0; i < 4; i++) {
char c = lettres[i];
int randomCount = 0;
int guessCount = 0;
int letterInCorrectPos = 0;
for (int z = 0; z < 4; z++) {
if (rString[z] == c) {
randomCount++;
}
if (t[z] == c) {
guessCount++;
}
if (rString[z] == t[z] && t[z] == c)
letterInCorrectPos++;
}
correctLetters += min(guessCount, randomCount) - letterInCorrectPos;
}
cout << "No. of correct letters but in wrong position :" << correctLetters;
cout << "\n\n";
u++;
}
return 0;
}
Explaining Logic
1. Finding No. Of Correct Positions:
This is done by iterating with z = 0 -> z=4 over the rString and t if rString[z] is t[z] (the char at z are matching) then we just print the position!
2. Finding No. Of Correct Letters In Wrong Position
This part was little tricky to implement but here is the method I followed.
We have lettres[] array which is containing all the letters, right? We will now individual loop over each letter in the array and count the no. of occurrence in the rString and t, and store the respective counts in a randomCount and guessCount respectively.
Ex. let rString = "bdcc" and t = "abcd" so we have the following data:
'a': randomCount:0 guessCount:1 letterInCorrectPos: 0
'b': randomCount:1 guessCount:1 letterInCorrectPos: 0
'c': randomCount:2 guessCount:1 letterInCorrectPos: 1
'd': randomCount:1 guessCount:1 letterInCorrectPos: 0
This is the first part in the above loop you can see we have another variable letterInCorrectPos, this variable stores the no. of instances in the string where, the letter is at the same position in both the strings.
Figuring these three values we can calculate the no. of correct letter:
correctLetters = min(guessCount, randomCount)
the smaller value of guessCount or randomCount is chosen because we don't want repeated counting. (We can't have more correct letters than there are instances of that letter in another class).
Now by simple logic: correct letters in wrong place is (correct letters) - (correct letters in the correct place ).Hence,
correctLetters = min(guessCount, randomCount) - letterInCorrectPos;
Since we are iterating in a loop and we want to add correctLetters of each letter, we use this statement at the end of loop:
correctLetters += min(guessCount, randomCount) - letterInCorrectPos;
Hope this will explain the working.
I am trying to implement the algorithm RLE with simple input like:
ddddddddddhhhhhhhhhhhhhhhttttttttttttt
code:
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
int main() {
vector<char> read;
ifstream file;
file.open("file.txt");
if (!file) {
cout << "Unable to open";
}
char v;
while(file>>v) {
read.push_back(v);
}
char x;
int count=0;
for(int i=0; i<read.size(); i++) {
x = read[i];
if(x != read[++i]) {
cout << x << "1";
}
while(x == read[++i]) {
count++;
}
cout << x << count;
count = 0;
}
return 0;
}
The output I am getting is:
d9d1h12h1t10t1
Please help me with the code.
Update: I have updated the question as I have realized few things.
Plus: This code produced no output, is there anything wrong which I am doing wrong?
char o;
char n;
int count=0;
for(int i=0; i<read.size(); i++) {
o = read[i];
n = read[++i];
while(o == n) {
count++;
}
cout << o << count;
if(o != n) {
cout << o << "1";
} count = 0;
}
return 0;
This loop:
char x;
int count=0;
for(int i=0; i<read.size(); i++) {
int j=i;
x = read[i];
if(x != read[++j]) {
cout << x << "1";
}
while(x == read[++j]) {
count++;
}
cout << x << count;
}
Has several errors. First, you should use two indices, i and j. i is going through each element of read, but then j is iterating through a subsequence too. What you want is to go through each element only once, and in each case either print or increase the count. However having a for loop and moving the index inside too is not a very good practice, is rather error-prone. Also you have to cout statements that are do not run at the right time (you don't wan to print something on every iteration, only when the character changes). You could do it with a while loop, or using a simpler structure like:
// If there are no characters finish
if (read.empty()) {
return 0;
}
// Get the first character
char lastChar = read[0];
int count = 1; // We have counted one character for now
// Go through each character (note start from 1 instead of 0)
for(int i = 1; i < read.size(); i++) {
// Get the next char
char newChar = read[i];
// If it is different, print the current count and reset the counter
if (lastChar != newChar) {
cout << lastChar << count;
count = 1;
lastChar = newChar;
} else { // Else increase the counter
count++;
}
}
// Print the last one
cout << lastChar << count;
return 0;
Problem is that I want 'o' , not to repeat... I tried to find but I failed!
Also explain me that how this happens. I am a new learning programmer!
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
using namespace std;
int main()
{
//all in-game variables here
string o = "o";
int oH = 0;
int oW = 0;
//variables ending point...
bool run = true;
bool frameShow = true;
char input;
int width = 53;
int height = 22;
string px[width][height];
while (run)
{
for (int xEmp=0; xEmp<height; xEmp++){
for (int yEmp=0; yEmp<width; yEmp++)
{
px[xEmp][yEmp]= " ";
}
if (frameShow)
{
clrscr(); // Must be at start
px[oH][oW] = o;
for (int x=0; x<height; x++)
{
for (int y=0; y<width; y++)
{
cout << px[x][y];
}
cout << "\n";
frameShow = false; // Must be at end
}
}
if (kbhit())
{
input = getch();
// Most Used ones are:
// char 119 for "w"
// char 97 for "a"
// char 115 for "s"
// char 100 for "d"
// char 32 for "space"
// char 27 for ESC
if (input == 119)
{
oH--;
frameShow = true;
}
else if (input == 115)
{
oH++;
frameShow = true;
}
else if (input == 97)
{
oW--;
frameShow = true;
}
else if (input == 100)
{
oW++;
frameShow = true;
}
else if (input == 27)
{
// Game exits...
// To terminate, use:
run = false;
}
if(oH > height)
{
oH = height;
}
else if(oH < 0)
{
oH = 0;
}
if(oW > width - 1)
{
oW = width - 1;
}
else if(oW < 0)
{
oW = 0;
}
}
}
}
// Output for confiming program termination
clrscr();
cout << "\n - Terminated! - \n";
return 0;
}
As a start, width and height use is being changed. px[width][height];, px[xEmp][yEmp], xEmp<height, yEmp<width. One time you use it as px[width][height];, then px[height][width];. keep your code coherent!
Also if(oH > height) { oH = height; } is wrong. subtract one from height.
This also probably doesn't do what you want:
for (int x=0; x<height; x++)
for (int y=0; y<width; y++)
{
cout << px[x][y];
}
cout << "\n";
Use brackets correctly, IF you don't know how to use them, put them ALWAYS!
Again, I think you're not using brackets correctly:
for (int xEmp=0; xEmp<height; xEmp++){
for (int yEmp=0; yEmp<width; yEmp++)
{
px[xEmp][yEmp]= " ";
}
... // do other things
}
I think you want to close it right away to set everything back to space and them do other works. As it is now, it will set one line back to spaces, print everything and run your code, and only after empty next line.
for (int xEmp=0; xEmp<height; xEmp++){
for (int yEmp=0; yEmp<width; yEmp++)
{
px[xEmp][yEmp]= " ";
}
}
... // do other things
Ps: clrscr() is a non-standard function, only works in Windows, I think, for Linux use system('clr');
Ps2: Why are you using std::string instead of char if you only store chars?