
やぁ、水那だ。
突然だが、僕は昔ウェブサイトの勉強という事でとあるサイトを作った。
ちなみにその頃は、リーダブルコードを知らなければ、文法が合っているのかも分からないという中で作ったサイトであった。
そしてそのサイトは「Mizupedina」という同じ名前で、今でも残っているのだ(後日紹介する)。
そこで今回は、旧Mizupedinaに載せていた「【C言語】Linux上でコンソールテトリスを作れなかった話」をこちらの新Mizupedinaで解説させていただく。
少しでもC言語をやっている方や、これからC言語を始める方にご覧いただければと思う。
それでは早速いってみよう。
経緯と開発環境
時は遡ること弥生時代。
去年の12月半ばに、初心者にも理解しやすいプログラミング言語がある中、何を思ったか

お堅い言語で何か作れるのカッコよくね?
という風に考えた。
そして、その代表格であるC言語を選ぶのであった。
ちなみにコンパイラはgccを使った(余談だが、vimのプラグインでquickrunというものがあって「:QuickRun」と打つだけで実行できたのでかなり便利)。
次いで、開発環境の選択(これが後に首を絞めるのは知る由もない)。
僕は以前までWindows7ユーザーだったが、2020年の1月にサポートが終了することは前もって把握していたため、1年以上前からLinuxに乗り換えて人生を謳歌していた。
いくつかのディストリビューションを利用し、自分好みのOSを模索中だったこともあって、当初は比較的情報量の少ない「Manjaro」を使っていた。

ArchもGentooも使えん!
何かインスコする際にはpacmanを使い、特に不備なく生活していたのであった。
(なお、現在のメインはWin10である)
待っていた落とし穴
そして前述の開発環境で作ろうとしたのはご名答、テトリスだ。
しかし落とし穴があり、先ず一つは「DXライブラリ」を使用できなかったということだ。
Xubuntu(Ubuntu)等でDxLibを使う方法はあるようだが、如何せん情報量の少ないManjaro。
そして二つ目に「仮想環境」が使えなかったということ。
manjaro上でWindows10を構築する目論見で、彼の有名なVirtualBoxやVMwareなどをインスコしたが、起動と同時に謎のエラーが出て使用不可(治せる人が羨ましい)。
そして(自身の力量の兼ね合いにより)答えは必然的に決まった。
コンソールテトリスを作ろう
だがしかし、問題しかなかった
そんな感じで僕は、「Linuxでのコンソールテトリス開発」を開始した。
様々なサイトや動画や書籍を参考にしつつ、基本的には
- ループ処理
- 配列
- 関数
という簡単な文法を駆使して作成した。
以下は、160行程度のソースコードとなっているが

俺、C言語とか苦手や・・・
という方でも理解しやすい文法なので是非ご覧いただきたい→https://github.com/xjaxvax/tetris/blob/master/tetris-vol1/tetris.cpp(汚くてすまん)
ご覧いただけただろうか?
そうなのだ。
途中なのだ。
詰んだのだ。
先ず、結論から申し上げると「kbhit」と「getch」が使えなかった。
それ以外は、代用できそうなものをインクルードして何とか使えたのだが、前述の関数に関してはどうしても難しかった。
参考サイトなどではどれもWindows向けに説明しており、kbhitとgetchに関しては代用が効かなかった。
調べてみたところ、自作している方が居たため参考にしてみたが、イマイチ理解できず詰んだ感じである。
参考元はこちら→https://hotnews8.net/programming/tricky-code/c-code03
挑戦者求む
是非、上記のコードから後を継いで下さる後継者の方が現れてくれると信じ、僕が解決した事を簡単に綴っておく。
画面のクリア
先ずは、ゲームオーバーした際などに画面をクリアする目的で使用したかった。「system(“cls”)」。
これは「stdlib.h」をインクルードしてwindowsで使うものであるため、僕の環境では使えなかった。
代わりに使ったのは「printf(“\x1b[2J”)」。
この謎の文字列で画面をクリアすることに成功した(結構調べてみると1996年に作成された記事などが出てきて、本当に使う人はいるのかと不安になった)。
ミノの落ちるスピード
続いて、ミノ(ブロックの名称)の落ちるスピードの指定。
「windows.h」をインクルードしてSleep関数を使う例がほとんどだが、Linuxでも使える「unistd.h」をインクルードした。
これで同じようにSleep関数を使えるようになるのだが、注意してほしいところは、unistd.hの場合「Sleep」ではなく「sleep」と先頭は小文字になるところ。
加えて、windows.hのSleepはミリ秒単位で処理を止めるのだが、unistd.hのsleepは1秒単位で止めるということに注意していただきたい。
conio.hはトラウマ
最後に、ソースコードに記述していないが、C言語で(キー入力必須の)ゲームを作ろうとなった際に必ずと言っていいほど登場してくる「conio.h」(今ではこいつを見ただけで体調悪くなる)。
まさに言わずもがなLinux勢最大の敵と言えるだろう。
代用は「curses.h」若しくは「ncurses.h」でOK(ちなみに、ncursesの頭文字nはnew(新しい)という意味だからこっちを使った方がいいらしい)。
出来たら連絡求む
とまぁ僕が解決できたのはこれくらいだった。
少しでも参考になり、後継者の方が調べる手間を省けていたらなと思う(後継ぎ出来るレベルの人には参考にならないな)。
もし挑戦してみて、出来てしまった方はTwitterにご連絡していただければ幸いだ。

みんな挑戦してみてくれ!
結局どうしたのか
前述通り僕は失敗したわけなのだが、何時間もコードを書いていたこともあって、引くに引けない状態の僕が取った行動は「ディストリビューションを変える」ことであった(仮想環境使えないから涙目)。
まぁ何に変えようか悩みに悩み夜もぐっすり眠れたのだが、結局情報量の多いUbuntuにした(なぜWindowsを選ばないのか自分でも謎)。
早速ISOイメージファイルを使いOS移行(どうせManjaro使わんしデュアルブートにはしなかった)。
そこでようやくVirtualBoxを使えるようになったため、Windows10での開発をすることにした(MinGWを使うのに少々苦労)。
その後は語るまでもなく簡単に進み、以下のようなコードとなった→https://github.com/xjaxvax/tetris/blob/master/tetris(%E5%AE%8C%E6%88%90%E7%89%88)/tetris.cpp
実行しているときに、画面がチカチカしてしまうことに関しての対処方法は解りかねるが、粗方コンソールテトリスと言われるものが出来たのではないかと思う。
このようにOSを変えたら苦労することは無くなったが、Linuxでの開発をする場合だと、僕みたいに力量不足だと痛い目を見るだろう(そもそもコンソールでゲームを作る自体本当に時代遅れな気はする)。
確実にDxLibを使用した開発のほうが生産性や将来性があると思うため、今回のような中規模なゲーム開発はWindows一択だなと痛感した。
最後に
大分長い話になってしまったが、ご覧いただきありがとうございました。
今後似たようなコンソールゲームを制作する機会があったら、改めて記事にしようと思うが、ぜひ皆さんにも挑戦していただきたい。
それではまた会おう。