コード:
/* ラックナンバーサーチ・トレーニング(最近の10回の日時の表示)*/
#include <stdio.h>
#include <time.h>
#include <float.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include "getputch.h"
#define MAX_STAGE 3
#define swap(type, x, y) do { type t = x; x = y; y = t; } while (0)
#define MAX_NUM 10
char dtfile[] = "LACKNUM.DAT"; /* ファイル名 */
char dtfile2[] = "LACKNUM2.DAT";/* 最高記録用のファイル */
double score2;
//1回実行したとき進むポイントの大きさを求める
int kaime_p(fpos_t* kaime_p1)
{
FILE *fp;
struct tm local;
double best;
fp = fopen(dtfile, "rb");
fread(&local, sizeof(struct tm), 1, fp);
fread(&best, sizeof(double), 1, fp);
//ファイルポインタの位置を取得
fgetpos(fp,kaime_p1); //ファイルfpの現在のファイル位置を取得して
// kaime_p1の示す場所に格納します。
printf("ファイルポインタの位置kaime_p1は「%d」です。\n",*kaime_p1);
fclose(fp);
return *kaime_p1;
}
//local のデータを新しい順にならべる。
void new_local_data(fpos_t ft,int k)
{
FILE *fp; // これまでの履歴を指すポインタ
FILE *fp2; // これまでの最短所要時間を指すポインタ
double best; //これまでの履歴の所要時間
double best2; //これまでの最短所要時間のベストテンも保存しておく
int i;
struct tm local; //構造体変数 localの大きさ
if ((fp = fopen(dtfile, "rb")) == NULL) {
printf("ファイルを作成します。\n\n");
best = DBL_MAX; /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */
} else {
for(i=ft-k; i>=ft-10*k; i -= k){ //構造体変数 localの大きさkaime_p1で44
//ファイルポインタを先頭からiまで移動
fseek(fp,i,SEEK_SET);
fread(&local, sizeof(struct tm), 1, fp);
printf("%d年 %d月 %d日 %d時 %d分 %d秒\n",
local.tm_year + 1900, local.tm_mon + 1,
local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec);
fread(&best, sizeof(double), 1, fp);
printf("得点(所要時間)は%.1f秒\n\n", best);
}
printf("enterキーで開始します。\n");
fflush(stdin);
getchar();
}
fclose(fp);
}
/*--- 今回のトレーニング情報を書き込む ---*/
void put_data(double best, double best2)
{
FILE *fp; //fpはfopenされたdtfileを指すポインタ
FILE *fp2; //fp2はfopenされたdtfile2を指すポインタ、最短時間が格納されている
time_t t = time(NULL);
struct tm *local = localtime(&t);
time(&t);
local = localtime(&t);
if ((fp = fopen(dtfile, "ab")) == NULL){
printf("ファイルがあーりません");
fflush(stdout);
}else {
fwrite(local, sizeof(struct tm), 1, fp); //fpに書き込む
fwrite(&best, sizeof(double), 1, fp); //fpに書き込む
fclose(fp);
}
if(best <= best2){
if((fp2 = fopen(dtfile2, "wb")) ==NULL){
printf("ファイルがあーりません");
fflush(stdout);
}else{
//point配列にbestをいれ、best2をベスト2にいれる。dtfile[0]にbest1,dtfile[1]にbest2.....dtfile[9]にbest10
fwrite(local, sizeof(struct tm), 1, fp2);
fwrite(&best2, sizeof(double), 1, fp2);
fclose(fp2);
}
}
}
/*--- トレーニングを実行して得点(所要時間)を返す ---*/
double go(void)
{
int i, j, stage;
int dgt[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int a[8];
double jikan; /* 時間 */
clock_t start, end; /* 開始時刻・終了時刻 */
printf("欠けている数字を入力してください。\n");
printf("スペースキーで開始します。\n");
while (getch() != ' ')
;
start = time(NULL);
for (stage = 0; stage < MAX_STAGE; stage++) {
int x = rand() % 9; /* 0~8の乱数を発生 ,1から9までのうち8文字を表示するための数字 */
int no; /* 読み込んだ値 ,キーボードから打ち込んだ数字 */
i = j = 0;
while (i < 9) { /* dgt[x]を飛ばしてコピー */
if (i != x)
a[j++] = dgt[i];/* dgt[x]は1から9までの数字が入っている配列 */
i++;
}
for (i = 7; i > 0; i--) { /* 配列aをシャッフル、配列の添字は0から7までの8個である */
int j = rand() % (i + 1); /* 配列aの添字は0から7までの8個である。jは1から7まで変化する */
if (i != j) /* jは1から7まで変化する。iとjの添字でシャッフルする。 */
swap(int, a[i], a[j]);
}
printf("%d回目:", stage+1);
for (i = 0; i < 8; i++){ /* 全要素を表示 */
printf("%d ", a[i]);
}
printf(":");
fflush(stdout);
do {
no = getch();
if (isprint(no)) { /* 表示可能であれば */
putch(no); /* 押されたキーを表示 */
if (no != dgt[x] + '0') /* 正解でなければ */
putch('\b'); /* カーソルを一つ戻す */
else
printf("\n"); /* 改行 */
}
} while (no != dgt[x] + '0');
}
end = time(NULL);
jikan = (double)difftime(end, start);
printf("%.1f秒かかりました。\n", jikan);
if (jikan > 25.0)
printf("鈍すぎます。\n");
else if (jikan > 20.0)
printf("少し鈍いですね。\n");
else if (jikan > 17.0)
printf("まあまあですね。\n");
else
printf("素早いですね。\n");
return (jikan);
}
int main(void)
{
int retry; /* もう一度? */
double score; /* 今回の所要時間 */
double best; /* 最短所要時間 */
FILE *fp;
fpos_t ft;
fpos_t kaime_p1;
struct tm local ;
int k;
fp = fopen(dtfile, "rb");
kaime_p(&kaime_p1);
k=kaime_p1;
//ファイルポインタの位置を取得
printf("mainのkaime_p(&kaime_p1)後のkの値は「%d」です。\n\n",k);
//ファイルポインタを末尾まで移動
fseek(fp,0,SEEK_END);
//ファイルポインタの位置を取得
fgetpos(fp,&ft); //ファイルfpの現在のファイル位置を取得して
// &ftの示す場所に格納します。
new_local_data(ft,k);
fgetpos(fp,&ft);
//best = get_data(ft);
// get_data()で前回までの最短所要時間を
//ファイルから読み込んでbestに代入する。
init_getputch();
srand(time(NULL)); /* 乱数の種を初期化 */
do {
score = go(); // トレーニング(go)で実行、返却された所要時間(jika)をscoreに代入する。
if (score < best) {
printf("最短所要時間を更新しました!!\n");
best = score; /* 最高得点更新 */
}
printf("もう一度しますか … (0)いいえ (1)はい:");
scanf("%d", &retry);
} while (retry == 1);
put_data(score,best); /* 今回の日付・時刻・得点を書き込む */
fclose(fp);
term_getputch();
return 0;
}
//上記のプログラムに実行時間の短い順に表示するプログラムbesttenを追加したい。
//いろいろやって、あたまがくちゃくちゃで、整理がつかなくなりました。下のプログラムは
//でたらめですが、これを何とか手直ししながらかんせいさせたいのでよろしくおねがします。
//このプログラムは新詳解c言語中級編9章から引用し、追加、変更しています。
//新詳解c言語中級編9章自由課題9-1をといています。
// 実行時間の短い順に並べて表示する。
int bestten(double best,double p_score)
{
FILE *fp; // これまでの履歴を指すポインタ
double past_score;
int i,N;
struct tm local;
if ((fp = fopen(dtfile, "rb")) == NULL) {
printf("ファイルを作成します。\n\n");
best = DBL_MAX; /* float.hに定義されている。double型で表現できる最大値を表すマクロDBL_MAX */
} else {
while((i = fread(&local, sizeof(struct tm), 1, fp)) > 0 ){
fread(&best, sizeof(double), 1, fp);
past_score=best;
printf("過去の実行時間 %d\n\n",past_score);
// 比較関数を使って短い順に挿入する。あるいはdtfile[]を並べ替える
/* float型のソート */
qsort(best,N,sizeof(float),float_cmp);
for(i = 0; i < N; i++)
printf("%0.1f ",best[i]);
/* float型の比較 */
int float_cmp(const void *arg0, const void *arg1){
float past_score = *(float*)arg0;
float best = *(float*)arg1;
if(past_score == best) return 0;
else if(past_score > best) return 1;
else return -1;
}
}
}
if((fp = fopen(dtfile, "rb")) == NULL){
printf("\aファイルをオープンできません。\n");
}else{
while((i = fread(dtfile, sizeof(struct tm), 1, fp)) > 0 ){
printf("%d年 %d月 %d日 %d時 %d分 %d秒\n",
local.tm_year + 1900, local.tm_mon + 1,
local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec);
fread(&best, sizeof(double), 1, fp);
printf("得点(所要時間)は%.1f秒\n\n", best);
}
}
fclose(fp);
}
int main(void)
{
int retry; /* もう一度? */
double score; /* 今回の所要時間 */
double best; /* 最短所要時間 */
best = get_data(); // get_data()で前回までの最短所要時間を
// ファイルから読み込んでbestに代入する。
init_getputch();
srand(time(NULL)); /* 乱数の種を初期化 */
do {
score = go(); // トレーニング(go)で実行、返却された所要時間(jika)をscoreに代入する。
if (score < best) {
printf("最短所要時間を更新しました!!\n");
best = score; /* 最高得点更新 */
}
printf("もう一度しますか … (0)いいえ (1)はい:");
scanf("%d", &retry);
} while (retry == 1);
put_data(score,best); /* 今回の日付・時刻・得点を書き込む */
term_getputch();
return 0;
}