質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

C++ else文の内容が勝手に実行される

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,248

score 13

C++ else文がおかしい?

c++の完全初心者なんですが、
https://www.youtube.com/watch?v=JLQLxrgygKk
を見て同じプログラムを書いています。
動画の42:00ごろのeraseConnectedBlocks関数を実装したところ、セルを選択しようとしただけでelse内の処理まで実行され、次のwhileループへ移ってしまいます。
別の場面でも同じバグが起こりましたが、その時はelseとその後ろの{の間にスペースを入れたら解決しました。今回はそれでは解決せず、困っています。回答よろしくお願いします。

状況

セルを選択しただけでブロックの消去がされ、矢印は一瞬しか表示されない

試したこと

elseをelse if(selectedX >=0 )にする

該当部分のコード

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <string.h>
#include<conio.h>

//マップ縦横幅
#define FIELD_WIDTH  8
#define FIELD_HEIGHT 8
    //ブロックの種類
#define BLOCK_TYPE_MAX 7

//セルの状態
enum{
    CELL_TYPE_NONE,//0
    CELL_TYPE_BLOCK_0,//1
    CELL_TYPE_BLOCK_1,//2
    CELL_TYPE_BLOCK_2,//3
    CELL_TYPE_BLOCK_3,//4
    CELL_TYPE_BLOCK_4,//5
    CELL_TYPE_BLOCK_5,//6
    CELL_TYPE_BLOCK_6,//7
    CELL_TYPE_BLOCK_MAX//8
};

//セルAA情報
char cellAA[][3+1] = {
    "・",//CELL_TYPE_NONE
    "〇",//CELL_TYPE_BLOCK_0
    "△",//CELL_TYPE_BLOCK_1
    "□",//CELL_TYPE_BLOCK_2
    "●",//CELL_TYPE_BLOCK_3
    "▲",//CELL_TYPE_BLOCK_4
    "■",//CELL_TYPE_BLOCK_5
    "☆",//CELL_TYPE_BLOCK_6
};

//セル(0,0)~(7,7)
int cells[FIELD_HEIGHT][FIELD_WIDTH];

//連結チェックされたか
int ischecked[FIELD_HEIGHT][FIELD_WIDTH];

//カーソル位置
int cursorX, cursorY;

//選択されたセル
int selectedX = -1, selectedY = -1;

/*
    連結判定関数
    x:対象のx座標
    y:対象のy座標
    cellType:ブロックの種類
    count:つながっている数
*/
int getConnectedBlockCount(int _x, int _y, int _cellType, int _count){
    //判定対象か否か
    if ((_x < 0) || (_x >= FIELD_WIDTH) || (_y < 0 ) || (_y >= FIELD_HEIGHT) || ischecked[_y][_x] || (cells[_y][_x] == CELL_TYPE_NONE) || (cells[_y][_x] != _cellType)) 
        return _count;
    _count++;
    ischecked[_y][_x] = true;

    //再帰処理
    //上
    _count = getConnectedBlockCount(_x, _y-1, _cellType, _count);
    //下
    _count = getConnectedBlockCount(_x, _y+1, _cellType, _count);
    //左
    _count = getConnectedBlockCount(_x-1, _y, _cellType, _count);
    //右
    _count = getConnectedBlockCount(_x+1, _y, _cellType, _count);

    return _count;
}

//連結したブロックを消す関数
void eraseConnectedBlocks(int _x, int _y, int _cellType){
    //対象か否か
    if ((_x < 0) || (_x >= FIELD_WIDTH) || (_y < 0 ) || (_y >= FIELD_HEIGHT) || (cells[_y][_x] == CELL_TYPE_NONE) || (cells[_y][_x] != _cellType))
        return;
    //自身を消す
    cells[_y][_x] = CELL_TYPE_NONE;
    //上下左右も判定し消す
    eraseConnectedBlocks(_x, _y-1, _cellType);
    eraseConnectedBlocks(_x, _y+1, _cellType);
    eraseConnectedBlocks(_x-1, _y, _cellType);
    eraseConnectedBlocks(_x+1, _y, _cellType);
}
//main
int main() {
    //ブロックのランダム化
    srand((unsigned int)time(NULL));
    for (int y = 0; y < FIELD_HEIGHT; y++){
        for(int x = 0; x < FIELD_WIDTH; x++){
            //1 + 0...6 =1...7
            cells[y][x] = CELL_TYPE_BLOCK_0 + rand() % BLOCK_TYPE_MAX;
        }
    }
    //描画とか
    while (1) {
        system("cls");
        for (int y = 0; y < FIELD_HEIGHT; y++) {

            for (int x = 0; x < FIELD_WIDTH; x++) {
                if ((x == cursorX) && (y == cursorY)) {
                    //カーソル
                    printf("◎");
                }
                else {
                    //ブロック
                    printf("%s", cellAA[cells[y][x]]);
                }
            }
            //y座標選択位置
            if (y == selectedY){
                printf("←");
            }
            //行移動
            printf("\n");
        }
        //最後の行に追加
        for(int x = 0; x < FIELD_WIDTH; x++){
            //選択されていたら矢印を描画
            printf("%s",(x == selectedX)?"↑":" " );
        }

        //キー入力に対応
        switch (_getch()){
            //カーソル移動
            case 'w':(cursorY == 0)? : cursorY--; break;
            case 's':(cursorY == FIELD_HEIGHT-1)? : cursorY++; break;
            case 'a':(cursorX == 0)? : cursorX--; break;
            case 'd':(cursorX == FIELD_WIDTH-1)? : cursorX++; break;
            default:
            if (selectedX < 0){
                //選択
                selectedX = cursorX;
                selectedY = cursorY;

            }else{
                //入れ替え
                int tmp = cells[cursorY][cursorX];
                cells[cursorY][cursorX] = cells[selectedY][selectedX];
                cells[selectedY][selectedX] = tmp;

                //判定フラグクリア
                memset(ischecked, 0, sizeof ischecked);

                    //連結判定&ブロック消去
                for (int y = 0; y < FIELD_HEIGHT; y++){
                    for(int x = 0; x < FIELD_WIDTH; x++){
                        int n = getConnectedBlockCount(x, y, cells[y][x], 0);
                        if(n >= 3) {
                            eraseConnectedBlocks(x, y, cells[y][x]);
                        }
                    }
                }

                //選択解除
                selectedX =
                selectedY = -1;
            }
            break;
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • pepperleaf

    2019/01/27 21:49

    thkanaさん>私のてもとでは「いわゆる全角(日本語)文字を入力する」
    矢印キー等の特殊キー (内部複数バイト)でも発生。(三項演算子は、適当に設定)
    もしかしたら、常に漢字入力(で、Ascii変換)になっているかも。
    とすると、aswdでも動かないとか。
    直接入力で、スペースキーで普通に動作(と言っても、動画見てませんが)

    キャンセル

  • ijuhs

    2019/01/28 21:01 編集

    すみません。確認不足で、スペースキーでやってみたら成功しました・・・
    どうやら、選択を矢印キーですると質問の症状が起きるようです。なぜ矢印キーではこのようなバグが発生するのでしょうか?

    キャンセル

  • thkana

    2019/01/28 23:37

    それが「バグ」かどうかは微妙です。
    なぜ、というなら"Windowsがそうなるように作られている"からだし、プログラムを組む人はそれについて知らなきゃいけません。動画中では"位置の移動はFPSと同様wsadで、Enterを押して選択/交換出来るようにしましょう、まぁ他のキーでもいいことにしましょうか"みたいなことを言っているのですから、単にあなたの使い方が間違っていただけ、とも言えます。

    そんなことより、今回は「ソースコードを載せて、起こった現象をそのまま書いたら話が進展した」ということをしっかり覚えておいていただきたいです。

    キャンセル

回答 1

checkベストアンサー

0

なぜ矢印キーではこのようなバグが発生するのでしょうか? 

矢印キーは、内部で発生しているコードが 2バイト(だったか) だからです。
_getch()関数は、字面だけ見れば、文字読込みですが、実体は、1バイトの読込みとなっているからです。(英語圏から、見れば、1文字 = 1バイト)

矢印キーとかのコードは、MSのサイトとかで調べると分かりますが、とりあえず回答まで。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/29 16:06

    詳しい解説ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る