python-study

Python を一から学びながら作った小さなプログラムを、ブラウザでそのまま遊べる形で置いています。

g01数当てゲーム

1〜100 の数字を 7 回以内に当てる。二分探索を使えば必ず勝てます。

whileif / elif / elsetry / exceptf-stringwhile-else

g02じゃんけん

コンピュータと何度でも勝負。勝ち負けのルールは辞書1つで表しています。

listdictdef / returnbreak / continue

g03タイピングゲーム

表示された文章を 5 問打つ。正解数と「1 秒あたり何文字」が出ます。

forrandom.shuffletimedict のリスト

g04テトリス

矢印キーで操作します。落ちる・回す・そろった列を消す、を Python で書いています。

2次元リストリスト内包表記zip と転置タプル

g05オセロ

挟んでひっくり返す 8×8 の盤。白をコンピュータに任せることもできます。

8方向の探索タプルをキーにした辞書短絡評価chr / ord

g06マインスイーパ

9×9 に地雷が 10 個。0 のマスを開くと周りが連鎖して開きます。最初の一手では爆発しません。

set再帰関数random.sampleジェネレータ式

g07シューティング

左右に動いて弾を撃ち、18 個の的を落とします。自機・弾・的をそれぞれクラスで書いています。

class__init__ / selfメソッドオブジェクトのリスト

g08敵の編隊

左右に動きながら降りてくる 21 体を落とします。紫の敵は 2 発必要。共通部分は親クラスにまとめました。

継承super()メソッドの上書きclass Game

g09スペースインベーダー

撃ち返してくる 21 体を、バリアに隠れながら落とします。自機は 3 機。ハイスコアはブラウザに残ります。

クラス変数関数の一般化any()ファイル入出力

g10五目ならべ

15×15 の碁盤で先に 5 個そろえたら勝ち。CPU は石の「形」を読んで、あなたの 3 を止めに来ます。

ジェネレータ yieldlambdadefaultdict辞書内包表記

g11ブラックジャック

ディーラーと 21 を競います。ダブルダウンあり、ブラックジャックは 1.5 倍。チップはブラウザに残ります。

dataclassEnum@propertymatch 文

g12迷路

穴掘り法で作った迷路を矢印キーで歩きます。ヒントは BFS の最短路から。大きさは 15 / 21 / 31。

再帰のバックトラックdeque と BFS@contextmanagerargparse

g13迷路レース

深さ優先で「実際に歩く」ロボットと競走します。DFS・BFS・A* がどう探すかを 1 歩ずつ見るボタンつき。

再帰 → スタック探索をジェネレータにheapq と A*perf_counter

g14ブロック崩し

パドルでボールを打ち返して 40 個のブロックを壊します。端に当てるほど横に飛び、壊すほど速くなる。

演算子オーバーロード__abs__ / __iter__float の物理time.monotonic と dt

g15ピンボール

右のレーンから打ち出してバンパーを狙います。重力と斜めの壁の反射を Python で計算。フリッパーで打ち返す。

math.sin / cos / radians__matmul__ で内積法線での反射重力とサブステップ

g16宇宙船

慣性で滑る船を回転と加速だけで操り、星の引力に引かれながら 5 つのリングをくぐるタイムアタック。

complex を 2D ベクトルにcmath.rect / phase小数の %0.5 ** (dt / 半減期)

g17小惑星

宇宙船で小惑星を弾で砕きます。撃つと 2 つに割れ、全部砕くと次のウェーブ。船は 3 機。

abc と @abstractmethodsuper().update(dt)円と円の当たり判定random.gauss

g18ランキング

小惑星の得点を名前つきで残して上位 10 件を並べます。CLI 版は sqlite3、ブラウザは localStorage。

sqlite3datetimepathlibunicodedata で全角の幅

g19ダンジョン

部屋と廊下をランダムに作り、霧の中を歩いて階段を探すローグライク。地下 5 階でクリア。

__contains__itertools.combinationsBFS で到達を確かめる集合の和 |=

g20モンスター

ダンジョンに敵。見えている敵が追ってきて噛みつきます。体当たりで攻撃、へびは毒、オークは硬い。

