БлогNot. Найди сеты

Найди сеты

Головоломка на колоде из игры Сеты, по крайней мере, в том виде, что она описана в "Вики" (только пурпурный или фиолетовый цвет заменил на синий).

Задача состоит в том, чтобы найти сеты из 3 карт в наборе карт, которые были сданы в открытую.

Реализованы описания карты (класс card) и головоломки (класс setPuzzle) плюс отдельная функция для вывода информации (displayCardsSets).

Если достаточно сетов не находится, выполняем просто "аварийный выход" из функции setPuzzle::create через n попыток, которых может не хватить, ведь наборы генерируются случайно.

Может, когда пригодится ещё, идея сетов, по крайней мере, забавная. Код запускался в консоли Visual Studio 2015.

#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <string>
#include <ctime>
using namespace std;

enum colorType { red, green, blue };
enum symbolType { oval, squiggle, diamond };
enum numberType { one, two, three };
enum shadingType { solid, open, striped };

class card {
private:
 colorType color;
 symbolType symbol;
 numberType number;
 shadingType shading;
public:
 card (colorType c, symbolType s, numberType n, shadingType h) {
  color = c; symbol = s; number = n; shading = h;
 }
 colorType getColor() { return color; }
 symbolType getSymbol() { return symbol; }
 numberType getNumber() { return number; }
 shadingType getShading() { return shading; }
 string toString() {
  string str = "[ ";
  str += color == red ? "R " : color == green ? "G " : "B ";
  str += number == one ? "1 " : number == two ? "2 " : "3 ";
  str += symbol == oval ? "O " : symbol == squiggle ? "~ " : "V ";
  str += shading == solid ? "#" : shading == open ? "_" : "%";
  return str + " ]";
 }
};

typedef struct { vector <size_t> index; } set;

class setPuzzle {
private:
 vector<card> this_cards;

 bool testSet (card *c1, card *c2, card *c3) {
  int c = (c1->getColor() + c2->getColor() + c3->getColor()) % 3,
      s = (c1->getSymbol() + c2->getSymbol() + c3->getSymbol()) % 3,
      n = (c1->getNumber() + c2->getNumber() + c3->getNumber()) % 3,
      h = (c1->getShading() + c2->getShading() + c3->getShading()) % 3;
  return !(c + s + n + h);
 }
public:
 setPuzzle() {
  for (size_t c = red; c <= blue; c++) {
   for (size_t s = oval; s <= diamond; s++) {
    for (size_t n = one; n <= three; n++) {
     for (size_t h = solid; h <= striped; h++) {
      card crd(
       static_cast <colorType> (c),
       static_cast <symbolType> (s),
       static_cast <numberType> (n),
       static_cast <shadingType> (h)
      );
      this_cards.push_back(crd);
     }
    }
   }
  }
 }

 void create (size_t countCards, size_t countSets, vector <card> &cards, vector <set> &sets) {
  long int i = 0, n = 1e5;
  while (true) { //КОНТРОЛЬ "ЗАВИСАНИЙ" - ВЫХОД ЧЕРЕЗ n ПОПЫТОК
   sets.clear();
   cards.clear();
   random_shuffle (this_cards.begin(), this_cards.end());
   for (size_t f = 0; f < countCards; f++) {
    cards.push_back(this_cards.at(f));
   }
   for (size_t c1 = 0; c1 < cards.size() - 2; c1++) {
    for (size_t c2 = c1 + 1; c2 < cards.size() - 1; c2++) {
     for (size_t c3 = c2 + 1; c3 < cards.size(); c3++) {
      if (testSet(&cards.at(c1), &cards.at(c2), &cards.at(c3))) {
       set s;
       s.index.push_back(c1); s.index.push_back(c2); s.index.push_back(c3);
       sets.push_back(s);
      }
     }
    }
   }
   if (sets.size() == countSets || ++i==n) return;
  }
 }
};

void displayCardsSets(vector <card> &cards, vector <set> &sets) {
 size_t cnt = 1;
 cout << "CREATE " << cards.size() << " CARD(S):" << endl;
 for (vector<card>::iterator i = cards.begin(); i != cards.end(); i++) {
  cout << setw(2) << cnt++ << ": " << (*i).toString() << endl;
 }
 cout << endl << "CONTAINING " << sets.size() << " SET(S):" << endl;
 for (vector<set>::iterator i = sets.begin(); i != sets.end(); i++) {
  for (size_t j = 0; j < (*i).index.size(); j++) {
   cout << " " << setiosflags(ios::left) << setw(28)
    << cards.at((*i).index.at(j)).toString() << " : "
    << resetiosflags(ios::left) << setw(2) << (*i).index.at(j) + 1 << "\n";
  }
  cout << endl;
 }
 cout << endl;
}
int main(int argc, char* argv[]) {
 srand (static_cast <unsigned> (time(NULL)));
 setPuzzle p;
 vector <card> v;
 vector <set>  s;
 p.create (10, 5, v, s);
  //максимум = 81, 27, но это долго будет выполняться :)
 displayCardsSets (v, s);
 
 cin.get(); return 0;
}

теги: random игра c++ числа

16.05.2019, 16:35; рейтинг: 71