c言語はまだ習って一年ほどなので分からないことが多々ありますがよろしくお願いします。
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct{
char name[20];
char score[20];
}rank;
rank r[5];//ランキングを管理する構造体
int Time, s = 0;//時間、スコア
char str[256], name[20]; //文字列汎用変数,プレイヤー名
time_t current, start;//経過時間
FILE *fp;
int ch;//キー入力
int level;//レベル
int next, nextnext, d_lines = 0;//次と次の次のブロック、消した行
void go();
#define PATNUM 7
#define PATSIZEW 3
#define PATSIZEH 3
#define PATSPIN 4
static char blockPattern[PATNUM][PATSPIN][PATSIZEH][PATSIZEW] =
{
{
{{'#','#',' '}, {'#','#',' '}, {' ',' ',' '}},//pt ##
{{'#','#',' '}, {'#','#',' '}, {' ',' ',' '}},// ##
{{'#','#',' '}, {'#','#',' '}, {' ',' ',' '}},//
{{'#','#',' '}, {'#','#',' '}, {' ',' ',' '}},//
},{
{{' ','#',' '}, {' ','#',' '}, {' ','#',' '}},//pt
{{' ',' ',' '}, {'#','#','#'}, {' ',' ',' '}},// ###
{{' ','#',' '}, {' ','#',' '}, {' ','#',' '}},//
{{' ',' ',' '}, {'#','#','#'}, {' ',' ',' '}},//
},{
{{' ',' ',' '}, {' ','#',' '}, {'#','#','#'}},//pt
{{' ',' ','#'}, {' ','#','#'}, {' ',' ','#'}},// #
{{'#','#','#'}, {' ','#',' '}, {' ',' ',' '}},// ###
{{'#',' ',' '}, {'#','#',' '}, {'#',' ',' '}},//
},{
{{'#',' ',' '}, {'#','#','#'}, {' ',' ',' '}},//pt
{{' ','#',' '}, {' ','#',' '}, {'#','#',' '}},// #
{{' ',' ',' '}, {'#','#','#'}, {' ',' ','#'}},// ###
{{' ','#','#'}, {' ','#',' '}, {' ','#',' '}},//
},{
{{' ',' ','#'}, {'#','#','#'}, {' ',' ',' '}},//pt
{{'#','#',' '}, {' ','#',' '}, {' ','#',' '}},// #
{{' ',' ',' '}, {'#','#','#'}, {'#',' ',' '}},// ###
{{' ','#',' '}, {' ','#',' '}, {' ','#','#'}},//
},{
{{' ',' ',' '}, {' ','#','#'}, {'#','#',' '}},//pt
{{' ','#',' '}, {' ','#','#'}, {' ',' ','#'}},// ##
{{' ',' ',' '}, {' ','#','#'}, {'#','#',' '}},// ##
{{' ','#',' '}, {' ','#','#'}, {' ',' ','#'}},//
},{
{{' ',' ',' '}, {'#','#',' '}, {' ','#','#'}},//pt 回転軸は中央ではない(pt6と一致してしまう)
{{' ',' ','#'}, {' ','#','#'}, {' ','#',' '}},// ##
{{' ',' ',' '}, {'#','#',' '}, {' ','#','#'}},// ##
{{' ',' ','#'}, {' ','#','#'}, {' ','#',' '}},//
}
};
//下+左右の当たり判定を調べる関数(下、左、右それぞれにブロック、壁がある場合に2、3、4を返すように設定)
int collision(int blocY, int blocX, int bottom, int pattern, int spin, char buffer[LINES][COLS/2] )
{
int ii, jj;
int j = 0;
for( jj=0; jj<3; jj++){
for( ii=0; ii<3; ii++){
if(blockPattern[pattern][spin][jj][ii] == '#'){
if((buffer[blocY + jj + 1][blocX + ii] == '#') || (blocY + jj + 1 == bottom))//下の当たり判定
j = 2;
if((buffer[blocY + jj][blocX + ii - 1] == '#') || (blocX + ii - 1 == COLS/4))//左の当たり判定
j = 3;
if((buffer[blocY + jj][blocX + ii + 1] == '#') || (blocX + ii + 1 == COLS/2))//右の当たり判定
j = 4;
}
}
}
return j;
}
//ランキングを書き込むか、新たにランキングのファイルを作成する関数
void ranking(int n)
{
int i;
//nが1ならランキングをファイルに書き込む
if(n == 1){
if((fp = fopen("highscore.txt", "w+")) == NULL){
printf("ランキングファイルの作成に失敗しました。\n");
exit(1);
}
for( i=0; i<5; i++){
sprintf(str, "%s\n", r[i].name);
if(fputs(str, fp) == EOF){
printf("書き込みにに失敗しました。\n");
exit(1);
}
sprintf(str, "%s\n", r[i].score);
if(fputs(str, fp) == EOF){
printf("書き込みに失敗しました\n");
exit(1);
}
}
}
//nが0ならランキングを読み込めないとき
if(n == 0){
printf("ランキングを読み込めません。新しいファイルを作成します。\n");
if((fp = fopen("highscore.txt", "w+")) == NULL){
printf("ランキングファイルの作成に失敗しました。\n");
exit(1);
}
for(i=0; i<5; i++){
if(fputs("No name\n", fp) == EOF){
printf("書き込みに失敗しました。\n");
exit(1);
}
if(fputs("0\n", fp) == EOF){
printf("書き込みに失敗しました。\n");
exit(1);
}
}
}
return;
}
void end(int n)//ゲーム終了時の関数
{
int i,j;
mvaddstr(LINES / 2 - 7, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) - 6, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) - 5, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) - 4, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) - 3, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) - 2, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) - 1, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) , ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) + 1, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) + 2, ((COLS - 20) / 2) - 16, " ");
mvaddstr((LINES / 2) + 3, ((COLS - 20) / 2) - 16, " ");
mvaddstr(LINES / 2 - 7, ((COLS - 20) / 2) - 3, "GameOver...");
mvprintw((LINES / 2) - 6, ((COLS - 20) / 2) - 7, "Your Score %7d !!", s);
if (s > atoi(r[4].score)){
mvaddstr((LINES / 2) - 5, ((COLS - 20) / 2) - 4, "High Score !!");
mvaddstr((LINES / 2) - 4, ((COLS - 20) / 2) - 8, "Your Name -> ");
curs_set(1);
nocbreak();
echo();
timeout(-1);
getnstr(name, 15);
curs_set(0);
cbreak();
noecho();
timeout(0);
//ランキングに追加
for (i = 4; i >= 0; i--){
if (atoi(r[i].score) < s){
if (i == 0){
strcpy(r[i].name,name);
sprintf(r[i].score, "%d", s);
break;
}
if (atoi(r[i - 1].score) >= s){
strcpy(r[i].name,name);
sprintf(r[i].score, "%d", s);
break;
}else{
strcpy(r[i].name,r[i - 1].name);
strcpy(r[i].score,r[i - 1].score);
}
}
}
mvaddstr((LINES / 2) - 3 + i, ((COLS - 20) / 2) - 16, "You! -> ");
//ファイルに書き込み
ranking(1);
fclose(fp);
}
mvaddstr((LINES / 2) - 4, ((COLS - 20) / 2) - 8, " Ranking ");
for (i = 0; i < 5; i++){
mvprintw((LINES / 2) - 3 + i, ((COLS - 20) / 2) - 8,"%d:", i + 1);
j = strlen(r[i].name);
mvprintw((LINES / 2) - 3 + i, ((COLS - 20) / 2) + 6 - j,"%s", r[i].name);
j = strlen(r[i].score);
mvprintw((LINES / 2) - 3 + i, ((COLS - 20) / 2) + 14 - j,"%s", r[i].score);
}
mvaddstr((LINES / 2) + 3, ((COLS - 20) / 2) - 2, "q : Quit");
while(1){
ch = getch();
if (ch == 'q'){
endwin();
exit(1);
}
}
return;
}
void deleteLine(char buffer[LINES][COLS/2])//揃った行を消す関数
{
int i, j, q;
int hantei;
for(j = 0; j < LINES ; j++){
hantei = 1;
for(i = COLS/4 + 1; i < COLS/2; i++){
if(buffer[j][i] == ' ')
hantei = 0;
}
if(hantei){
for(q = j; q>0; q--){
for(i = COLS/4 + 1; i < COLS/2; i++){
buffer[q][i] = buffer[q-1][i];
//1段下げる
}
}
s += 100 * level;
d_lines++;
}
}
}
//画面横に情報を表示する関数
void info()
{
int i,j;
//経過時間の表示
time(¤t);
current -= start;
j = COLS/4 * 3;
mvaddstr(5, j, "Time:");
mvprintw(6, j, " %5d", current + Time);
//現在のレベルの表示
mvaddstr(3, j, "Level:");
mvprintw(4, j, " %d", level);
//消した行数の表示
mvaddstr(7, j, "deleted_lines:");
mvprintw(8,j, " %7d", d_lines);
//スコアの表示
mvaddstr(9, j, "Score:");
mvprintw(10,j, " %7d", s);
//ハイスコアの表示
mvaddstr(11,j, "High Score:");
i = strlen(r[0].score);
mvprintw(12,j + 19 - i, "%s", r[0].score);
//ハイスコアプレイヤ―の表示
mvaddstr(13,j, "High Score Player:");
i = strlen(r[0].name);
mvprintw(14,j + 19 - i, "%s", r[0].name);
//次と次の次ののブロックの表示
mvaddstr(15,j, "Next Blocks");
mvaddstr(16,j, "First Second");
mvaddstr(17,j, "+---+ +---+");
sprintf(str, "|%c%c%c| |%c%c%c|",blockPattern[next][0][0][0],blockPattern[next][0][0][1],blockPattern[next][0][0][2],blockPattern[nextnext][0][0][0],blockPattern[nextnext][0][0][1],blockPattern[nextnext][0][0][2] );
mvaddstr(18,j, str);
sprintf(str, "|%c%c%c| |%c%c%c|",blockPattern[next][0][1][0],blockPattern[next][0][1][1],blockPattern[next][0][1][2],blockPattern[nextnext][0][1][0],blockPattern[nextnext][0][1][1],blockPattern[nextnext][0][1][2] );
mvaddstr(19,j, str);
sprintf(str, "|%c%c%c| |%c%c%c|",blockPattern[next][0][2][0],blockPattern[next][0][2][1],blockPattern[next][0][2][2],blockPattern[nextnext][0][2][0],blockPattern[nextnext][0][2][1],blockPattern[nextnext][0][2][2] );
mvaddstr(20,j, str);
mvaddstr(21,j, "+---+ +---+");
return;
}
int main(int argc, char **argv){
int i, j;
//ランキングファイルを読み込む
for (;(fp = fopen("highscore.txt", "r")) == NULL;){
ranking(0);
fclose(fp);
}
for (i = 0; i < 5; i++){
if (fgets(r[i].name, 20, fp) == NULL){
ranking(0);
printf("もう一度プログラムを実行しなおしてください\n");
exit(1);
}
for (j = 0; r[i].name[j] != '\0'; j++);
if (r[i].name[j - 1] == '\n')
r[i].name[j - 1] = '\0';
if (fgets(r[i].score, 20, fp) == NULL){
ranking(0);
printf("もう一度プログラムを実行しなおしてください\n");
exit(1);
}
for (j = 0; r[i].score[j] != '\0'; j++);
if (r[i].score[j - 1] == '\n')
r[i].score[j - 1] = '\0';
}
fclose(fp);
initscr();
start_color();
noecho();
cbreak();
curs_set(0);
keypad(stdscr, TRUE);
go();
endwin();
return 0;
}
void go()
{
int blocX, blocY;
int delay=0;
int waitCount = 20000;
int pattern;
int spin = 0;
char buffer[LINES][COLS/2];
int i, j;
int ii, jj;
int a = 1;
int t;
level = 1;
s = 0;
Time = 0;
timeout(0);
time(&start);
srand((unsigned) time(NULL));
pattern = rand() % 7;
next = rand() % 7;
nextnext = rand() % 7;
blocX = (COLS/8) * 3;
blocY = 1;
for( j=0; j<LINES; j++){
for( i=0; i<COLS/2; i++){
buffer[j][i]=' ';
}
}//buffer内を初期化
timeout(0);
while((ch=getch())!='q'){
mvaddstr(blocY,blocX," ");
mvaddstr(blocY+1,blocX," ");
mvaddstr(blocY+2,blocX," ");
for(a=0; a<LINES; a++){
mvaddch( a, COLS/2, '|');
mvaddch( a, COLS/4, '|');
}
for(a = COLS/4 + 1; a < COLS/2; a++){
mvaddch(LINES-1, a, '-' );
}
if(delay%waitCount == 0){
blocY += 1;
}
delay++;
switch(ch){
case KEY_LEFT://左に1マス移動
if(collision(blocY, blocX, LINES-1, pattern, spin, buffer) != 3){
blocX -=1;
}
break;
case KEY_RIGHT://右に1マス移動
if(collision(blocY, blocX, LINES-1, pattern, spin, buffer) != 4){
blocX +=1;
}
break;
case KEY_DOWN://真下に即落下させる
while(1){
blocY++;
if(collision(blocY, blocX, LINES-1, pattern, spin, buffer) == 2){
for(jj=0; jj<3; jj++){
for(ii=0; ii<3; ii++){
if(blockPattern[pattern][spin][jj][ii] == '#'){
buffer[blocY+jj][blocX+ii] = blockPattern[pattern][spin][jj][ii];
}
}
}
pattern = next;
next = nextnext;
nextnext = rand() % 7;
blocY = 1;
blocX = (COLS/8) * 3;
beep();
break;
}
}
break;
case ' ':
if(collision(blocY, blocX, LINES-1, pattern, spin, buffer) <= 2){
spin = (spin + 1) % PATSPIN;
}
break;
default:
break;
}
//buffer内のブロック
for(j=0; j<LINES-1; j++){
for(i= COLS/4 + 1; i<COLS/2; i++){
mvaddch(j, i, buffer[j][i] );
}
}
//操作中のブロック
for(jj=0; jj<3; jj++){
for(ii=0; ii<3; ii++){
if(blockPattern[pattern][spin][jj][ii] == '#')
mvaddch(blocY+jj, blocX+ii, blockPattern[pattern][spin][jj][ii]);
}
}
//ブロックが着地した時にbufferに追加
if( collision(blocY, blocX, LINES-1, pattern, spin, buffer) == 2){
for(jj=0; jj<3; jj++){
for(ii=0; ii<3; ii++){
if(blockPattern[pattern][spin][jj][ii] == '#'){
buffer[blocY+jj][blocX+ii] = blockPattern[pattern][spin][jj][ii];
}
}
}
pattern = next;
next = nextnext;
nextnext = rand() % 7;
blocX = (COLS/8) * 3;
blocY = 1;
beep();
}
if(s >= 500 * level){
level++;
waitCount = waitCount / 4 * 3;
}
deleteLine(buffer);
t = 0;
for(ii = 0; ii < 256; ii++)//ゲームオーバーの条件
if(buffer[1][ii] == '#')
t = 1;
if(t)break;
info();
}
if(t)
end(0);
return;
}