enum.Flagrandom.choices(weights=)ブレゼンハムの線BFS の次の 1 歩

g21アイテムとセーブ

床に落ちている薬草・剣・鎧を拾って使います。セーブして、次に開いたときは続きから。

typing.Protocolpicklelogging@classmethod

g22チェス

盤と駒の動き。クリックで選んで、クリックで指す。相手のキングを取ったら勝ち。黒はランダムに指す CPU。

NamedTuple__getitem__ / __setitem____iter__FEN

g23チェスのルール

チェック・キャスリング・アンパッサン・成り。合法手だけ指せて、チェックメイトかステイルメイトで終わります。

@dataclass の __hash__dataclasses.replacecached_propertyperft

g24チェスの終局

千日手・50 手ルール・駒不足の引き分けまで。これでルールは全部。perft と unittest で検証済み。

unittestfunctools.lru_cachecollections.Counterfield(compare=False)

g25チェスの CPU

先読みする CPU と対戦。評価関数で採点し、ミニマックスと αβ 枝刈りで読み、1 秒の持ち時間で深さを増やします。

ミニマックス(negamax)αβ 枝刈りmath.inf反復深化と例外

g26チェスの棋譜

指した手が SAN の棋譜になり、PGN で保存・貼り付けて再現。5 段階のチェスの完成形。

re(名前付きグループ)SAN / PGNtextwrap.fill@classmethod from_pgn

g27冒険

夜の洋館を歩いて出口を探すテキストアドベンチャー。部屋・方角・地図。5 段階の 1 つ目。

enum.StrEnumtextwrap__str__ と __repr__dataclass の field

g28コマンド解析

「look at the 燭台」のような文を分解して受ける。言い換えは同じ動詞に、打ち間違いは「もしかして」。

shlex.splitdifflib.get_close_matchesNamedTuple と match逆引き辞書

g29アイテムと仕掛け

鍵を見つけ、扉を開け、窓をこじ開けて脱出。仕掛けはクロージャ・partial・__call__、動詞は自作デコレータで登録。

自作デコレータクロージャと nonlocalfunctools.partial__call__

g30シナリオ

世界を TOML ファイルで。洋館と洞窟の 2 つを同じプログラムで遊ぶ。読めないファイルはどこが悪いかを文で。

tomllib自作例外と raise from__getattr__pathlib.glob

g31セーブと自動テスト

コマンドの記録をセーブして続きから。SHA-256 の指紋で改ざんを見つける。攻略ファイルと doctest で自動テスト。5 段階の完成形。

hashlibzipfiledoctestio.StringIO と redirect_stdout

g32ギャラガ風(自機とスプライト)

多色ドット絵の自機と敵、星の流れる背景。PNG を Python で組み立てて canvas に貼る。5 段階の 1 つ目。

ドット絵をパレット+文字列でトゥルーカラー ANSI と ▀struct + zlib で PNGitertools.cycle

g33ギャラガ風(入場曲線と編隊)

敵がベジェ曲線を描いて飛来し、席に着き、編隊が呼吸する。5 段階の 2 つ目。

ベジェ曲線(math.comb)ジェネレータでパスitertools.chainmath.sin の呼吸

g34ギャラガ風(急降下と敵の弾)

席の敵が状態機械で自機めがけて急降下し、弾を撃ってくる。残機 3。5 段階の 3 つ目。

IntEnum の状態機械match 文random.choices の重み残機と復活

g35ギャラガ風(ボスと牽引ビーム)

ボスが降りてきてビームで自機を捕まえる。救出するとデュアルファイター。5 段階の 4 つ目。

send() でコルーチンheapq のタイムライン__post_init__描く先を差し替える

g36ギャラガ風(ステージと演出)

次々ステージ、3 の倍数は虹色のチャレンジングステージ。スコア表は CSV。5 段階の完成。

colorsyscsv と dataclasslocalStorage に CSV@property で難度

g37将棋(盤と駒の動き)

成り・持ち駒・打つ。相手の玉を取ったら勝ち。後手はランダム CPU。将棋 6 段階の 1 つ目。

IntFlag__slots__itertools.productstr.maketransSFEN / USI

g38将棋(反則と終局)

