feature image

2026年3月22日 | ブログ記事

ヤケクソなタイピングゲームを作る

これは2023年10月に部内向けに書いたブログを外部公開向けに書き直したものです。

はじめに

こんにちは。koukawa_ppです。
さて、今回はヤケクソなタイピングゲームを作るというタイトルで、ブログを書きます。
開発言語はPythonです。

ここでは、以下のものを作ります。

また、コードは こちらの GitHub リポジトリ にて公開しております。

開発環境

作ることになったいきさつ

まずそもそもタイピングゲームとは、皆さんご存じの通り、ある文章を出され、それをいかに早く正確に打ち込めるかを楽しむゲームです。
まあでもタイピングゲームが得意な方なら、この手のシンプルなタイピングゲームはまあ瞬殺でしょう。
退屈していらっしゃるのではないでしょうか。
そうするとシンプルなタイピングゲームを作成するのは野暮というもの。

そのような中で、このタイピングゲームが得意な方でもタイプが遅くなるようなチャレンジングなタイピングゲームを作れないだろうか。
このような考えのもと、この企画を考えました。

ぶっちゃけて言うと、正道では対抗できそうにありません。
そこで、何か普通のタイピングゲームより難しい何か、を作ることを考えました。

ここで、以下のような工夫点を導入したタイピングゲームを作りました。

まず最初の要素によって、「このような組み合わせはよく出てくるな」や、打ちなれているキーだけでできるタイピングゲームを排除します。
次に、特殊文字を入れることにより、あたかも複雑なパスワードを入力しているように感じさせます。
これら二つの要素は、ひょっとするとどこかのタイピングゲームにあるかもしれませんが、最後の要素を導入することで、多分他にはないタイピングゲームを完成させました。
最後の「シーザー暗号を導入する」とは、以下のようなものです。

eznoafowe (2)

とあったら、これら各々の文字を2つ後ろにずらして入力する必要があるということです。
つまりこの場合は、

gbpqchqyg

と入力する必要があるわけです。
つまりこのタイピングゲームは、タイピング速度もそこそこに、アルファベットの順番を即座にずらせることも求めたものなのです。

ゲームで遊ぶ

venv を作成する

まず、今回のプログラムでは pyyaml というサードパーティ製ライブラリが必要ですので、それをインストールする仮想環境 (venv) を用意します。

今回は typing_env という名称の仮想環境を作ります。

python -m venv typing_env

そしてこれを起動します。

./typing_env/Scripts/activate

もし Linux や、または macOS もそうだったと思うのですがその場合は、

source typing_env/bin/activate

とする必要があります。


そうすると、このような感じになります。

(typing_env) PS [directory name]

環境をアクティベートしたら、pip でライブラリをインストールします。

pip install pyyaml

これでいったん仮想環境は完成です。

configファイルを作成する

では次に、conffigファイルを作成します。
configファイルはyamlファイルで提供しており、この内容を変えることでゲームの設定を変えることができます。

game_config.yamlnum_problems: 10
min_chars_length: 20
max_chars_length: 30

contain_capital_char: true
contain_number: false

# If you want problems to contain special char, you have to set.
# Otherwise, set null
contain_special_char:
  - null

caesar: 0
random_caesar: false
not_negative: true

初期設定としてはこんな感じだと思います。
各々について説明します。

名前 初期値 説明
num_problems 10 問題数を表します。
min_chars_length 20 問題の最小文字数を表します。
max_chars_length 30 問題の最大文字数を表します。
contain_capital_char true 問題にアルファベット大文字を含むかを表します。
contain_number false 問題に算用数字を含むかを表します。
contain_special_char null 問題に含む特殊文字を、リスト形式で表してください。
caesar 0 シーザー暗号において、何文字ずらすかの最大値を表します。0の場合はシーザー暗号形式の問題を出題しません。特殊文字を入れたい場合は0に設定してください。
random_caesar false この値がtrueのとき、not_negativeの値によって何文字ずらすかの値の範囲を決定します。not_negativeがtrueなら、0以上caesar以下の値にして、not_negativeがfalseなら、-caesar以上caesar以下の値で文字をずらします。
not_negative true random_caesarの説明の通りです。

この部分を変更して、遊んでみてください。

実際に動かす

では、以下のようにしてプログラムを実行してください。

python yakekuso_typing.py

そうすると、始まります。

