この記事は SLP-KBIT AdventCalendar2023 24日目の記事です。
はじめに
こんばんわ。tttです。
メリークリスマス!!!!
今夜はクリスマスイブですね。
みなさん、いかがお過ごしでしょうか。
大切な家族や友人と過ごしたり、はたまた恋人と共に過ごす方もいらっしゃるでしょう。
中には「一人ぼっちのクリスマスイブでも問題ないし」と考えてる方もいると思います。
しかし、それは良くありません!
クリスマスイブは、「家族や友人、恋人との団らんの時間を大切にする時間である」(ネット検索)とされているように、決して一人で過ごす時間ではないのです!!
クリぼっちで問題ない!と考えている人も、心の底では寂しい思いを少なからずしているはずです。
さあ、今すぐ大切な人に会いに行きましょう!!
みなさんのクリスマスイブが、とても良い思い出になることを願っています。
え、僕?
ハハっ
序章
僕の大好きなボカロ曲です(唐突)。
何度聴いても素晴らしい!!
ココスキポイント
ベースが好き、コード進行が好き、シンプルな音楽構成が好き、歌詞が好き、間奏のギター好き、こんだけ爽やかな音楽のくせに「失恋ソング」なのが好き、こんだけ爽やかな音楽なのにMVが真っ黒な画面に緑コンソール文字だけっていうギャップが好き、タイトルが好き、以前の曲とつながってるのが好き、etc
考察も語りたいところですが、それだけで一つの記事になりそうなので割愛。
一応、他人の考察の中で納得したものもあるので、興味あればどぞ。
ほんへ
で。
情報学生の方なら以下の画像を見て思うことはないだろうか。
そうです。
「この画面をターミナル上で再現したい!!!!」
ですよね。
やりましょう。
文字列の解読?
したけりゃ勝手にドウゾ
ちなみに平文に直すとミクがうp主を罵倒するメッセージが現れます
CTF経験者は自力で解けるかな?
Step1.まずは普通に出力
どう出力しようかなぁと考えたとき、Cプログラムとして実行するのが面白そうだなと思ったので、プログラミングします。
とは言っても、文字を出力するだけのプログラムですけどね。
大きい文字の「Calc.」はもちろん工夫します。
#include <stdio.h>
int main(void)
{
putchar('\n');
puts("Initializing...");
putchar('\n');
puts("837E834E81755982B382F182CC82B182C682CD");
puts("82E082A4965982EA82BD82D982A482AA");
puts("82A282A282C68E7682A282DC82B78176...");
putchar('\n');
puts("838B834A8175918A95CF82ED82E782B8");
puts("96A297FB82AA82DC82B582A282C88176...");
putchar('\n');
puts("8357837E817592FA82DF82AA88AB82A282E68176...");
putchar('\n');
putchar('\n');
puts(" ■■■ ■");
puts("■ ■ ■■ ■ ■■■");
puts("■ ■ ■ ■");
puts("■ ■■■ ■ ■");
puts("■ ■ ■ ■ ■ ■");
puts(" ■■■ ■■■ ■ ■■■ ■");
putchar('\n');
putchar('\n');
puts("8357837E815B817581638163");
puts("28814C8145");
puts("81CD8145814D29");
puts("816381638176...");
putchar('\n');
return 0;
}
実行結果
Initializing...
837E834E81755982B382F182CC82B182C682CD
82E082A4965982EA82BD82D982A482AA
82A282A282C68E7682A282DC82B78176...
838B834A8175918A95CF82ED82E782B8
96A297FB82AA82DC82B582A282C88176...
8357837E817592FA82DF82AA88AB82A282E68176...
■■■ ■
■ ■ ■■ ■ ■■■
■ ■ ■ ■
■ ■■■ ■ ■
■ ■ ■ ■ ■ ■
■■■ ■■■ ■ ■■■ ■
8357837E815B817581638163
28814C8145
81CD8145814D29
816381638176...
まあ普通ですね。
Step2.色をつける
MVの文字は、緑色なのでそれに合わせます。
C言語には特殊文字と呼ばれるものが存在します。
ピンと来ない方もいると思いますが、簡単にいうと\n
や\0
などです。
で、文字を緑色にする特殊文字は以下の通りです。
\x1b[32m
長いので説明は省きます。
ファ!?なんだこれ!!と思う方はこちらをどうぞ。
コード
#include <stdio.h>
int main(void)
{
printf("\x1b[32m");
putchar('\n');
puts("Initializing...");
putchar('\n');
puts("837E834E81755982B382F182CC82B182C682CD");
puts("82E082A4965982EA82BD82D982A482AA");
puts("82A282A282C68E7682A282DC82B78176...");
putchar('\n');
puts("838B834A8175918A95CF82ED82E782B8");
puts("96A297FB82AA82DC82B582A282C88176...");
putchar('\n');
puts("8357837E817592FA82DF82AA88AB82A282E68176...");
putchar('\n');
putchar('\n');
puts(" ■■■ ■");
puts("■ ■ ■■ ■ ■■■");
puts("■ ■ ■ ■");
puts("■ ■■■ ■ ■");
puts("■ ■ ■ ■ ■ ■");
puts(" ■■■ ■■■ ■ ■■■ ■");
putchar('\n');
putchar('\n');
puts("8357837E815B817581638163");
puts("28814C8145");
puts("81CD8145814D29");
puts("816381638176...");
putchar('\n');
printf("\x1b[0m");
return 0;
}
実行結果
なんかこれじゃない感。
というのも、大文字の「Calc.」が本家と少し形が異なるんですよねぇ...
ということで工夫します。
Step3.「Calc.」の表記方法を一新
ここ賢いポイント。
「■」という文字を使って「Calc.」を表現しようとしていますが、これが半角判定になり、うまくできません。
ここで、C言語の文字を緑色にする特殊文字に注目します。
「文字を緑色にする」ということは、つまり「空白文字も緑色にする」ということです。
なので、空白文字に緑色が当たるよう調整すれば、いい感じになるはずです。
コード
#include <stdio.h>
int main(void)
{
printf("\x1b[32m");
putchar('\n');
puts("Initializing...");
putchar('\n');
puts("837E834E81755982B382F182CC82B182C682CD");
puts("82E082A4965982EA82BD82D982A482AA");
puts("82A282A282C68E7682A282DC82B78176...");
putchar('\n');
puts("838B834A8175918A95CF82ED82E782B8");
puts("96A297FB82AA82DC82B582A282C88176...");
putchar('\n');
puts("8357837E817592FA82DF82AA88AB82A282E68176...");
putchar('\n');
putchar('\n');
puts(" \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts(" \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
putchar('\n');
putchar('\n');
puts("8357837E815B817581638163");
puts("28814C8145");
puts("81CD8145814D29");
puts("816381638176...");
putchar('\n');
printf("\x1b[0m");
return 0;
}
実行結果
:)
Step4.アニメーションをつける
当初の目的は達成しましたが、あまり面白みがないので、この画面に動きを付けます。
MVに登場するClacプログラムが実際にどのように動くのか、想像しながら作成していきます。
文字が流れるように表示されていく様子を想像したので、それをプログラムで表現することにしました。
それを実現するために
- usleep()関数
- fflush()関数
を使用します。
また、任意の時間によって文字を出力したいので、それを実現する自作関数も用意します。
参考サイト:
ついでに実行時に画面が更新されるようにもします。
コード
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void slowMsg(char* msg, int wait_time)
{
int i = 0;
while(msg[i] != '\0')
{
printf("%c", msg[i]);
usleep(wait_time);
fflush(stdout);
i++;
}
}
int main(void)
{
system("clear");
printf("\x1b[32m");
putchar('\n');
slowMsg("Initializing", 100000);
slowMsg("... ", 1000000);
putchar('\n');
putchar('\n');
slowMsg("837E834E81755982B382F182CC82B182C682CD\n", 30000);
slowMsg("82E082A4965982EA82BD82D982A482AA\n", 30000);
slowMsg("82A282A282C68E7682A282DC82B78176... ", 30000);
putchar('\n');
putchar('\n');
slowMsg("838B834A8175918A95CF82ED82E782B8\n", 30000);
slowMsg("96A297FB82AA82DC82B582A282C88176... ", 30000);
putchar('\n');
putchar('\n');
slowMsg("8357837E817592FA82DF82AA88AB82A282E68176", 30000);
slowMsg("... ", 800000);
putchar('\n');
putchar('\n');
putchar('\n');
puts(" \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts(" \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
putchar('\n');
putchar('\n');
usleep(1000000);
slowMsg("8357837E815B817581638163\n", 30000);
slowMsg("28814C8145\n", 30000);
slowMsg("81CD8145814D29\n", 30000);
slowMsg("816381638176... ", 30000);
putchar('\n');
putchar('\n');
printf("\x1b[0m");
return 0;
}
実行結果
[calc_step5.gifhttps://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384147/852b8c34-2460-0917-2c2c-d68de4bb9674.gif
動画をgifに直すと劣化が凄かったのでカット
:(
Step5.音楽と同時に実行する
仕上げです。
音楽も流して盛大にしましょう。
コード
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void slowMsg(char* msg, int wait_time)
{
int i = 0;
while(msg[i] != '\0')
{
printf("%c", msg[i]);
usleep(wait_time);
fflush(stdout);
i++;
}
}
void* startMusic(void *arg)
{
system("mpg123 -q ./music/Calc.mp3");
return NULL;
}
int main(void)
{
system("clear");
printf("\x1b[32m");
putchar('\n');
slowMsg("Initializing", 100000);
slowMsg("...", 800000);
pthread_t music_thread;
pthread_create(&music_thread, NULL, startMusic, NULL);
slowMsg(" ", 500000);
putchar('\n');
putchar('\n');
slowMsg("837E834E81755982B382F182CC82B182C682CD\n", 40000);
slowMsg("82E082A4965982EA82BD82D982A482AA\n", 40000);
slowMsg("82A282A282C68E7682A282DC82B78176... ", 40000);
putchar('\n');
putchar('\n');
slowMsg("838B834A8175918A95CF82ED82E782B8\n", 40000);
slowMsg("96A297FB82AA82DC82B582A282C88176... ", 40000);
putchar('\n');
putchar('\n');
slowMsg("8357837E817592FA82DF82AA88AB82A282E68176", 40000);
slowMsg("... ", 500000);
usleep(408000);
putchar('\n');
putchar('\n');
putchar('\n');
puts(" \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts("\x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
puts(" \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m \x1b[42m \x1b[49m");
putchar('\n');
putchar('\n');
usleep(5000000);
slowMsg("8357837E815B817581638163\n", 30000);
slowMsg("28814C8145\n", 30000);
slowMsg("81CD8145814D29\n", 30000);
slowMsg("816381638176... ", 30000);
usleep(3000000);
putchar('\n');
putchar('\n');
putchar('\n');
slowMsg("すれ違いは結局運命で", 30000);
usleep(1900000);
slowMsg(" 全ては筋書き通りだって", 30000);
usleep(1900000);
putchar('\n');
slowMsg("悲しみを紛らわせるほど", 30000);
usleep(1905000);
slowMsg(" 僕は強くないから", 30000);
usleep(1900000);
putchar('\n');
putchar('\n');
slowMsg("弾き出した答えの全てが", 30000);
usleep(1850000);
slowMsg(" 一つ二つ犠牲を伴って", 30000);
usleep(1840000);
putchar('\n');
slowMsg("また一歩踏み出す勇気を", 30000);
usleep(1800000);
slowMsg(" 奪い取ってゆく", 30000);
usleep(1500000);
putchar('\n');
putchar('\n');
putchar('\n');
slowMsg("いつか", 95000);
usleep(470000);
slowMsg("君に捧げた歌", 30000);
slowMsg(" ", 1830000);
slowMsg("今じゃ哀しいだけの愛の歌", 30000);
usleep(5000000);
putchar('\n');
slowMsg("風に吹かれ飛んでゆけ", 30000);
usleep(4000000);
slowMsg(" 僕らが出会えたあの夏の日まで", 30000);
usleep(12000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
slowMsg("巡り会いも結局運命で", 30000);
usleep(1900000);
slowMsg(" 全ては筋書き通りだって", 30000);
usleep(1900000);
putchar('\n');
slowMsg("都合良く考えられたら", 30000);
usleep(1905000);
slowMsg(" 寂しくはないのかな", 30000);
usleep(1900000);
putchar('\n');
putchar('\n');
slowMsg("弾き出した答えの全てが", 30000);
usleep(1850000);
slowMsg(" 一つ二つ矛盾を伴って", 30000);
usleep(1840000);
putchar('\n');
slowMsg("向こう側へと続く道を", 30000);
usleep(1800000);
slowMsg(" 消し去ってゆく", 30000);
usleep(1400000);
putchar('\n');
putchar('\n');
putchar('\n');
slowMsg("いつか", 95000);
usleep(470000);
slowMsg("君に捧げた歌", 30000);
slowMsg(" ", 1830000);
slowMsg("今じゃ哀しいだけの愛の歌", 30000);
usleep(5000000);
putchar('\n');
slowMsg("風に吹かれ飛んでゆけ", 30000);
usleep(4000000);
slowMsg(" 僕らが出会えたあの夏の日まで", 30000);
usleep(12000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
slowMsg("過去も未来も無くなれば", 30000);
slowMsg(" ", 1900000);
slowMsg("僕も自由に飛び立てるかな", 30000);
usleep(5000000);
putchar('\n');
slowMsg("感情一つ消せるのなら", 30000);
usleep(4000000);
slowMsg(" 「好き」を消せば楽になれるかな", 30000);
usleep(4900000);
putchar('\n');
putchar('\n');
slowMsg("君の耳を、目を、心を", 30000);
slowMsg(" ", 2000000);
slowMsg("通り抜けたモノ全てを", 30000);
usleep(5000000);
putchar('\n');
slowMsg("いつか知ることが出来たら", 30000);
usleep(4500000);
slowMsg(" 次はちゃんと君を愛せるかな", 30000);
usleep(12000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
usleep(3000000);
putchar('\n');
puts("Music : OneRoom");
puts("Created by ttt");
puts("2023/12/24");
putchar('\n');
putchar('\n');
printf("\x1b[0m");
pthread_join(music_thread, NULL);
return 0;
}
実行結果
おわりに
余は大変満足である。
あとカラオケ行きたくなった。
では良いお年を~~~ノシ