K3の住民

最近はレア社のゲームについては書いていませんが、一応レア社のゲームが一番好きな人です。『雪圀』で"圀"は"国"とほぼ同義ですが、国ではありませんって当たり前か(笑)。

【Cプログラミング】簡単な連打測定ソフトを作ってみた

連打測定ソフト自体はどこにでもあると思うので、配布は致しません。

皆さん、こんにちは。雪圀です。
今回、Cで簡単な連打測定ソフトを作ったので実際に使ってみるのと、適当に解説して
いきます。

使ってみた

それでは実際に使ってみようと思います。

キーボード入力を可視化する為にorenge様の「kbv」を使わせていただきました。

解説

開発環境はWindows10で、Windowsで無いと動かないプログラムとなっております。
その故に、移植性は低いです。

仕様としては、

  • 10秒間スペースキーの連打回数の測定を行う
  • 開始前に最大連打回数(要はハイスコア)を表示する
  • 測定終了後連打回数と1秒毎の連打速度を表示する
  • 最大連打回数を更新したことが確認出来る

以上の4点となっております。

先ず、最初の時点で、「はい」か「いいえ」の選択肢があったと思いますが、あれは
Windows用の仮想キーコードを読み取るGetKeyState()関数を使って、矢印キーで判断
を行い、エスケープ文字「\r」を含めた文字列をprintf()関数で出力し、あたかも選択
しているかのように見せています。
GetKeyState()関数はwindows.hをincludeすることで使うことが出来るようになり、
この関数によりWindowsでキーボード操作をする場合の問題が解消されます。

・・・え、conio.hのkbhit()関数とgetch()関数を使えばいいのでは無いかって?
いやー、僕も最初はそれを使って作ろうかと思ったんですけどね。なんかWindows
キー処理の仕様が特殊だったのかは知らないですけど、キーを押しっぱなしにする
と、キーを高速で押して離してを繰り返すって判断されて、押しっぱなしにするだけ
で超高速連打をしてしまうっていうバグがどうしても発生してしまうので、仕方無く
windows.hのGetKeyState()関数を使ったらそれが解消されたわけですよ。
多分他のOSではkbhit()関数とgetch()関数でも問題無いんでしょうけどねえ・・・。

因みに基本的にはこのように書いています。

#include <windows.h>

int main(void)
{
	if((GetKeyState(/* 仮想キーコード */) & 0x80) != 0) {
 		
		/* 細かい処理 */
	
		// キーを離すまでループ
		while((GetKeyState(/* if文と同じ */) & 0x80) != 0);
	}
	
	return 0;
}

ビットAND演算子を使って仮想キーコードと0x80の論理積を求めています。これは
Windowsの仕様によるものなので、絶対に必要であることとして覚えておいて
ください。
while文でif文と同じ条件文を書いていると思いますが、これは押しっぱなしによる
連打の防止策です。
以上の処理は連打回数計測時にも使われています。

次に、「はい」を選択したときに、画面が切り替わったと思いますが、これは簡単
ですね。
stdlib.hをincludeすることで使えるsystem()関数を使い、コマンド「cls」を呼び出し
ています。以上。
地味にこれもWindowsじゃないと使えない要因の一つです。UNIX系でやる場合は
「cls」を「clear」に変える必要があります。

#include <stdlib.h>

int main(void)
{
	// コマンド「cls」の実行
	system("cls");
	
	return 0;
}

測定時間についてですが、これはtime.hをincludeし、time_t型の変数を用意し、
その変数に現在の時刻を代入、そしてdifftime()関数を利用し、現在の時刻と変数の
差が指定した秒数になるまでループするという仕組みになっております。

#include <time.h>

int main(void)
{
	time_t cnt;
	
	for(cnt = time(NULL); difftime(time(NULL), cnt) < /* 秒数 */; ) {
		
		/* 細かい処理 */
		
	}
	
	return 0;
}

「後処理が無いじゃん」と思われたかもしれませんが、for文の初期処理または
後処理は省略することが出来ます。後処理は省略することで後処理を無しにする
ことが出来ます。

指定した秒数待つだけのときはwindows.hのSleep()関数を使っています。

#include <stdio.h>
#include <windows.h>

int main(void)
{
	printf("文字列\n");
	Sleep(1000);		// 1秒待つ
	printf("文字列\n");
	
	return 0;
}

最後に測定開始前に表示する最大連打回数と、測定後に表示する連打回数と
1秒毎の連打速度、そして最大連打回数更新を表示する方法は、以下の通りと
なっております。

  • 最大連打回数の表示
#include <stdio.h>

int main(void)
{
	int hscr = 0;		// 最初の最大連打回数は0
	
	printf("%d", hscr);	// 最大連打回数の表示
	
	return 0;
}
  • 連打回数の表示

最大連打回数と同じ

  • 1秒毎の連打速度の表示
#include <stdio.h>

int main(void)
{
	float spd;		// 連打速度
	int scr = 125;		// 連打回数は125回とする
	
	spd = (float)scr / 10;	// 10秒間計測するので10で割る
	
	printf("%.1f", spd);	// 1秒毎の連打速度の表示(小数点1桁)
	
	return 0;
}
  • 最大連打回数の更新
int main(void)
{
	int hscr = 0;		// 最大連打回数
	int scr = 125;		// 連打回数は125回とする
	
	if(scr > hscr) {	// scrがhscrを上回った
		hscr = scr;	// hscrの更新(最大連打回数の更新)
	
		/* その他の処理 */
		
	}
	
	return 0;
}

あとはタイトルに戻るとき、連打回数を0にするのを忘れないようにしましょう。
これを忘れると計測終了後の連打回数から開始してしまいます。

以上をまとめると、このような感じです。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

int main(void)
{
	/* 変数の宣言 */
	
	while(1) {
		/* 画面切り替え */
		
		/* タイトル */
		/* - 最大連打回数表示 */
		/* - キー操作 */
		
		/* 画面切り替え */
		
		/* 測定 */
		/* - 10秒間測定 */
		/* - キー連打 */
		/* - 連打回数表示 */
		
		/* 画面切り替え */
		
		/* 測定終了 */
		/* - 連打回数表示 */
		/* - 1秒毎の連打速度表示 */
		/* - 最大連打回数の更新 */
		/* - キー操作 */
		
		/* 連打回数の初期化 */
	}
	
	return 0;
}


以上です。
指摘等(特にkbhit()とgetch()での押しっぱなし連打の回避方法)はどんどんして
もらって構わないです。
寧ろ勉強になるのでしてください。

今回はこれくらいにしときます。