Last active
August 29, 2015 14:02
-
-
Save lmdexpr/4b2944de7419b8f2f28f to your computer and use it in GitHub Desktop.
そこそこ頑張った課題なのでup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#define N_MENU 3 | |
#define M 20 | |
#define STR_LEN 64 | |
#define DIFs 3 | |
//#define PLAYERS 1 | |
#define _CMD(x) printf("\033[" x); | |
#define CLEAR _CMD("2J"); | |
#define MOVE_TOP _CMD("0;0H"); | |
enum {EASY = 1, NORMAL, HARD}; | |
enum {Win, Lose, Show, Exit}; | |
typedef enum {GT, LT, EQ} Ordering; | |
typedef enum {P = 0, C} Player; | |
typedef enum {RESET = -1, GET = 0, SET = 1} Method; | |
typedef int (*enterHand)(void); | |
int menu(); | |
int selectDif(); | |
int input(const char [][STR_LEN], int); | |
void printContents(const char [][STR_LEN], const int); | |
int game(int); | |
int setPlayerNumber(); | |
int guess(); | |
int setComputerNumber(); | |
enterHand ai(Method, int); | |
enterHand easy(Method); | |
enterHand normal(Method); | |
enterHand hard(Method); | |
Ordering resultMemory(Method, Ordering); | |
Ordering judge(int, int); | |
char *show(Ordering, int); | |
void printResults(Ordering [], int); | |
void printScore(int [2]); | |
void streamClear(); | |
int main(void) | |
{ | |
srand((unsigned)time(NULL)); | |
while(menu()); | |
CLEAR; | |
MOVE_TOP; | |
return 0; | |
} | |
int menu() | |
{ | |
static int winCounter[2] = {0, 0}; | |
int result, inp; | |
const char contents[][STR_LEN] = | |
{"数当てげーむ!", "メニュー:", "ゲームをする", "成績を見る", "ゲームを終わる"}; | |
const char inputText[][STR_LEN] = {"メニューから", "数字を選んでね"}; | |
printContents(contents, 5); | |
inp = input(inputText, 3); | |
switch (inp) { | |
case 1: | |
result = game(selectDif()); | |
winCounter[result]++; | |
break; | |
case 2: | |
result = Show; | |
printScore(winCounter); | |
break; | |
case 3: | |
result = Exit; | |
} | |
return !(result == Exit); | |
} | |
int selectDif() | |
{ | |
int inp; | |
const char contents[][STR_LEN] = | |
{"", "むずかしさを選んでね", "かんたん", "ふつう", "むずかしい"}; | |
const char inputText[][STR_LEN] = {"", "数字を選んでね"}; | |
printContents(contents, 2 + DIFs); | |
return input(inputText, 3); | |
} | |
int setPlayerNumber() | |
{ | |
const char str[][STR_LEN] = {"自分の数字(1から20まで)を", "入力してね"}; | |
MOVE_TOP; | |
CLEAR; | |
return input(str, M); | |
} | |
int guess() | |
{ | |
const char str[][STR_LEN] = | |
{"コンピュータの手を予想して数字を", "入力してね(1~20)"}; | |
return input(str, M); | |
} | |
int setComputerNumber(int dif) | |
{ | |
return rand() % M + 1; | |
} | |
enterHand ai(Method method, int dif) | |
{ | |
switch (dif) { | |
case EASY: | |
return easy(method); | |
case NORMAL: | |
return normal(method); | |
case HARD: | |
return hard(method); | |
} | |
} | |
enterHand easy(Method method) | |
{ | |
static int count = 0; | |
int reset() { | |
return count = rand() % M; | |
} | |
int get() { | |
return ++count > M ? count = 1 : count; | |
} | |
return method == RESET ? reset : get; | |
} | |
enterHand normal(Method method) | |
{ | |
static int flag[M] = {0}; | |
int get() { | |
int now = rand() % M; | |
if (flag[now]) | |
return normal(1)(); | |
flag[now] = 1; | |
return now + 1; | |
} | |
int reset() { | |
int i; | |
for (i = 0; i < M; i++) | |
flag[i] = 0; | |
return 0; | |
} | |
return method == RESET ? reset : get; | |
} | |
enterHand hard(Method method) | |
{ | |
static int min, max; | |
int get() { | |
static int mem = 0; | |
if (resultMemory(GET, EQ) == GT) | |
max = mem; | |
else if(resultMemory(GET, EQ) == LT) | |
min = mem; | |
mem = rand() % (max - min) + min + 1; | |
return mem; | |
} | |
int reset() { | |
min = 0; | |
max = M; | |
return 0; | |
} | |
return method == RESET ? reset : get; | |
} | |
Ordering resultMemory(Method method, Ordering r) | |
{ | |
static Ordering mem = EQ; | |
return method ? (mem = r) : mem; | |
} | |
Ordering judge(int inp, int ans) | |
{ | |
if (inp == ans) | |
return EQ; | |
else | |
return inp < ans ? LT : GT; | |
} | |
char *show(Ordering r, int c) | |
{ | |
int i; | |
static char str[2 * STR_LEN]; | |
const char msg1[][20] = {"あなた", "コンピュータ"}; | |
const char msg2[][20] = {"より大きい", "より小さい", "と同じ!"}; | |
strcpy(str, ""); | |
strcat(str, msg1[c]); | |
strcat(str, "が考えた数は"); | |
strcat(str, msg1[!c]); | |
strcat(str, "の隠している数"); | |
strcat(str, msg2[r]); | |
return str; | |
} | |
void printResults(Ordering result[], int count) | |
{ | |
printf("\n\t対戦結果:\n\n"); | |
printf("\t\t対戦数:%d\n", (count / 2) + 1); | |
printf("\t\t結果:%s", show(result[count % 2], count % 2)); | |
puts("\nなにかキーを押してね"); | |
getchar(); | |
return; | |
} | |
int game(const int dif) | |
{ | |
Ordering result[2] = {LT, LT}; | |
int hand, ph, ch, count = -1; | |
int numbers[2]; | |
enterHand eh[2] = {guess, ai(GET, dif)}; | |
numbers[0] = setPlayerNumber(); | |
numbers[1] = setComputerNumber(dif); | |
(void)ai(RESET, dif)(); | |
printf("\n\tコンピュータの考えた数字を当てよう!\n\n"); | |
do { | |
count++; | |
hand = eh[count % 2](); | |
result[count % 2] = judge(hand, numbers[!(count % 2)]); | |
resultMemory(SET, result[C]); | |
if (count % 2 == P) | |
printResults(result, count); | |
else { | |
printf("\tコンピュータは%dと答えました\n\n", hand); | |
puts("\nなにかキーを押してね"); | |
getchar(); | |
} | |
} while (result[count % 2] != EQ); | |
(void)ai(RESET, dif)(); | |
return count % 2; | |
} | |
void printScore(int c[2]) | |
{ | |
float matches = c[P] + c[C]; | |
MOVE_TOP; | |
CLEAR; | |
if (!matches) | |
printf("まだ一回も戦ってないよ><\n"); | |
else { | |
printf("\n\n\t\tあなたのスコア\n\n"); | |
printf("\n勝ち:%d(%3.2f%)", c[P], c[P] / matches * 100.0); | |
printf("\n負け:%d(%3.2f%)", c[C], c[C] / matches * 100.0); | |
printf("\n試合数:%.f", matches); | |
} | |
puts("\n\nなにかキーを押してね"); | |
getchar(); | |
return; | |
} | |
void printContents(const char str[][STR_LEN], const int strSize) | |
{ | |
int i; | |
MOVE_TOP; | |
CLEAR; | |
printf("\n\n\n\t\t%s\n\n", str[0]); | |
printf("\n\t%s\n", str[1]); | |
for (i = 1; i < strSize - 1; i++) | |
printf("\t\t%d)%s\n", i, str[i+1]); | |
return; | |
} | |
void streamClear(FILE *stream) | |
{ | |
while (fgetc(stream) != '\n') | |
; | |
return; | |
} | |
int input(const char str[][STR_LEN], const int m) | |
{ | |
static int re = 0; | |
int inp = -1, check; | |
printf("\t%s%s%s\n\t\t> ", str[0], re ? "もう一度" : "", str[1]); | |
check = scanf("%d", &inp); | |
streamClear(stdin); | |
if (inp < 1 || inp > m || check != 1) { | |
re = 1; | |
return input(str, m); | |
} | |
return inp; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
注: 課題としてグローバル変数は使用不可の条件付