12/20/2019

すべてのプログラマーが試すべき挑戦的なプロジェクト

Austin Z. Henleyのブログより

更新12/14: この投稿は、Hacker NewsRedditに関する多くの議論に拍車をかけました。 提案されたプロジェクトのいくつかを収集し、この投稿の最後にリストに入れました。

私は、多くの場合、サイドプロジェクトを開始したいが、何を構築すべきかわからない多くの学生やプロの開発者と話します。以下は、私に多くを教えてくれたいくつかのソフトウェアプロジェクトです。実際、それらは何度も作成でき、毎回新しいことを学ぶことができるので素晴らしいです。従って、何を構築するのか分からない場合、または新しいプログラミング言語またはフレームワークを学びたい場合は、次のいずれかから始めます。

  • テキストエディタ
  • 2Dゲーム - スペースインベーダー
  • コンパイラ - Tiny BASIC
  • ミニ・オペレーティング・システム
  • スプレッドシート (難しい!)
  • ビデオゲームコンソールエミュレータ (難しい!)

テキストエディタ

私たちは毎日テキストエディタを使っていますが、実際にどのように機能するかを知っていますか? お気に入りのエディターにあるすべての機能を無視して、移動可能なテキストカーソルとテキストの選択、挿入、削除をサポートするテキストボックスをどのように実装しますか? いいえ、お気に入りのGUIフレームワークから組み込みのテキストボックスコンポーネントを使用することはできません!

最大の課題は、テキストドキュメントをメモリに保存する方法を見つけることです。最初に考えたのは配列を使用することでしたが、ユーザーがドキュメントの最後以外の場所にテキストを挿入すると、パフォーマンスが最悪になります。幸いなことに、これを解決するために学ぶべきいくつかの素晴らしいデータ構造があります。

別のハードルは、一般的なエディターでテキストカーソルがどのように動作するかを学習することでした。例えば、ドキュメントの中央にカーソルがある状態で上矢印キーを押すと、カーソルはどこに移動しますか? 同じ列? その行が短い場合ではありません。 押し続けます。行が十分に長くなると、カーソルは元の列に戻ります。カーソルには列のメモリがあり、そこに戻ろうとしていることが分かります。実装しようとするまで気がつかなかったのは、これらの詳細です。

基本的なエディターを実装した後、元に戻す/やり直しとワードラッピングの2つの機能を実装することに挑戦します。元に戻す/やり直しを効率的な方法で実装することは、私にとって非常に頭が痛いことでした! 私は最初に以前の状態の配列を保持しようとし、次にMementoパターンを試し、最終的にCommandパターンに落ち着きました。ワードラッピングを使用すると、テキスト行の視覚的な側面とメモリの側面を分離する必要があります。

学ぶべきこと:

参考文献:

  • テキストエディター: データ構造(web)
  • Win32テキストエディターの設計と実装(web)
  • Javaのデータ構造とアルゴリズム(Amazon)

2Dゲーム - スペースインベーダー

最も単純なゲームでさえ、いくつかのユニークなデータ構造とデザインパターンを必要とします。ここでのアイデアは、他の楽しいもの(ゲームデザインやアートなど)にとらわれずに、最初から最後まで明確に定義されたゲームを実装することです。また、すべての興味深い部分を隠す大きなゲームエンジンではなく、ベアボーンの2Dグラフィックライブラリ(SDL、SFML、PyGameなど)を使用するのが最適です。

第一に、画面に描画することを学ぶ必要があります。私はこれがどのように機能するか見当がつきませんでした。実際に画面をクリアしてから、画面の各部分を1秒間に何回も高速で連続して描画し、オブジェクトが動いている効果を作成しました。

第二に、ゲームループのすべてを学習します。ゲームは、描画、ユーザー入力の取得、およびゲームロジックの処理の間で効果的にループしています。

第三に、ユーザー入力を処理する方法を学びます。これまで、最初にキーやマウスボタンを押したり、押し続けたり、放したりすることの繊細さに注意を払ったことはありません。そして、どのくらいの頻度でユーザー入力をチェックしますか? 常にチェックしていると、それはゲームのその他の部分がフリーズしていることを意味します!

第四に、すべてのゲームオブジェクトとその状態を作成および管理する方法を学びます。例えば、動的な数の敵をどのように生成しますか? 工場出荷時のパターンは非常に役立ちます。

五番目に、ゲームのロジックを適用する方法を学びます。弾丸の位置はいつ更新されますか? より多くの敵が画面に現れるのはいつですか? 敵がいつ破壊されるかをどのようにして知るのですか? ゲームオーバーはいつですか? ゲームを作成する前にモジュロ演算子を使用したことはありませんでしたが、ゲームのコード全体に散らばっています。

基本的なゲームが機能するようになったら、タイトルスクリーンメニュー、ゲームオーバースクリーンを追加し、異なるコンピューターでもゲームが同じ速度で実行されることを確認し、AIでより興味深い敵を実装する方法を探ります。まだ足りない? それでは、シェーダーエフェクト、サウンド、オンラインマルチプレイヤーを追加して下さい!

学ぶべきこと:

  • 画面への描画
  • ユーザー入力の処理
  • ゲームループ
  • 動的な数のオブジェクト(ファクトリーパターンなど)の作成と管理
  • 敵AIの状態機械
  • サウンドの再生
  • シェーダーの使用
  • オンライン機能のネットワーキング