王手放置・二歩・打ち歩詰めを外した本物のルール。詰み・千日手・連続王手で終わる。将棋 6 段階の 2 つ目。

contextmanagerZobrist ハッシュcollections.dequeassertperft 719731

g39将棋(詰将棋)

王手を続けて玉を詰ませる。受け方は最も粘る手、次の一手のヒント付き。1〜5 手詰 8 題。将棋 6 段階の 3 つ目。

再帰ジェネレータ(yield)dataclass(slots=True)itertools.islicetime.perf_counter自作例外で上限

g40将棋(詰将棋 df-pn)

証明数・反証数で「解けそうな所」から掘り、置換表で同じ局面を省く。7 手詰まで 11 題。将棋 6 段階の 4 つ目。

df-pn置換表 dictmath.infitertools.countoperator.itemgetter

g41将棋(CPU)

駒割りの評価と αβ 探索で先読みする CPU。取る手とキラームーブを先に読み、反復深化と時間制限。将棋 6 段階の 5 つ目。

arrayαβ(ネガマックス)MVV-LVA とキラームーブ反復深化と TimeUpcProfile / pstats

g42将棋(棋譜)

日本語の表記で指し、KIF を書いて読み戻し、途中から再開、zip の棋譜集。将棋 6 段階の完成形。

re.VERBOSE と名前付きグループunicodedata.normalizeKIFjsonzipfile
<

g43グラディウス風(自機と横スクロール)

上下の地形が流れる洞窟を飛ぶ。地形に触れると撃墜、先へ行くほど狭い。グラディウス風 6 段階の 1 つ目。

itertools.pairwisebisecttyping.Protocol横スクロールと視差
f

g44グラディウス風(敵の出現)

出現表に沿ってファン・ガルン・ダッカー・砲台が出る。正面の敵は撃ち落とし、弾はよける。グラディウス風 6 段階の 2 つ目。

enum.autodataclass(kw_only=True)functools.partialitertools.groupbymath.atan2
o

g45グラディウス風(パワーアップ)

カプセルでゲージが進み、選んで発動。スピード・ミサイル・ダブル・レーザー・シールド。グラディウス風 6 段階の 3 つ目。

abc.ABC / abstractmethodfunctools.singledispatchEnum の順送りisinstance で振る舞い

g46グラディウス風(オプション)

自機の軌跡を少し遅れてたどる分身。最大 4 つ、同じ武器を撃つ。赤い敵は必ずカプセルを落とす。グラディウス風 6 段階の 4 つ目。

array のリングバッファ__len__ / __iter__math.distfunctools.cache

g47グラディウス風(ビッグコア)

ステージの終わりに足止めするボス。4 枚のバリアの奥のコアを撃つ。揺れる狙い、撃破の演出。グラディウス風 6 段階の 5 つ目。

enum.Flagrandom.gausscontextlib.suppressEnum で段階

g48グラディウス風(ステージと難度)

砂漠・火山・要塞の 3 面を TOML の表で。ボスを倒すと次の面、3 面抜けると 2 周目で速くなる。グラディウス風 6 段階の完成。

tomllibfunctools.reduceloggingargparse サブコマンド

g49イー・アル・カンフー風(舞台と格闘家)

2 人の格闘家。歩く・跳ぶ・しゃがむ、向きは相手の方へ、押し合い、体力バー。イー・アル・カンフー風 6 段階の 1 つ目。

match 文typing.Literaldataclasses.replaceproperty の setter

g50イー・アル・カンフー風(技と当たり判定)

パンチ・キック・しゃがみパンチ・跳び蹴り。攻撃ボックスが相手の体に重なればダメージと硬直。イー・アル・カンフー風 6 段階の 2 つ目。

itertools.accumulate__next__ の自作イテレータfunctools.wrapsfrozen dataclass の技の表

g51イー・アル・カンフー風(最初の敵ワンと AI)

間合いで行動に点を付けて選ぶ AI。こちらの技に遅れて気づいてよける。難度 3 段階を自動対戦の統計で調整。イー・アル・カンフー風 6 段階の 3 つ目。

collections.ChainMapdataclass(order=True)statistics?level=hard

