席替えをしたかった
ちょっと諸事情ありまして、席替えプログラムを作っておりました。
で、今回作ったプログラムを題するなら、「お隣さん絶対かわるやーつ」ってところでしょうか。
前後お隣の人がかならず変わります。というか、変わるまで、プログラムは終わりません。
あと、かなりテキトーなプログラムになるので、まさかりは投げないでください。
以下、プログラムになります。
#include<iostream> #include<vector> #include<random> #include<unistd.h> #define X_MAX 6 #define Y_MAX 4 #define KINBOU_N 4 #define NINZU 21 struct Tkumi{ int p1; int p2; bool operator<( const Tkumi& right ) const { return p1 == right.p1 ? p2 < right.p2 : p1 < right.p1; } }; void back_disp(){ printf("\e[5F"); } void disp(int seki[Y_MAX+2][X_MAX+2], char const *name[]){ printf("---------------------------------------------"); printf("---------------------------------------------------\n"); for ( int y = 1; y < Y_MAX+1; y++ ){ for ( int x = 1; x < X_MAX+1; x++ ){ if ( seki[y][x] > 0 ) { printf("%16s", name[seki[y][x]]); }else{ printf(" "); } } printf("\n"); } } int main(int argc, char const *argv[]) { int kinbou_x[KINBOU_N] = { 1, 0, -1, 0 }; int kinbou_y[KINBOU_N] = { 0, 1, 0, -1 }; int set[Y_MAX+2][X_MAX+2] = { // 場所固定の場合はここに値を入れる {-1,-1,-1,-1,-1,-1,-1,-1}, {-1, 0, 0, 0, 0, 0,19,-1}, {-1, 0, 0, 0, 0, 0, 0,-1}, {-1, 0, 0, 0, 0, 0, 0,-1}, {-1, 0,-1, 0,-1, 0,-1,-1}, {-1,-1,-1,-1,-1,-1,-1,-1} }; int next[Y_MAX+2][X_MAX+2] = { {-1,-1,-1,-1,-1,-1,-1,-1}, {-1, 0, 0, 0, 0, 0, 0,-1}, {-1, 0, 0, 0, 0, 0, 0,-1}, {-1, 0, 0, 0, 0, 0, 0,-1}, {-1, 0,-1, 0,-1, 0,-1,-1}, {-1,-1,-1,-1,-1,-1,-1,-1} }; int before[Y_MAX+2][X_MAX+2] = { {-1,-1,-1,-1,-1,-1,-1,-1}, {-1, 1, 5, 8,12,15,19,-1}, {-1, 2, 6, 9,13,16,20,-1}, {-1, 3, 7,10,14,17,21,-1}, {-1, 4,-1,11,-1,18,-1,-1}, {-1,-1,-1,-1,-1,-1,-1,-1} }; int now[Y_MAX+2][X_MAX+2] = { {-1,-1,-1,-1,-1,-1,-1,-1}, {-1, 1, 2, 3, 4, 5, 6,-1}, {-1, 7, 8, 9,10,11,12,-1}, {-1,13,14,15,16,17,18,-1}, {-1,19,-1,20,-1,21,-1,-1}, {-1,-1,-1,-1,-1,-1,-1,-1} }; char const *name[NINZU+1] = { "nonono", "name01", "name02", "name03", "name04", "name05", "name06", "name07", "name08", "name09", "name10", "name11", "name12", "name13", "name14", "name15", "name16", "name17", "name18", "name19", "name20", "name21" }; std::vector<Tkumi> kinshi; Tkumi dmy = { 0, 0 }; // 禁止リストを作成 for ( int y = 1; y < Y_MAX+1; y++ ){ for ( int x = 1; x < X_MAX+1; x++ ){ if ( now[y][x] >= 0 ) { // -1じゃなければ、4近傍を検索 for ( int k = 0; k < KINBOU_N; k++ ) { int hikaku = now[y+kinbou_y[k]][x+kinbou_x[k]]; if ( hikaku > 0 ){ // -1じゃなければ追加 dmy.p1 = now[y][x]; dmy.p2 = hikaku; if ( dmy.p1 > dmy.p2 ){ int swp = dmy.p1; dmy.p1 = dmy.p2; dmy.p2 = swp; } kinshi.push_back(dmy); } } } } } for ( ;; ) { // printf("---- restart ----\n"); // disp(next, name); int not_decide = 0; int ok = 0; // 固定値を設定 for ( int y = 1; y < Y_MAX+1; y++ ){ for ( int x = 1; x < X_MAX+1; x++ ){ if ( set[y][x] >= 0 ) { if ( set[y][x] == 0 ) not_decide++; next[y][x] = set[y][x]; } } } // 確定フェーズへ // 乱数生成 std::random_device rnd; // 非決定的な乱数生成器を生成 std::mt19937 mt(rnd()); // メルセンヌ・ツイスタの32ビット版、引数は初期シード値 std::uniform_int_distribution<> rand(1, NINZU); // [0, 99] 範囲の一様乱数 ok = 1; for ( int y = 1; y < Y_MAX+1; y++ ){ for ( int x = 1; x < X_MAX+1; x++ ){ if ( next[y][x] == 0 ) { // 席が未決かを確認 // 1席を決定 int maybe; for ( ;; ) { maybe = rand(mt); int maybe_cnt = 0; // 表内を探索して、同一番号があれば、乱数を振り直す for ( int y = 1; y < Y_MAX+1; y++ ){ for ( int x = 1; x < X_MAX+1; x++ ){ if ( next[y][x] == maybe ) { maybe_cnt++; } } } if ( maybe_cnt == 0 ) { // かぶり無しなので、この座席で仮決定 next[y][x] = maybe; break; } } back_disp(); disp(next, name); usleep(50000); // 禁止組み合わせを確認 // 4近傍を検索 for ( int k = 0; k < KINBOU_N; k++ ) { int hikaku = next[y+kinbou_y[k]][x+kinbou_x[k]]; if ( hikaku > 0 ){ // 近傍の席が配置済み for ( auto v = kinshi.begin(); v != kinshi.end(); v++ ) { if ( v->p1 == hikaku && v->p2 == maybe ) { ok = 0; break; } if ( v->p1 == maybe && v->p2 == hikaku ) { ok = 0; break; } } } } } if ( ok == 0 ) break; } if ( ok == 0 ) break; } if ( ok == 1 ){ break; } } printf("-----------------finale-------------\n"); printf("-----------------finale-------------\n"); printf("-----------------finale-------------\n"); disp(next, name); return 0; }