I have to implement a deck of cards with a number and a letter. This is what I have done so far:
string deck [6][6] =
{
{1A, 1B, 1C, 1D},
{2A, 2B, 2C, 2D},
{3A, 3B, 3C, 3D},
{4A, 4B, 4C, 4D},
{ , , , };
};
int main ()
{
cout << deck[0][0] << endl;
}
I get an error:
invalid suffix 'A' on integer constant
You are getting this error because you need to wrap your strings in double quotations. If you want to use a static initialization/declaration, it should look something like this:
std::string deck[4][4] = {
{ "1A", "1B", "1C", "1D"},
{ "2A", "2B", "2C", "2D"},
{ "3A", "3B", "3C", "3D"},
{ "4A", "4B", "4C", "4D"}
};
You can display the entire contents of the deck by using two nested for loops:
for (int r=0; r < 4; ++r) {
for (int c=0; c < 4; ++c) {
if (c > 0) {
cout << " ";
}
cout << deck[r][c];
}
cout << "\n";
}
Related
I define a struct.
struct test
{
char name[10];
int num;
}temp[20];
I want to only output the data with the same name and three consecutive num or more in temp[20].
for example,the data of the temp[20] are as follows:
temp[0] = { "a",0 };
temp[1] = { "b",1 };
temp[2] = { "a",2 };
temp[3] = { "b",2 };
temp[4] = { "a",3 };
temp[5] = { "b",3 };
temp[6] = { "a",4 };
temp[7] = { "c",1 };
temp[8] = { "c",2 };
temp[9] = { "a",5 };
........
the output is
temp[2] = { "a",2 };
temp[4] = { "a",3 };
temp[6] = { "a",4 };
temp[9] = { "a",5 };
temp[1] = { "b",1 };
temp[3] = { "b",2 };
temp[5] = { "b",3 };
I can only use a triple for loop to output data with the same name and three consecutive num,but four consecutive num can`t output.My code are as follows:
for (int i = 0; i < 20; i++)
{
for (int j = i + 1;j < 20;j++) {
if ((strcmp(temp[i].name, temp[j].name) == 0) && (temp[j].num - temp[i].num == 1))
{
for (int k = 0; k < 20; k++)
{
if ((strcmp(temp[k].name, temp[j].name) == 0) && (temp[k].num - temp[j].num == 1)) {
printf("%s,%d", temp[i].name, temp[i].num);
printf("%s,%d", temp[j].name, temp[j].num);
printf("%s,%d", temp[k].name, temp[k].num);
}
}
}
}
}
what could I do?
Since you haven't specified anything particular about the data's ordering, I assume that it's fine to sort it. Sorting by the name, then number allows you to find consecutive runs of values in linear time. And a typically sorting algorithm can be achieved in N.log(N) time.
Let's assume that N represents the number of elements in your array. You can sort it simply like this:
std::sort(temp, temp + N,
[](const test& a, const test& b) {
int result = strcmp(a.name, b.name);
return result < 0 || result == 0 && a.num < b.num;
});
Using a couple of simple helpers to display the data...
void Show(const test& t)
{
std::cout << t.name << "," << t.num << "\n";
}
void Show(const test* t, int N)
{
for (int i = 0; i < N; ++i)
Show(t[i]);
}
Now, after sorting, a call to Show(temp, N); gives this:
a,0
a,2
a,3
a,4
a,5
b,1
b,2
b,3
c,1
c,2
Now it's quite trivial to walk through the array and find runs of some minimum number. You requested 3, but we can choose any number.
const int minRunLength = 3;
std::cout << "Consecutive runs with matching name (minimum " << minRunLength << "):\n";
for (int i = 0, runLength = 0; i < N; ++i)
{
// Update run length
if (i > 0 &&
strcmp(temp[i-1].name, temp[i].name) == 0 &&
temp[i-1].num + 1 == temp[i].num)
{
++runLength;
}
else
{
runLength = 1;
}
// Show items meeting run length criteria
if (runLength == minRunLength)
{
for (int p = runLength-1; p >= 0; --p)
Show(temp[i - p]);
}
else if (runLength > minRunLength)
{
Show(temp[i]);
}
}
Running this with a minimum length of 3 gives:
Consecutive runs with matching name (minimum 3):
a,2
a,3
a,4
a,5
b,1
b,2
b,3
A minimum of 4 is:
Consecutive runs with matching name (minimum 4):
a,2
a,3
a,4
a,5
Here is a Live Demo that you can play with.
For a homework assignment i need to create a program that lets you play the Irish card game 25. I can kind of have my code give out a hand to one person but if i try to have multiple people, the code gives out an identical hand to the other people. How do i give different, unique hands to other people?
I've tried using a loop, thinking that the function would simply reset the array but it hasn't
/* Deals a random hand of cards */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define BOOL int
#define NUM_SUITS 4
#define NUM_RANKS 13
int DealCards(int i);
int main()
{
int i;
int NumOfPlayers;
printf("Please Enter the Number Of Players: ");
scanf("%d", &NumOfPlayers);
for (i = 1; i <= NumOfPlayers; i++)
{
DealCards(i);
}
}
int DealCards(int i)
{
BOOL in_hand[NUM_SUITS][NUM_RANKS] = { FALSE };
int num_cards = 5, rank, suit;
const char rank_code[] = { '2', '3', '4', '5', '6', '7', '8',
'9', '10', '11', '12', '13', 'A' };
const char suit_code[] = { 'C', 'D', 'H', 'S' };
srand(time(NULL));
printf("\n\nPlayer %d's hand :\n", i);
while (num_cards > 0)
{
suit = rand() % NUM_SUITS;
rank = rand() % NUM_RANKS;
if (!in_hand[suit][rank])
{
in_hand[suit][rank] = TRUE;
num_cards--;
printf(" %cof%c ", rank_code[rank], suit_code[suit]);
}
printf("\n");
}
return 0;
}
The problem is that you call srand() function before giving card to every player. You use time(NULL) as an argument, therefore seed changes only every second, and players get cards with the same seed.
You need to set seed only once for each program launch.
Your current method is drawing cards with replacement, then checking if that has been drawn. It's rather easy, and a better model of the game, to shuffle the deck.
What you should do is define a type that encodes a particular card, populate a collection of that type, with each card value in use, shuffle the deck, then assign cards from the shuffled deck.
As a sketch
#include <vector>
#include <string>
#include <random>
#include <algorithm>
#include <iostream>
const std::vector<std::string> rank_code = { "2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace" };
const std::vector<std::string> suit_code = { "Clubs","Diamonds","Hearts","Spades" };
const int num_cards = 5;
struct Card
{
Card(char s, char r) : suit(s), rank(r) {}
char suit;
char rank;
};
std::ostream & operator<< (std::ostream & os, const Card & c)
{
return os << rank_code[c.rank] << " of " << suit_code[c.suit];
}
using Deck = std::vector<Card>;
Deck freshDeck()
{
Deck result;
for (std::size_t s = 0; s < suit_code.size(); ++s)
for (std::size_t r = 0; r < rank_code.size(); ++r)
result.emplace_back(s, r);
return result;
}
void dealCards(int player, Deck & deck)
{
std::string joiner;
std::cout << std::endl << "Player " << player << "'s hand" << std::endl;
for (int c = 0; c < num_cards; ++c)
{
std::cout << joiner << deck.back();
deck.pop_back();
joiner = ", ";
}
std::cout << std::endl;
}
int main ()
{
std::mt19937 gen{ std::random_device{}() };
Deck deck = freshDeck();
std::shuffle(deck.begin(), deck.end(), gen);
std::cout << "Enter number of players" << std::endl;
int num_players;
std::cin >> num_players;
for (int p = 1; p <= num_players; ++p)
{
dealCards(p, deck);
}
}
Just initialize your srand(time(NULL)) before giving cards
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define BOOL int
#define NUM_SUITS 4
#define NUM_RANKS 13
int DealCards(int i);
int main()
{
int i;
int NumOfPlayers;
printf("Please Enter the Number Of Players: ");
scanf("%d",&NumOfPlayers);
//here for example
srand(time(NULL));
for (i = 1; i <= NumOfPlayers; i++)
{
DealCards(i);
}
}
int DealCards(int i) {
BOOL in_hand[NUM_SUITS][NUM_RANKS] = { FALSE };
int num_cards = 5, rank, suit;
const char rank_code[] = { '2','3','4','5','6','7','8',
'9','10','11','12','13','A' };
const char suit_code[] = { 'C','D','H','S' };
printf("\n\nPlayer %d's hand :\n",i);
while (num_cards > 0) {
suit = rand() % NUM_SUITS;
rank = rand() % NUM_RANKS;
if (!in_hand[suit][rank])
{
in_hand[suit][rank] = TRUE;
num_cards--;
printf(" %cof%c\n", rank_code[rank], suit_code[suit]);
}
}
return 0;
}
The problem is that the srand is initialized with the same value each time it is run.
So the same random values are generated in the same order. This is why all the hands are the same.
srand and rand are from the <cstdlib> header.
In C++11 and higher it is better to use functions from <random> header.
Also C++ gives many possibilities to use object orientated programming and has an extensive library of data structures and algorithms. I would suggest to use std::vector or std::array instead of plain arrays. And also use std::shuffle to get a random order of cards.
#include <vector>
#include <string>
#include <random>
#include <algorithm>
#include <iostream>
#include <exception>
//////////////////////////////////////////////////////////////////////////////////////////
class Rank
{
std::string value;
Rank(std::string value) : value(value) {}
public:
static const std::vector< Rank >& get_all()
{
static std::vector< Rank > suits = { { "2" }, { "3" }, { "4" }, { "5" }, { "6" },
{ "7" }, { "8" }, { "9" }, { "10" }, { "J" },
{ "Q" }, { "K" }, { "A" } };
return suits;
}
const std::string& to_string() const { return value; }
};
//////////////////////////////////////////////////////////////////////////////////////////
class Suit
{
std::string value;
Suit(std::string value) : value(value) {}
public:
static const std::vector< Suit >& get_all()
{
static std::vector< Suit > ranks = {
{ "Clubs" }, { "Diamonds" }, { "Hearts" }, { "Spades" }
};
return ranks;
}
const std::string& to_string() const { return value; }
};
//////////////////////////////////////////////////////////////////////////////////////////
class Card
{
Suit suit;
Rank rank;
public:
Card(const Suit& suit, const Rank& rank) : suit(suit), rank(rank) {}
std::string to_string() const { return rank.to_string() + " of " + suit.to_string(); }
};
//////////////////////////////////////////////////////////////////////////////////////////
class Deck
{
std::vector< Card > cards;
public:
Deck()
{
const auto& ranks = Rank::get_all();
const auto& suits = Suit::get_all();
cards.reserve(ranks.size() * suits.size());
for (const Suit& s : suits)
for (const Rank& r : ranks)
cards.emplace_back(s, r);
}
void shuffle()
{
static std::random_device rd;
static std::mt19937 g(rd());
std::shuffle(cards.begin(), cards.end(), g);
}
std::size_t cards_count() const { return cards.size(); }
Card get_top_card()
{
if (cards_count() == 0)
throw std::logic_error("No more cards!");
const auto card = cards.back();
cards.pop_back();
return card;
}
};
//////////////////////////////////////////////////////////////////////////////////////////
int get_player_count()
{
std::cout << "Please enter the number of players:" << std::endl;
int player_count;
std::cin >> player_count;
return player_count;
}
//////////////////////////////////////////////////////////////////////////////////////////
void deal_cards(int player_count, int cards_to_deal, Deck& deck)
{
for (auto player_num = 1; player_num <= player_count; player_num++)
{
std::cout << "\n\nPlayer " << player_num << "'s hand :\n";
for (auto card_count = 0; card_count < cards_to_deal; card_count++)
{
if (deck.cards_count() == 0)
{
std::cout << "\n\nNo more cards to deal!" << std::endl;
return;
}
std::cout << deck.get_top_card().to_string() << ", ";
}
}
std::cout << std::endl;
}
//////////////////////////////////////////////////////////////////////////////////////////
int main()
{
Deck deck;
deck.shuffle();
const auto player_count = get_player_count();
const auto cards_to_deal = 5;
deal_cards(player_count, cards_to_deal, deck);
}
//////////////////////////////////////////////////////////////////////////////////////////
I've got a JSON with the following structure
[{
"primul": "Thor",
"alDoilea": "Odin",
"alTreilea": "Loki"
},
{
"s": 1,
"d": 7,
"hp": 39
},
{
"1": "sabie",
"2": "scut",
"3": "coif"
}
]
Basically it's an array with x objects inside.
I've tried using QVariant to transform the data into a list and then map the elements of the list but it keeps throwing me cannot convert const char to int when using QVariantMap
Where am I going wrong?
Here is my code
QFile file2("../JsonExemplu/exampleArray.json");
if (!file2.exists()) {
qDebug()<<"Fisierul nu a fost gasit ";
exit(1);
}
if(!file2.open(QIODevice::ReadOnly)){
qDebug()<<"Nu s-a putut deschide fisierul JSON ";
exit(1);
}
QTextStream file_text(&file2);
QString json_string;
json_string = file_text.readAll();
file2.close();
QByteArray json_bytes = json_string.toLocal8Bit();
auto json_doc=QJsonDocument::fromJson(json_bytes);
if(!json_doc.isArray()){
qDebug() << "Formatul nu e de tip arrray.";
exit(1);
}
QJsonArray json_array = json_doc.array();
if(json_array.isEmpty()){
qDebug() << "JSON gol";
exit(1);
}
QVariantList root_map = json_array.toVariantList();
QVariantMap stat_map = root_map["nume"].toMap();
QVariantMap stat_map2 = root_map["statistici"].toMap();
QVariantMap stat_map3 = root_map["inventar"].toMap();
QStringList key_list = stat_map.keys();
for(int i=0; i< json_array.count(); ++i){
QString key=key_list.at(i);
QString stat_val = stat_map[key.toLocal8Bit()].toString();
qDebug() << key << ": " << stat_val;
}
}
The problem is that your convert QJsonArray to a list of variants. However you refer to that list as if it's a map - this will, of course, not compile. To fix the problem you need to use the appropriate QList API, i.e:
QVariantList root_map = json_array.toVariantList(); // This is a list, not a map!
// There are three items in the list.
// The code below can be put into a loop.
QVariantMap stat_map = root_map.at(0).toMap();
QVariantMap stat_map2 = root_map.at(1).toMap();
QVariantMap stat_map3 = root_map.at(2).toMap();
QStringList key_list = stat_map.keys();
for (int i = 0; i< key_list.count(); ++i)
{
QString key = key_list.at(i);
QString stat_val = stat_map[key.toLocal8Bit()].toString();
}
I am learning more about smart pointers in C++14.
Consider the following MWC:
#include <iostream>
#include <string>
#include <memory>
class House {
public:
House &operator=(const House &house) = default;
House(const House &house) = default;
House(): id_habitants_(nullptr), num_habitants_() {}
explicit House(size_t num_habitants) {
if (num_habitants > 0) {
num_habitants_ = num_habitants;
id_habitants_ = new int[num_habitants_];
if (id_habitants_ != nullptr) {
for (size_t id = 0; id < num_habitants_; ++id) {
id_habitants_[id] = 1;
}
}
}
}
void Print() {
if (id_habitants_ != nullptr) {
for (size_t id = 0; id < num_habitants_; ++id) {
std::cout << id_habitants_[id] << ' ';
}
std::cout << std::endl;
} else {
std::cout << "<empty>" << std::endl;
}
}
~House() {
if (id_habitants_ != nullptr) {
delete [] id_habitants_;
}
num_habitants_ = 0;
}
private:
int *id_habitants_;
size_t num_habitants_;
};
int main() {
std::cout << "Testing unique_ptr.\n" << std::endl;
std::cout << "Using a dumb House class..." << std::endl;
std::cout << "Creating House h1 with 3 habitants..." << std::endl;
House h1(3);
std::cout << "IDs of h1's 3 habitants:" << std::endl;
h1.Print();
std::cout << "Creating House h2 with 0 habitants..." << std::endl;
House h2;
std::cout << "IDs of h2's 0 habitants:" << std::endl;
h2.Print();
std::cout << "Default-assigning h1 to h2..." << std::endl;
h2 = h1;
std::cout << "IDs of h2's new 3 habitants:" << std::endl;
h2.Print();
std::cout << "Destroying h1..." << std::endl;
h1.~House();
std::cout << "IDs of h2's new 3 habitants:" << std::endl;
h2.Print();
}
Without modifying the default copy constructor and the default assignment operator for the class House, how can I ensure correct pointer behavior during assignment via smart pointers?
On a first try it seems like using std::unique_ptr would be the way to go. I could create a new class:
class SmartHouse {
public:
SmartHouse &operator=(const SmartHouse &shouse) = default;
SmartHouse(const SmartHouse &shouse) = default;
SmartHouse(): id_habitants_(nullptr), num_habitants_() {}
explicit SmartHouse(size_t num_habitants) {
if (num_habitants > 0) {
num_habitants_ = num_habitants;
id_habitants_ = std::unique_ptr<int[]>(new int[num_habitants_]);
if (id_habitants_) {
for (size_t id = 0; id < num_habitants_; ++id) {
id_habitants_[id] = 1;
}
}
}
}
void Print() {
if (id_habitants_) {
for (size_t id = 0; id < num_habitants_; ++id) {
std::cout << id_habitants_[id] << ' ';
}
std::cout << std::endl;
} else {
std::cout << "<empty>" << std::endl;
}
}
~SmartHouse() {
num_habitants_ = 0;
}
private:
std::unique_ptr<int[]> id_habitants_;
size_t num_habitants_;
};
According to this, I can't really copy one unique pointer to another. Makes sense, right? It sort of defeats the purpose of it being unique. I.e. this would not compile:
SmartHouse sh1(3);
SmartHouse sh2;
sh2 = sh1;
But I could specify a move assignment operator and have the unique_ptr<int[]> member be moved upon assignment thus transferring ownership of the pointed data to the left object upon assignment:
class SmartHouse {
SmartHouse &operator=(SmartHouse &&SmartHouse) = default;
}
...
SmartHouse sh1(3);
SmartHouse sh2;
sh2 = std::move(sh1);
sh1.~SmartHouse();
sh2.Print();
Core question: Does this make sense at all? Are there better ways to enhance assignment of pointer member variables?
Full MWE.
I have a two dimensional float array in QML. How do I get its values in C++.
I have created a class in c++ and have done the part of qmlRegisterType. The class is now accessible in QML.
Please demonstrate with a small example.
Here's what I have tried:
Header:
#include <QQuickItem>
#include <iostream>
class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QList <QVariantList> names READ names WRITE setnames NOTIFY namesChanged)
QList <QVariantList> m_names;
public:
Controller()
{
}
~Controller() {
}
QList <QVariantList> names() const
{
return m_names;
}
public slots:
void setnames(QList <QVariantList> arg)
{
QVariantList p;
if (arg.size () > 0)
{
p = arg.first ();
std::cout << "\narg: \n" << p[0].toInt ();
}
else
std::cout << "\nqqqq " << arg.size () << "\n";
}
signals:
void namesChanged(QList <QVariantList> arg);
};
qml
import QtQuick 2.0
import FromCpp 1.0
Rectangle
{
property variant arras: [[1,2,3], [4,5,6]]
Controller
{
id: ppp
}
MouseArea
{
anchors.fill: parent
onClicked:
{
ppp.setnames(arras)
console.log(arras.length)
}
}
}
The exact output from QtCreator:
Starting /home/***/documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk...
QML debugging is enabled. Only use this in a safe environment.
2
qqqq 0
QThreadStorage: Thread 0x181e270 exited after QThreadStorage 2 destroyed
/home/***/documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk exited with code 0
///
Here, as you can see the size of the 2D array from QML is printed correctly as 2 and the size is printed 0 from c++.
Why is that happening? Please explain.
According to user1095108's answer, in order to access the internal elements of the QML's 2 Dim array passed to C++, we need to convert each row to a list as follows:
QML part:
import QtQuick 2.0
import FromCpp 1.0
Rectangle
{
property variant twoDimArray: [[1,2,3], [4,5,6]]
Controller
{
id: controllerA
}
MouseArea
{
anchors.fill: parent
onClicked:
{
controllerA.setname (twoDimArray)
}
}
}
C++ part:
void setname (QVariantList arg)
{
if (arg.size())
{
QList <QVariant> p = arg[0].toList();
std::cout << "\nRow0 0:" << p[0].toInt ();
std::cout << "\nRow0 1:" << p[1].toInt ();
std::cout << "\nRow0 2:" << p[2].toInt ();
std::cout << "\n";
QList <QVariant> p1 = arg[1].toList();
std::cout << "\nRow1 0:" << p1[0].toInt ();
std::cout << "\nRow1 1:" << p1[1].toInt ();
std::cout << "\nRow1 2:" << p1[2].toInt ();
}
}
Output:
Starting /home/.../documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk...
QML debugging is enabled. Only use this in a safe environment.
Row0 0:1
Row0 1:2
Row0 2:3
Row1 0:4
Row1 1:5
Row1 2:6/home/.../documents/test/build-junk-Desktop_Qt_5_1_0_GCC_64bit-Debug/junk exited with code 0
It is actually very simple. Javascript arrays map to QVariantLists, Javascript objects to QVariantMaps. Therefore, you are dealing with nested QVariantLists. Try this:
void setnames(QVariantList const& arg)
{
if (arg.size())
{
auto const p(arg.front().toList());
std::cout << "\narg: \n" << p.front().toInt();
}
else
std::cout << "\nqqqq " << arg.size () << "\n";
}
This is my method :
#include <QQuickItem>
#include <QDebug>
#include <QVariantList>
class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant names READ names WRITE setnames NOTIFY namesChanged)
QVariant m_names;
public:
Controller()
{
}
~Controller() {
}
QVariant names() const
{
return m_names;
}
public slots:
void setnames(QVariant arg)
{
QVariantList dim1 = arg.toList();
qDebug() << "outer dimension size" << dim1.size();
for(int i=0;i<dim1.size();++i)
{
QVariantList &dim2 = dim1.at(i).toList();
qDebug() << "inner dimension size at" << dim2.size();
}
}
signals:
void namesChanged();
};
Try this:
Somewhere in QML file:
property variant floats: [1.1, 2.2, 3.3, 4.4, 5.5, 6.6]
Includes:
#include <QtQuick/QQuickView>
#include <QQmlContext>
#include <QQmlProperty>
#include <QQuickItem>
In C++, in constructor for example:
QQuickView *view = new QQuickView();
QWidget *container = QWidget::createWindowContainer(view, ui->widget);//I show view in my widget
container->setMinimumSize(ui->widget->size());
container->setMaximumSize(ui->widget->size());
view->setSource(QUrl::fromLocalFile("pathToQMLFile"));
//starts here
QQmlProperty property(view->rootObject(), "floats");//get rootObject and set name of property
QVariantList lst = property.read().toList();//use raed method to get QVariant and convert it to list
for (int i = 0; i < lst.length(); ++i)
{
qDebug() << lst.at(i).toFloat();//show list
}
Output:
1.1
2.2
3.3
4.4
5.5
6.6
I hope my code shows main idea and you can use it in your class, because the most important job(how to get numbers) was done.
It looks like you can use QVariantList (or QList<QVariant>):
#include <QtQuick>
class Controller : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariantList names READ names WRITE setnames NOTIFY namesChanged)
QVariantList m_names;
public:
Controller()
{
}
~Controller() {
}
QVariantList names() const
{
return m_names;
}
public slots:
void setnames(QVariantList arg)
{
qDebug() << arg;
}
signals:
void namesChanged(QVariantList arg);
};
#include <QApplication>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
qmlRegisterType<Controller>("FromCpp", 1, 0, "Controller");
QQuickView view(QUrl(QStringLiteral("main.qml")));
view.show();
return app.exec();
}
#include "main.moc"
Output:
(QVariant(QVariantList, (QVariant(int, 1) , QVariant(int, 2) , QVariant(int, 3) ) ) , QVariant(QVariantList, (QVariant(int, 4) , QVariant(int, 5) , QVariant(int, 6) ) ) )