g52イー・アル・カンフー風(武器の敵)

タオの火の玉、チェンの鎖、ランの手裏剣、飛ぶムー。敵の動きは yield from でつないだ台本。イー・アル・カンフー風 6 段階の 4 つ目。

yield from の台本typing.Generic / TypeVarTypedDict?enemy=tao

g53イー・アル・カンフー風(対戦の流れ)

60 秒のラウンドを 2 本先取、5 人連戦、コンティニュー、結果の表。イー・アル・カンフー風 6 段階の 5 つ目。

functools.total_ordering__format__datetime.timedelta__enter__ / __exit__

g54イー・アル・カンフー風(リプレイと記録)

毎コマの入力を記録して、同じ試合をそのまま再生。巻き戻しの練習モード、記録の保存。イー・アル・カンフー風 6 段階の完成。

__set_name__ の記述子copy.deepcopyitertools.zip_longestshelve

g55パックマン風(迷路とパックマン)

21×13 の迷路を走り、124 個のエサを全部食べたらクリア。曲がれない向きは覚えておく先行入力、左右のトンネル。パックマン風 6 段階の 1 つ目。

collections.abc.Mappingtyping.Selfzip(strict=True)itertools.takewhile

g56パックマン風(4 体のおばけ)

赤・桃・水・橙が 1 体ずつ違う狙い方で追ってくる。散らばりと追いかけを時間割で切り替え、そのたびに反転。パックマン風 6 段階の 2 つ目。

__init_subclass__typing.ClassVartyping.assert_neveraccumulate + bisect

g57パックマン風(パワーエサとイジケ)

パワーエサでおばけが青くなって逃げ、捕まえると 200・400・800・1600 点。目玉だけになって巣へ帰る。パックマン風 6 段階の 3 つ目。

type 文(PEP 695)singledispatchmethodtyping.Finalassert_never の回収

g58パックマン風(ステージと果物)

全部食べると次の面へ。面が進むとおばけが速くなりイジケが短くなる。途中に出る果物はボーナス。パックマン風 6 段階の 4 つ目。

fractions.Fractioncollections.abc.Sequenceitertools.repeat + chainregister を 1 つ足す

g59パックマン風(演出とアトラクトモード)

放っておくとデモが流れ、キーを押すと始まる。READY! の間、捕まって消える動き、面クリアの点滅。パックマン風 6 段階の 5 つ目。

_generate_next_value_functools.partialmethodmath.atan2 で絵を作る3×5 の英字フォント

g60パックマン風(記録と分析)

遊んだ結果が残り、得点の散らばり・到達した面・どのおばけに捕まったかを振り返れる。パックマン風 6 段階の完成。

collections.abc.MutableMappingstatistics.quantilesdataclasses.astuple + fieldsoperator.attrgetter

g61推理ゲーム風(現場と聞き込み)

コマンド選択式の推理もの。街を回って調べ、人に聞き、手がかりを集める。手がかりが揃うと聞ける話が増える(事件はオリジナル)。

collections.abc.Settyping.NewTypedataclasses.KW_ONLYstring.Template

g62推理ゲーム風(推理ノートと手がかりの地図)

一度見た選択肢は消えるので残りが一目で分かる。集めた手がかりは層に並べた図に。事件が詰まないかも機械で確かめる。

graphlib.TopologicalSorterprepare / get_ready で層にgraphlib.CycleErroritertools.filterfalse

g63推理ゲーム風(証言の矛盾と告発)

食い違う 2 つの証言を突きつけて言い直させ、最後に犯人・手口・動機を指名して採点。推理もの 3 段階の完成。

copy.replace(3.13)field(metadata=)fields() から画面と採点矛盾の判定

g64物理の積み木(剛体の箱)

重力・跳ね返り・摩擦・回転を自分で書いた物理エンジン。落ちて弾んで転がり、止まると眠って完全に静止します。

複素数で剛体撃力で跳ね返すクーロン摩擦眠らせる固定の刻み幅

g65物理の積み木(箱どうしの衝突)

分離軸で重なりを見つけ、撃力で押し返す。箱が積めるようになったので、塔を建てて重い塊で崩せます。

