雪の日の過ごし方

こんにちは。武田です。
2月9日は記録的な大雪となりましたが、みなさんはいかがお過ごしでしたか?
雪の日は、行動派なら「雪かき」、ひきこもりなら「プログラミング」に限りますね。
わたしはちなみに「プログラミング」です!

プログラミングの面白いところは、答えが一つではないところです。
どこか人生にも似ていると思います。

わたしは完成したプログラムよりも、プログラミングで試行錯誤している過程が好きです。

学生にC言語で、こんな課題を出しました。

 画面に表示された10進数を16進数で答えるゲーム
	仕様
	・問題はランダムに5問出題される
	・0~15の10進数が画面に表示される
	・ユーザはキーボードから答えを16進数で入力する
	・解答後に「正解」「不正解」を表示する
	・解答での大文字・小文字の区別はない
		例)問題が「10」のとき、「A」も「a」も正解

問題データの持ち方でプログラムの内容も変わってくると思います。
わたしは文字型で問題と解答データを作成しました。
配列変数の初期化にはmemsetなども使ってC言語の基本にそって作ってみました。
scanfなどの危険な関数もあえて使わずに実践的に作ったつもりです。

以下、解答例です。
正直なところ、もっと簡単なプログラムでもできます。

/*
	answer16.c 画面に表示された10進数を16進数で答えるゲーム
		仕様
		・問題はランダムに5問出題される
		・0~15の10進数が画面に表示される
		・ユーザはキーボードから答えを16進数で入力する
		・解答後に「正解」「不正解」を表示する
		・解答での大文字・小文字の区別はない
			例)問題が「10」のとき、「A」も「a」も正解
			
	Created by take3.asia on 2014/02/10.
	Copyright 2014 Shuichi Takeda, All rights reserved.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

#define MAX 16
int main(void)
{
	int i, j, r;
	char mondai[MAX][3];
	char kotae[MAX][2];
	char kaitou[MAX];
	
	// 配列の初期化
	memset(mondai, 0, sizeof(mondai));
	memset(kotae, 0, sizeof(kotae));
	memset(kaitou, 0, sizeof(kaitou));

	/* 問題と解答の設定 */
	for(i=0; i<MAX; i++){
		sprintf(mondai[i], "%d", i);	/* 0, 1, 2...15 */
		sprintf(kotae[i], "%X", i);	/* 0, 1, 2...F */
	}
	/* ランダムで5問出題 */
	srand((unsigned)time(NULL));
	printf("10進数を16進数に直して答えて下さい...");
	getchar();
	
	for(i=0; i<5; i++){
		r = rand() % MAX;
		printf("[ %s ] の16進数は? ", mondai[r]);
		/* 解答する */
		fgets(kaitou, sizeof(kaitou), stdin);
		sscanf(kaitou, "%2s", kaitou);
		for(j=0; kaitou[j] != '\0'; j++) kaitou[j] = toupper(kaitou[j]);	/* 小文字入力は大文字に変換 */
		rewind(stdin);
		/* 正誤 */
		if(!strcmp(kotae[r], kaitou)){
			printf("○\n");
		}
		else{
			printf("×\t->%s\n", kotae[r]);
		}
	}
	
	return 0;
}

ところで、このプログラムには欠点があり、場合によっては同じ問題が続けて出題されてしまいます。
ランダムで毎回適当に出題しているからです。
重複しないで出題するにはどうすればいいでしょうか?
これが正式な課題です。

その方法は色々あります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です