kivantium活動日記

プログラムを使っていろいろやります

コマンドライン上でライツアウトを遊ぶ

ライツアウトというパズルゲームコマンドライン上で遊ぶプログラムを書きました。
盤面をランダムに生成して解法が存在しない場合はimpossibleと表示して終了、存在する場合は遊ぶモードに入ります。左上から順についたマスの番号を指定して消灯・点灯を行います。

#include<iostream>
#include<cstdlib>
#include<ctime>

using namespace std;

bool map[41];
bool answer[25];
bool solvable=false;
int table[25] = {
    6, 7, 8, 9, 10,
    12,13,14,15,16,
    18,19,20,21,22,
    24,25,26,27,28,
    30,31,32,33,34};

void show(){
    for(int i=0; i<25; i++){
        if(map[table[i]]) cout << "O";
        else cout << "X";
        if((i+1)%5==0) cout << endl;
    }
}

int push(int pos){
    map[table[pos]]=!map[table[pos]];
    map[table[pos]-1]=!map[table[pos]-1];
    map[table[pos]+1]=!map[table[pos]+1];
    map[table[pos]-6]=!map[table[pos]-6];
    map[table[pos]+6]=!map[table[pos]+6];
    return 0;
}

void search(int pos){
    if(pos==25){
        bool flag=true;
        for(int i=20; i<25; i++){
            if(map[table[i]]) flag=false;
        }
        if(flag){
            solvable = true;
            //解答表示部はコメントアウト
            /*cout << "answer" << endl;
              for(int i=0; i<25; i++){
              if(answer[i]) cout << "1";
              else cout << "0";
              if((i+1)%5==0) cout << endl;
              }*/
        }
    } else {
        if(pos < 5){
            search(pos+1);
            answer[pos]=!answer[pos];
            push(pos);
            search(pos+1);
            answer[pos]=!answer[pos];
            push(pos);
        } else{
            if(!map[table[pos]-6]){
                search(pos+1);
            } else{
                answer[pos]=!answer[pos];
                push(pos);
                search(pos+1);
                answer[pos]=!answer[pos];
                push(pos);
            }
        }
    }
}

int main(void){
    srand((unsigned int)time(NULL));
    int seed = rand()%(1<<25);
    int c;
    for(int i=0; i<25; i++){
        answer[i]=false;
        if(seed&(1<<i)) map[table[i]]=true;
        else map[table[i]]=false;
    }
    show();
    search(0);
    if(solvable) cout << "possible" << endl;
    else {
        cout << "impossible" << endl;
        return -1;
    }
    while(cin >> c){
        if(c<1 | c>25){
            cout << "error!"<< endl;
            continue;
        }
        c -= 1;
        push(c);
        show();
        bool clear=true;
        for(int i=0; i<25; i++){
            if(map[table[i]]) clear=false;
        }
        if(clear){
            cout << "Clear!!" << endl;
            return 0;
        }
    }
    return 0;
}

プレイ画面はこんな感じです
f:id:kivantium:20140917141906p:plain
次はグラフィックを実装します。

参考

ライツアウトを解く 解が存在するのか調べるアルゴリズムにはこれを使いました。