分離軸法(SAT)typing.NamedTuplemath.inf の質量撃力の 2 体版dataclass(slots=True)

g66物理の積み木(パチンコで崩す)

自分で書いた物理エンジンで遊ぶ。石を撃って積み木を崩し、標的を割って得点。面は 3 つ、記録はブラウザに残ります。

enum.IntEnumitertools.groupbybisect.insortcontextlib.suppressdeepcopy で先を読む

g67倉庫のロボット(自作ミニ言語)

自分で作った小さな言葉でロボットに命令し、荷物を棚まで運ぶ。書き間違いは行と桁と ^ で教えてくれます。

re.finditer と名前付きの枠位置を持つ Token自作の例外に報告を書かせるジェネレータで 1 コマずつ

g68倉庫のロボット2(繰り返しと条件)

repeat と if と while を足した自作ミニ言語。書いたプログラムの構文木が画面に出ます。

再帰下降パーサfunctools.singledispatchtextwrap.indentExceptionGroup と except*

g69倉庫のロボット3(変数と手順)

変数と手順(関数)を足した自作ミニ言語の完成形。ChainMap でスコープを作り、再帰も書けます。

collections.ChainMapoperator の関数を表に実行時エラーの分離再帰と深さの見張り

g70街づくり(土地と道)

土地に道と建物を置いて街を作る。道でつながった建物が「区画」になり、離れた建物には赤い枠が付きます。

enum.Flagtyping.Literaldecimal.Decimal幅優先で区画を見つける

g71街づくり2(需給と人口と災害)

月が進むと資源が配られ、満ち足りた家に人が入る。火事と洪水も起きます。30 か月で人口 60 人が目標。

heapq.mergemath.prod災害の乱数を分けるDecimal の収支

g72街づくり3(季節と備えと記録)

季節が巡り、消防署と堤防が災害を止め、街の歩みが毎月 1 行の記録に残ります。

itertools.cyclecsv.DictWriterio.StringIO決まりを機械に確かめさせる

g73耳コピ1(音を作る)

流れた旋律を聞いて、25 鍵のピアノで同じ音を打ち込みます。どの高さから弾いても正解。童謡・唱歌 47 曲、音は正弦波から Python で作っています。

arraywaveio.BytesIO平均律

g74耳コピ2(楽器を選ぶ)

耳コピを、ピアノ・エレクトーン・ギター・ベース・木琴から楽器を選んで。弦の音は雑音を遅らせて平均するだけで作れます。

TypeAliasfunctools.reducedeque(maxlen=)Karplus-Strong

g75タイピング1(キーボードと指)

ブラインドタッチの練習。JIS 配列のキーボードに、次に押すキーとどの指で押すかが出ます。ホームポジションから段階を踏みます。

絵のもとを表で共有enum.Enumstatistics.fmeanrandom.Random(種)

g76タイピング2(ローマ字で日本語)

「さくら」を sakura と。shi/si、n/nn、っ のような綴りのゆれは全部受け付けます。ことばから文へ。

状態の集合で判定re.sub に関数str.removeprefixitertools.product

g77タイピング3(記録と苦手キー)

記録が残り、自己ベストといつもの速さが出ます。苦手なキーを含むことばが多めに出る練習も。

dataclasses.asdictrandom.choices(weights=)heapq.nlargestdatetime.fromisoformat

g78小惑星をよける(3D)

宇宙船の後ろから見た視点で、迫ってくる小惑星をよけます。3D は透視投影・回転・隠面消去・陰影を自分で書きました。

透視投影外積で法線画家のアルゴリズムスキャンライン

g793D レース

曲がって上下する周回コースを、CPU カー 3 台と 3 周で競います。車の向きで回るカメラ、視点をまたぐ多角形を切るニアクリッピング、曲線から作る道を自分で書きました。

カメラの回転ニアクリッピングCatmull-Rombisect

g80クレー射撃

放出機から飛ぶ皿を散弾銃で撃ちます。上下左右に回るカメラ、皿の放物線、円錐に広がる散弾の当たり判定、弾が届く時刻の位置を狙う先読みを自分で書きました。

yaw と pitch放物線円錐の当たり判定先読み