参考文献:

  • Game Programming Patterns (Amazon, web)
  • Data Structures for Game Programmers (Amazon)
  • Programming Game AI by Example (Amazon)
  • The 8 lessons I learned from releasing 8 video games (web)

コンパイラ - Tiny BASIC

私が取り組んだ最も目を見張るプロジェクトはコンパイラです。今でも、日曜日の午後に自由にコーディングを行うことができれば、コンパイラーである可能性があります。他の人がより多くのものを生み出す事ができる何か作成するとき、それは素晴らしい気持ちになります。実装することで、通常は考えられないほど複雑なコンパイラーについてさらに学ぶ必要がありました(例えば、式が暗黙的に型変換される場合)。

非常に小さなBASICに似た言語(Tiny BASICを参照)のコンパイラをゼロから作成し、よく知られている他の言語にコンパイルすることをお勧めします。例えば、PythonでC#コードを出力するTiny BASICコンパイラを作成できます。アセンブリまたはCを出力する必要はありません! これらを回避することで、コンパイラ自体に集中できます。

最初のハードルは、入力コードをlex(またはトークン化)する方法を考え出すことです。次に、コードを解析します。つまり、入力の構造を確認し、コードのツリー表現を生成します。再帰降下解析のテクニックは美しいです! 次に、入力を意味的にチェックし、コードが意味を成し、タイプルールが守られていることを確認します。最後に、出力を生成できます!

このプロジェクトには、あなたを支援する既存のリソースが大量にあり、簡単なコンパイラーは数日で完成します。専門用語に怖気付かないで下さい。さらに、可能性はあなたが追加できるものに無限です! 基本的なコンパイラが動作したら、標準ライブラリ(PeayBASICで簡単な2Dグラフィック機能を追加しました)、最適化パスを追加し、エラーメッセージを改善できます。最後に、世界に誇示するためにあなた自身の言語でいくつかのサンプルプログラムを書くべきです!

学ぶべきこと:

参考文献:

  • Crafting Interpreters (web)
  • Write an Interpreter in Go (Amazon)
  • Let's Build a Compiler (web)
  • PeayBASIC source code (GitHub)

ミニオペレーティングシステム

長年にわたって、オペレーティングシステムの基本的な概念を、ゲームや人間の行動の予測モデルなどの様々なドメインに適用していることに気付きました。教室では、オペレーティングシステムで使用されるアルゴリズムとデータ構造は抽象的または役に立たないように見えるかもしれませんが、それらは本当に便利です。また、オペレーティングシステムを実装することで、内部で何が起こっているのかをより深く理解することができました。

ハードウェアに依存しているため、少し学習曲線と開始するためのいくつかの障壁があります。ただし、本またはチュートリアルに従うことで、独自のプログラムを実行できる起動可能なOSを動作させることができます。Rustを使用してRISC-Vオペレーティングシステムを作成する同僚の無料オンラインブックを強くお勧めします。

学ぶべきこと:

参考文献:

  • OSDev.org's wiki of resources (web)
  • Making a RISC-V Operating System using Rust (web)
  • Operating System Concepts (Amazon)

それでもあなたにとって難しいことではありませんか? 次の2つのプロジェクトを試して下さい。

スプレッドシート

Excelのようなスプレッドシートアプリケーションは、テキストエディターの課題とコンパイラーの課題を組み合わせています。メモリ内のセルの内容を表現する方法を学び、方程式に使用されるプログラミング言語のインタープリターを実装する必要があります。

参考文献:

  • 有向非巡回グラフ (web)
  • Reactive programming paradigm (web)
  • Spreadsheet Implementation Technology (Amazon)

ビデオゲームコンソールエミュレータ

ビデオゲームコンソール用のエミュレーター(または仮想マシン)を記述すると、コンパイラ、オペレーティングシステム、およびコンパイラをすべて1つに記述するという課題が組み合わされます。エミュレータを使って他の人が作った本物のゲームをプレイするのはとてもやりがいがあります!

実際のビデオゲームコンソールをエミュレートするということは、実際のCPUやその他のハードウェアコンポーネントのように機能するふりをする仮想マシンを作成することを意味します。これにより、ビデオゲームコンソール用に設計されたゲームをエミュレータで実行できます。

実際のビデオゲームコンソールに移る前に、シンプルで架空のコンソールであるCHIP-8をエミュレートすることから始めることをお勧めします。NES、SNES、Gameboy、およびGameboy Advanceはすべて、エミュレートするのに非常に適しています。既に多くのドキュメントとオープンソースエミュレータがありますが、それぞれに物事を面白くする独自の癖があります(例えば、特定のゲームは特定のハードウェアの文書化されていないバグ/機能に依存する場合があります)。PICO-8もあり、非常に収益性の高い「ファンタジー」コンソールになりました。

参考文献:

  • Writing a Chip-8 emulator (web)
  • JavaScript Chip-8 Emulator (web)
  • How to Emulate a Game Boy (web)
  • PyBoy source code (GitHub)

他にプロジェクトのアイデアがあれば教えて下さい! 以下は、Hacker NewsReddit、Twitter、および私が受け取ったメールからの提案のリストです。

  • データベースをスクラッチで作成
  • レイトレーサー
  • MSペイントクローン
  • ベクターグラフィックエディター
  • 画像デコーダー
  • チャットルームWebアプリ
  • 円周率計算機
  • 一般的な端末ユーティリティ(grepなど)
  • FTPクライアントおよびサーバ