【概要】
ターミナルで機関車を動かすことができるsl
コマンドを作ってみました。
ただし、オプションまでの実装はしていません。
また、俺の機関車は本家の機関車よりスピードが遅いです(作成後に本家と比較したら遅くて、でもこの方が面白いかなと・・・)。
タイトルはこちらの記事のオマージュです → 俺のlsが遅すぎる
本家のコードは一切見ないで、本家の実行結果だけを繰り返し見て作成しました。
(本家のコードはネットにあるかどうか知りません)
[追記] fujitanozomuさんからコメント頂き、下記GitHubにありました。
https://github.com/mtoyoda/sl
【準備】
コードを実行するときはcurses.h
が必要になります。
インストール方法は下記サイトを参考にしました。
Linux Error: curses.h: No such file or directory Problem Solution
【環境】
[vagrant@vagrant-centos65 sl_command]$ cat /etc/centos-release
CentOS release 6.5 (Final)
【コード】
コンパイルするときはgcc -o sl sl.c -lcurses
sl.c
#include <stdio.h>
#include <curses.h>
#include <string.h>
void printSL();
int main(int argc, char *argv[])
{
// 初期化
initscr();
// カーソルを表示しない
curs_set(0);
// キー入力された文字を表示しない
noecho();
// バッファを使用しない
cbreak();
// 機関車出力
printSL();
// 端末制御を終了
endwin();
return 0;
}
void printSL()
{
int count = 1;
int slScrInCol = 0, slScrOutCol = 0;
int lineNum = 0;
int colNum = 0;
// 現在の画面のサイズ取得
// curses.hで定義されているLINES, COLSだとターミナルのサイズを変更しても
// 初期の画面サイズとなってしまうため現在の画面サイズを取得する
// colNumは必要ないため、以後使用しない
getmaxyx(stdscr, lineNum, colNum);
// 機関車を画面中央に表示するため
lineNum /= 4;
char str[24][1000] = {'0'};
int maxLen = strlen(" \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ \\_/ \\_/ \\_/ \\_/");
// マジックナンバー6は微調整用
while(COLS + maxLen + 6 - slScrInCol != 0) {
strncpy(str[0], " ( ) (@@) ( ) (@) () @@ O @ O @ O", slScrInCol);
strncpy(str[1], " (@@@)", slScrInCol);
strncpy(str[2], " ( )", slScrInCol);
strncpy(str[3], " (@@@@)", slScrInCol);
strncpy(str[4], " ( )", slScrInCol);
strncpy(str[5], " (@@) ( ) ( ) () (@) @@ @ O @ O @", slScrInCol);
strncpy(str[6], " ( )", slScrInCol);
strncpy(str[7], " (@@@@)", slScrInCol);
strncpy(str[8], " ( )", slScrInCol);
strncpy(str[9], " (@@@)", slScrInCol);
// 煙突の煙の出力
// 煙と車輪が動く速度は違うため、煙のは車輪に比べて遅く表示する
if (count <= 4) {
mvprintw(lineNum, COLS-slScrInCol, str[0]);
mvprintw(lineNum+1 ,COLS-slScrInCol, str[1]);
mvprintw(lineNum+2 ,COLS-slScrInCol, str[2]);
mvprintw(lineNum+3 ,COLS-slScrInCol, str[3]);
mvprintw(lineNum+4 ,COLS-slScrInCol, "");
mvprintw(lineNum+5 ,COLS-slScrInCol, str[4]);
} else {
mvprintw(lineNum, COLS-slScrInCol, str[5]);
mvprintw(lineNum+1 ,COLS-slScrInCol, str[6]);
mvprintw(lineNum+2 ,COLS-slScrInCol, str[7]);
mvprintw(lineNum+3 ,COLS-slScrInCol, str[8]);
mvprintw(lineNum+4 ,COLS-slScrInCol, "");
mvprintw(lineNum+5 ,COLS-slScrInCol, str[9]);
}
strncpy(str[10], " ==== ________ ___________", slScrInCol);
strncpy(str[11], " _D _| |_______/ \\__I_I_____===__|_________|", slScrInCol);
strncpy(str[12], " |(_)--- | H\\________/ | | =|___ ___| _________________", slScrInCol);
strncpy(str[13], " / | | H | | | | ||_| |_|| _| \\_____A", slScrInCol);
strncpy(str[14], " | | | H |__--------------------| [___] | =| |", slScrInCol);
strncpy(str[15], " | ________|___H__/__|_____/[][]~\\_______| | -| |", slScrInCol);
strncpy(str[16], " |/ | |-----------i_____I [][] [] D |=======|____|________________________|_", slScrInCol);
// 車輪より上部の出力
mvprintw(lineNum+6 , COLS-slScrInCol, str[10]);
mvprintw(lineNum+7 , COLS-slScrInCol, str[11]);
mvprintw(lineNum+8 , COLS-slScrInCol, str[12]);
mvprintw(lineNum+9 , COLS-slScrInCol, str[13]);
mvprintw(lineNum+10, COLS-slScrInCol, str[14]);
mvprintw(lineNum+11, COLS-slScrInCol, str[16]);
mvprintw(lineNum+12, COLS-slScrInCol, str[10]);
strncpy(str[17], "__/ =| o |=-O=====O=====O=====O\\ ____Y___________|__|__________________________|_", slScrInCol);
strncpy(str[18], " |/-=|___|= || || || |_____/\\___/ |_D__D__D_| |_D__D__D_|", slScrInCol);
strncpy(str[19], " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ \\_/ \\_/ \\_/ \\_/", slScrInCol);
strncpy(str[20], "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__|__________________________|_", slScrInCol);
strncpy(str[21], " |/-=|___|=O=====O=====O=====O |_____/\\___/ |_D__D__D_| |_D__D__D_|", slScrInCol);
strncpy(str[22], " \\_/ \\_O=====O=====O=====O/ \\_/ \\_/ \\_/ \\_/ \\_/", slScrInCol);
strncpy(str[23], " |/-=|___|= O=====O=====O=====O|_____/\\___/ |_D__D__D_| |_D__D__D_|", slScrInCol);
// 車輪部分の出力
if (count % 4 == 1) {
mvprintw(lineNum+13, COLS-slScrInCol, str[17]);
mvprintw(lineNum+14, COLS-slScrInCol, str[18]);
mvprintw(lineNum+15, COLS-slScrInCol, str[19]);
} else if (count % 4 == 2) {
mvprintw(lineNum+13, COLS-slScrInCol, str[20]);
mvprintw(lineNum+14, COLS-slScrInCol, str[21]);
mvprintw(lineNum+15, COLS-slScrInCol, str[19]);
} else if (count % 4 == 3) {
mvprintw(lineNum+13, COLS-slScrInCol, str[20]);
mvprintw(lineNum+14, COLS-slScrInCol, str[18]);
mvprintw(lineNum+15, COLS-slScrInCol, str[22]);
} else {
mvprintw(lineNum+13, COLS-slScrInCol, str[20]);
mvprintw(lineNum+14, COLS-slScrInCol, str[23]);
mvprintw(lineNum+15, COLS-slScrInCol, str[19]);
}
// countの数を大きくしないようにするため
if (count / 8 == 1) {
count = 1;
} else {
count++;
}
// 機関車の先頭が画面左から出ていくときの画面出力
if (COLS - slScrInCol <= 0) {
if (count <= 4) {
mvprintw(lineNum, 0, &str[0][slScrOutCol]);
mvprintw(lineNum+1 ,0, &str[1][slScrOutCol]);
mvprintw(lineNum+2 ,0, &str[2][slScrOutCol]);
mvprintw(lineNum+3 ,0, &str[3][slScrOutCol]);
mvprintw(lineNum+4 ,0, "");
mvprintw(lineNum+5 ,0, &str[4][slScrOutCol]);
} else {
mvprintw(lineNum, 0, &str[5][slScrOutCol]);
mvprintw(lineNum+1 ,0, &str[6][slScrOutCol]);
mvprintw(lineNum+2 ,0, &str[7][slScrOutCol]);
mvprintw(lineNum+3 ,0, &str[8][slScrOutCol]);
mvprintw(lineNum+4 ,0, "");
mvprintw(lineNum+5 ,0, &str[9][slScrOutCol]);
}
mvprintw(lineNum+6 , 0, &str[10][slScrOutCol]);
mvprintw(lineNum+7 , 0, &str[11][slScrOutCol]);
mvprintw(lineNum+8 , 0, &str[12][slScrOutCol]);
mvprintw(lineNum+9 , 0, &str[13][slScrOutCol]);
mvprintw(lineNum+10, 0, &str[14][slScrOutCol]);
mvprintw(lineNum+11, 0, &str[16][slScrOutCol]);
mvprintw(lineNum+12, 0, &str[10][slScrOutCol]);
if (count % 4 == 1) {
mvprintw(lineNum+13, 0, &str[17][slScrOutCol]);
mvprintw(lineNum+14, 0, &str[18][slScrOutCol]);
mvprintw(lineNum+15, 0, &str[19][slScrOutCol]);
} else if (count % 4 == 2) {
mvprintw(lineNum+13, 0, &str[20][slScrOutCol]);
mvprintw(lineNum+14, 0, &str[21][slScrOutCol]);
mvprintw(lineNum+15, 0, &str[19][slScrOutCol]);
} else if (count % 4 == 3) {
mvprintw(lineNum+13, 0, &str[20][slScrOutCol]);
mvprintw(lineNum+14, 0, &str[18][slScrOutCol]);
mvprintw(lineNum+15, 0, &str[22][slScrOutCol]);
} else {
mvprintw(lineNum+13, 0, &str[20][slScrOutCol]);
mvprintw(lineNum+14, 0, &str[23][slScrOutCol]);
mvprintw(lineNum+15, 0, &str[19][slScrOutCol]);
}
slScrOutCol++;
}
slScrInCol++;
// 60ミリ秒待つ
usleep(6 * 10000);
refresh();
clear();
}
}