(typing_env) PS [directory name]> python .\yakekuso_typing.py
press Enter to start. 
1   onEhBqIsdDbxGLcskUThOiK
>>> onEhBqIsdDbxGLcskUThOiK
2   DqxMHGXdneoacvZBmqQuUkuKmw
>>> DqxMHGXdneoacvZBmqQuUkuKmw
3   GnlJjOpBsiHxAdYsrObjLCxVFUpc
>>> GnlJjOpBsiHxAdYsrObjLCxVFUpc
4   cLXctVjCSZPehUEPBmPmGeUiXH
>>> cLXctVjCSZPehUEPBmPmGeUiXH
5   RXnkbMTSGvuDVoyyZLZqilL
>>> RXnkbMTSGvuDVoyyZLZqilL
6   FKuUavxxRPTRhKybsdtmJ
>>> FKuUavxxRPTRhKybsdtmJ
7   RrGVvVbYLgBrveHnIStyzuILto
>>> RrGVvVbYLgBrveHnIStyzuILto
8   YwMhVThewpHiJxZigwsJG
>>> YwMhVThewpHiJxZigwsJG
9   kRdaNZRnmMyRaXaQVIQINaf
>>> kRdaNZRnmMyRaXaQVIQINaf
10  faBdlXTMBGFJzicJWOLP
>>> faBdlXTMBGFJzicJWOLP

Spent time: 91.1295325756073
2.601 types per second.
(typing_env) PS [directory name]>

プレイにかかった時間はEnterを押してからカウントされるので、
準備ができたらEnterを押すという形でOKです。

シーザー暗号のパターンもできます。

game_config.yaml# omitted

caesar: 2
random_caesar: true
not_negative: true

このようにconfigファイルを変更して、実行してみてください。

(typing_env) PS [directory_name]> python .\yakekuso_typing.py
press Enter to start. 
1   QXXORCCWKlKtThBSQOquYSQAfZYW (1)
>>> RYYPSDDXLmLuUiCTRPrvZTRBgAZX
2   TmSKfJbZUCxpvJlBnFMPdJTrkm (2)
>>> VoUMhLdBWEzrxLnDpHORfLVtmo
3   NtrQMpnVTwmgoGZADRPWddC (0)
>>> NtrQMpnVTwmgoGZADRPWddC 
4   DeyxfmYDWTWPherccZKvfYsLm (2)
>>> FgazhoAFYVYRjgteeBMxhAuNo
5   TuwjoLtzqhRtvbdQCRfolDUl (2)
>>> VwylqNvbsjTvxdfSEThqnFWn
6   cwZdDkVSbCJvNWfNbFEaiqxoS (2)
>>> eyBfFmXUdELxPYhPdHGckszqU
7   YllpIgYwwCoNXFNItGmIcx (1)
>>> ZmmqJhZxxDpOYGOJuHnJdy
8   dVPCvUpIvNYTuJhAUewG (1)
>>> eWQDwVqJwOZUvKiBVfxH
9   qmCwtKihENzegpBomAWrQzykzBhkLH (1)
>>> rnDxuLjiFOafhqCpnBXsRazlaCilMI
10  YIWRSszClsfPoeZYDpremakA (0)
>>> YIWRSszClsfPoeZYDpremakA

Spent time: 372.90026021003723
0.662 types per second.
(typing_env) PS [directory_name]>

なぜタイピングの問題10問で6分も掛けなければならないのか、という話ですが、これ相当難しいです。
日ごろから任意の英文について文字ずらしをしていれば出来たかもしれませんが、そんな毎日毎日暗号化したい英文なんて扱うわけがないですから。
(というか今シーザー暗号してもすぐバレる)
ただとりあえず、うまくシーザー暗号のように文字ずらしができていることが分かります。
ぜひいろいろなconfigにして、試してみてください。

TASツールを作る

さて、タイピングゲームとなれば、よく使われるのはTASツールです。
しかもオープンソースのタイピングゲームみたいなものですから、アルゴリズムも丸わかりです。
そうなると、最速でクリアしたいという感想が出てくるのは当たりまえです。
無論人力で最速を目指せればそれもすごいですが、TASツールを作るのもまた一つの手だと思います。

次のようなコードを作成しました。

tas_typing_game.py# Reference:
# https://qiita.com/HidKamiya/items/e192a55371a2961ca8a4#subprocesspopen%E3%81%AB%E3%82%88%E3%82%8B%E8%87%AA%E7%94%B1%E5%BA%A6%E3%81%AE%E9%AB%98%E3%81%84%E5%87%A6%E7%90%86

import re
import subprocess

from yakekuso_typing import caesar_encrypt

if __name__ == '__main__':
    p = subprocess.Popen(['typing_env/Scripts/python.exe', 'yakekuso_typing.py'],
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         encoding='utf8')

    p.stdin.write('\n')
    p.stdin.flush()
    while p.poll() is None:
        line = p.stdout.readline().strip()
        
        if re.search('press Enter to', line):
            p.stdin.write('\n')
            p.stdin.flush()
        elif re.search('Spent time', line) or re.search('types per second', line):
            print(line, flush=True)
            p.stdin.write('print()\n')
            p.stdin.flush()
        elif re.search('[0-9][0-9\s][0-9\s] (\S+) \([\-0-9]+\)', line):
            print(line, flush=True)
            m = re.search('([0-9][0-9\s][0-9\s]) (\S+) \(([\-0-9]+)\)', line)
            p.stdin.write(f'{caesar_encrypt(m.group(2), int(m.group(3)))}\n')
            p.stdin.flush()
        elif re.search('[0-9][0-9\s][0-9\s] (\S+)', line):
            print(line, flush=True)
            m = re.search('([0-9][0-9\s][0-9\s]) (\S+)', line)
            p.stdin.write(f'{m.group(2)}\n')
            p.stdin.flush()

