プログラムでタイルを生成しようとすることもできますが、対称性のために注意が必要な重複があり、生成されたパターンの一部は偽物である可能性があります。次に例を示します。
int array0[16]={0,0,0,0,
0,0,0,0,
0,0,0,0,
1,1,1,1};
int array0[16]={0,0,0,1,
0,1,0,0,
1,1,0,1,
0,0,1,0};
すべての組み合わせを試す生成アルゴリズムによって生成される可能性があります。重複を避けるには、タイル構成に存在する対称規則を確立する必要があります。これは、ポリオミノのより一般的な設定では非常に興味深い問題です。
テトリス タイルの場合、有効な構成がわずかしかないことを考えると、その解決策は少し行き過ぎかもしれません。ただし、すべてのタイルを同じ配列に格納し、配列要素の各ビットを使用して各タイルの情報を保持し、ビットマスクを使用して正しいパターンを選択することで、メモリ スペースを少し節約できます。
これは、組み合わせを行う C++11 の小さなプログラムです。
#include <array>
#include <vector>
#include <iostream>
#include <utility>
#define WIDTH 4
typedef std::pair<int,int> coord_t;
coord_t coord(int x, int y) {
return std::make_pair(x,y);
}
int index(const coord_t &c) {
//std::cout << "getting (" << c.first << "," << c.second << ")" << std::endl;
return c.first * WIDTH + c.second;
}
coord_t cw (const coord_t &c){
int x = c.first;
int y = c.second;
return coord(WIDTH - 1 - y, x);
}
coord_t r0(const coord_t &c){
return c;
}
coord_t r90(const coord_t &c){
return r0(cw(c));
}
coord_t r180(const coord_t &c){
return r90(cw(c));
}
coord_t r270(const coord_t &c){
return r180(cw(c));
}
typedef coord_t (*rotate)(const coord_t &);
class tetro;
std::ostream &operator <<(std::ostream &out, const tetro &t);
class tetro {
public:
tetro(){ v.reserve(WIDTH * WIDTH); }
tetro(const std::initializer_list<int> &data): v(data){
std::cout << *this << std::endl;
}
tetro(const tetro &src) {
for (int i = 0; i < WIDTH * WIDTH; i++)
v[i] = src.v[i];
}
void set(coord_t c, int val){
v[index(c)] = val;
}
int get(coord_t c) const {
return v[index(c)];
}
void combine (int r, const tetro &b, rotate rot){
int i,j;
for (i = 0; i < WIDTH; i++) {
for (j = 0; j < WIDTH; j++) {
coord_t c = coord(i,j);
set(c, get(c) | ( b.get(rot(c)) << r));
}
}
}
private:
std::vector<int> v;
};
std::ostream &operator <<(std::ostream &out, const tetro &t){
int i,j;
for (i = 0; i < WIDTH; i++) {
for (j = 0; j < WIDTH; j++) {
coord_t c = coord(i,j);
out << t.get(c) << ",";
}
out << std::endl;
}
return out;
}
std::array<tetro, 6> vl {{
{
0,0,1,0,
0,0,1,0,
0,1,1,0,
0,0,0,0
},
{
0,0,0,0,
0,1,1,0,
0,1,1,0,
0,0,0,0
},
{
0,0,0,0,
1,1,1,1,
0,0,0,0,
0,0,0,0
},
{
0,1,0,0,
0,1,0,0,
0,1,1,0,
0,0,0,0
},
{
0,1,0,0,
0,1,1,0,
0,0,1,0,
0,0,0,0
},
{
0,0,0,0,
1,1,1,0,
0,1,0,0,
0,0,0,0
}
}};
void combine(int rank, tetro &t, rotate rot){
for (auto it = vl.begin(); it != vl.end(); ++it) {
t.combine(rank, *it, rot);
rank++;
}
}
int main(){
tetro t;
int d = 6;
combine(0, t, r0);
combine(d, t, r90);
combine(d+d, t, r180);
combine(d+d+d, t, r270);
std::cout << "result " << std::endl << t << std::endl;
}
これは、標準テトロミノとミラーリングされたテトロミノから開始し、int
各テトロミノのすべての回転を含むすべてのバリエーションを含む 単一の配列を構築します。コードを最初の組み合わせに制限するだけです。既にコードで処理されている場合はローテーションなしで、char
代わりに の配列を使用すると、合計で 16 バイトのスペースしか消費されません (データを操作するために必要な追加のコードによって使用されるスペースはカウントされず、そのまま残ります)。練習…)。
それ以外の場合は、データ全体を保持し、 flyweightパターンを使用してオブジェクトを実装します。各オブジェクトには、テトロミノのランクとその回転 ( 0
、90
、180
、および270
、つまり 4 つの異なる状態) のみが含まれます。上記のプログラムによって生成された配列全体 (384 バイト) を含め、ランクと状態からビットマスクを計算する関数を作成する必要があります (これは、提供されたプログラムのコードから推測できます)。