ViVi Home > 技術文書 > さくさく理解できる C/C++ コンソールアプリ入門 > カーソル位置指定(Win32)


 

 

カーソル位置指定(Win32)
Copyright (C) 2014 by Nobuhide Tsuda

カーソル位置指定関数

// カーソル位置指定 for Windows Console
void setCursorPos(int x, int y)
{
    HANDLE hCons = GetStdHandle( STD_OUTPUT_HANDLE );
    COORD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(hCons, pos);
}

上記がカーソル位置を指定する関数定義である。
通常のコンソール画面は、横80カラム、縦25行から成るので、 x は [0, 80) の範囲、y は [0, 25) の範囲となる。※ [a, b) は a 以上、b 未満の範囲を表す。

実装的には、引数を用意して、Win32 API の SetConsoleCursorPosition() をコールしているだけだ。
最初の引数はコンソールハンドルで、色指定の時と同じように GetStdHandle( STD_OUTPUT_HANDLE ) で取得する。
座標は COORD 構造体を利用する。

これらの関数、構造体を利用するには <window.h> をインクルードしておく必要がある。

使用例

下記は、画面のランダムな位置に、100個の * を表示するものである。

#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
    const int CONS_WD = 80;
    const int CONS_HT = 25;
    for (int i = 0; i < 100; ++i) {
        setCursorPos(rand() % CONS_WD, rand() % CONS_HT);    //  カーソルを画面上のランダムな位置に移動
        cout << "*";     //  * を描画
    }
    getchar();
    return 0;
}

演習問題

  1. (0, 0) から (24, 24) 間と、(0, 24) から (24, 0) 間を * の直線で結び、画面に大きな X を描画するプログラムを書きなさい。
  2. 初期位置 (40, 12) に * を表示し、それが 0.2秒毎にランダムに上下左右に移動するプログラムを書きなさい。
  3. 初期位置 (0, 0) に * を表示し、それが 0.2秒毎に右下方向に移動し、壁で反射するプログラムを書きなさい。

 

解答例

  1. (0, 0) から (24, 24) 間と、(0, 24) から (24, 0) 間を * の直線で結び、画面に大きな X を描画するプログラムを書きなさい。
  2. 初期位置 (40, 12) に * を表示し、それが 0.2秒毎にランダムに上下左右に移動するプログラムを書きなさい。
  3. 初期位置 (0, 0) に * を表示し、それが 0.2秒毎に右下方向に移動し、壁で反射するプログラムを書きなさい。
  4. #include <iostream>
    #include <Windows.h>
    #define     CONS_WD     80
    #define     CONS_HT      25
    using namespace std;
    // カーソル位置指定 for Windows Console
    void setCursorPos(int x, int y)
    {
        HANDLE hCons = GetStdHandle( STD_OUTPUT_HANDLE );
        COORD pos;
        pos.X = x;
        pos.Y = y;
        SetConsoleCursorPosition(hCons, pos);
    }
    int main()
    {
        int x = 0;      //  物体位置
        int y = 0;
        int vx = 1;     // x 方向速度
        int vy = 1;    //  y 方向速度
        for (;;) {
            setCursorPos(x, y);
            cout << "*";
            Sleep(200);
            int x0 = x;     // 移動前の位置
            int y0 = y;
            if( (x += vx) < 0 || x >= CONS_WD ) {    // 左右の壁に衝突した場合
                x += (vx = -vx) * 2;      //  x 方向速度反転、壁で反射
                cout << (char)7;       //  Bepp 音
            }
            if( (y += vy) < 0 || y >= CONS_HT ) {    //  上下の壁に衝突した場合
                y += (vy = -vy) * 2;      // y 方向速度反転、壁で反射
                cout << (char)7;       //  Beep 音
            }
            setCursorPos(x0, y0);
            cout << " ";      // 移動前の位置を空白に
        }
        return 0;
    }