今回は subprocess という標準ライブラリを使っています。
これを使うことで、このPythonプログラムを実行しながら、他のプログラムを別プロセスで実行できます。
また、reは、正規表現を扱うためのライブラリです。
Regular Expression の略です。
また、yakekuso_typing.pyからシーザー暗号で暗号化する関数をインポートしています。
ソースコードをそのまま保存しているので、簡単に再利用できます。

さて、実行においては yaml が必要なので、これまでと同様 typing_env 内で実行してください。

(typing_env) PS [directory name]> python .\tas_typing_game.py
>>> 1   vYfBBhgPBIrHEApzddZJlWO (2)
>>> 2   nycYSUdOjGrVYhNqKyzULNNQILz (1)
>>> 3   YwezVOGnscquhFrbFKFukvydOZgpVa (0)
>>> 4   DCVqjKxsgaVdDggsfxcPtYu (1)
>>> 5   CdKVamkVelTcJqYfBtOAUItzLEoAO (0)
>>> 6   dhAVcJTEbKLCChYDTvOGemH (0)
>>> 7   juIZbrkwWrZvBNBSagdYDvMI (2)
>>> 8   vCiGCzAVWGBASuJSQLWnGOiM (0)
>>> 9   DvUsENKbVrZdsoczGaVagEQIv (1)
>>> 10  BSJcmfjmvoEIuIygfmyaAnYkLZqdD (1)
Spent time: 0.00768733024597168
33431.633 types per second.
(typing_env) PS [directory_name]> 

こんな感じで出てきます。
平均して一秒あたり33431回ほどタイプしていることになっていることが分かります。

ちなみに configcaesar を0にしたとき、
tas_typing_game.pyは以下のような感じで実行できます。

(typing_env) PS [directory name]> python .\tas_typing_game.py
>>> 1   SgzxWXQVOAyJYDOJXXAWxh
>>> 2   tDevbinTnlfxSvSKmkptYYZ      
>>> 3   dnWLvBhusCwsmeBSXalSjVpircjoO
>>> 4   EdFNZcrsVoDZuxbKmltS
>>> 5   zFTmkzrpIWeRFwzMgtRsaAZi     
>>> 6   IRvROZVmKRyFhPMrlRqkuTmKwCFW 
>>> 7   VToRbXqNYizmRHMpomehdrTnhlH  
>>> 8   OHMSWCVhGPGqZsnPBuHtBU       
>>> 9   fXWJrPUMJECsvRlbxajwL        
>>> 10  lYgJSVgSOwCUKoVjSJCgV        
Spent time: 0.0046956539154052734    
50472.204 types per second.
(typing_env) PS [directory name]>

ここでは caesar_encrypt などを動かす必要が無くなるので、
実行速度がまた速くなります。
平均して一秒あたり50472回ほどタイプしていることになっていることが分かります。

体験版

以下に今回のタイピングゲームで、文字がズレるバージョンを実装いたしました。
このバージョンのコードも GitHub に上げておりますので、よろしければご覧ください。

時間などは測定しておりません。
下の入力欄には0以上3以下の数字を入力できます。最大この文字数分だけずれます。
入力欄において数字を入力したら、「変更」ボタンを押すことでその範囲内で出題されます。

おわりに

本日はタイピングゲームを作り、紹介してきました。
ぜひプレイして楽しんでください。
最後までお読みいただき、ありがとうございました。

koukawa_pp icon
この記事を書いた人
koukawa_pp

20 情報通信系、基本サウンド班所属 ブログはプログラミングに偏りがち

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2023年7月15日
2023 春ハッカソン 06班 stamProlog
H1rono_K icon H1rono_K
2023年3月30日
みやぎハッカソン2023に参加しました(ずんだ食べ食べ委員会)
mehm8128 icon mehm8128
2022年10月11日
アルゴリズム班にKaggle部を設立し、初心者向けデータ分析体験会を開催しました!
abap34 icon abap34
2021年4月18日
ベズー係数とN項の拡張ユークリッドの互除法
0214sh7 icon 0214sh7
2025年9月8日
ビット演算で何が計算できるのか?
n3 icon n3
2023年6月27日
2023 春ハッカソン 20班 『進捗が木になる~』
mehm8128 icon mehm8128
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記