Skip to content

Instantly share code, notes, and snippets.

@lmdexpr
Last active August 29, 2015 14:02
Show Gist options
  • Save lmdexpr/4b2944de7419b8f2f28f to your computer and use it in GitHub Desktop.
Save lmdexpr/4b2944de7419b8f2f28f to your computer and use it in GitHub Desktop.
そこそこ頑張った課題なのでup
#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;
}
@lmdexpr
Copy link
Author

lmdexpr commented Jul 5, 2014

注: 課題としてグローバル変数は使用不可の条件付

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment