C語言實現俄羅斯方塊
阿新 • • 發佈:2018-12-22
看下游戲介面:
不知道怎麼介紹,直接上程式碼:
Model.h
#pragma once #define FACE_X 20 #define FACE_Y 29 #define WALL 2 #define BOX 1 #define KONG 0 typedef struct Face { int data[FACE_Y][FACE_X + 10]; //1->方塊,2->空格 int color[FACE_Y][FACE_X + 10]; //對應方塊的顏色 }Face; typedef struct DownDiamonds { int space[4][4]; }DownDia; DownDia dia[7][4]; typedef struct Game { Face face; int maxscore; int score; int speed; }Game; void GameInit(Game *pGame); void Init_dia(); //初始化方塊 int color(int c);
Model.c
#define _CRT_SECURE_NO_DEPRECATE 1 #include "Model.h" #include "Windows.h" #include "view.h" void Init_dia() { for (int i = 0; i < 3; i++) { //0 1 0 0 dia[0][0].space[1][i] = 1; //1 1 1 0 dia[0][0].space[0][1] = 1; //0 0 0 0 //0 0 0 0 } for (int i = 0; i < 3; i++) { //1 1 1 0 dia[1][0].space[0][i] = 1; //1 0 0 0 dia[1][0].space[1][0] = 1; //0 0 0 0 //0 0 0 0 } for (int i = 0; i < 3; i++) { //1 1 1 0 dia[2][0].space[0][i] = 1; //0 0 1 0 dia[2][0].space[1][2] = 1; //0 0 0 0 //0 0 0 0 } for (int i = 0; i < 2; i++) { //1 1 0 0 dia[3][0].space[0][i] = 1; //0 1 1 0 dia[3][0].space[1][i + 1] = 1; //0 0 0 0 //0 0 0 0 //0 1 1 0 dia[4][0].space[0][i + 1] = 1; //1 1 0 0 dia[4][0].space[1][i] = 1; //0 0 0 0 //0 0 0 0 //1 1 0 0 dia[5][0].space[0][i] = 1; //1 1 0 0 dia[5][0].space[1][i] = 1; //0 0 0 0 //0 0 0 0 } for (int i = 0; i < 4; i++) { //1 1 1 1 dia[6][0].space[0][i] = 1; //0 0 0 0 //0 0 0 0 //0 0 0 0 } int tmp[4][4]; for (int i = 0; i < 7; i++) //方塊種類 { for (int j = 0; j < 3; j++) //旋轉次數 { for (int k = 0; k < 4; k++) { for (int z = 0; z < 4; z++) { tmp[k][z] = dia[i][j].space[k][z]; } } for (int k = 0; k < 4; k++) { for (int z = 0; z < 4; z++) { dia[i][j + 1].space[k][z] = tmp[4 - z - 1][k]; } } } } } void GameInit(Game *pGame) { pGame->score = 0; pGame->speed = 300; display_face(&pGame->face, pGame->maxscore, pGame->score); } int color(int c) { switch (c) { case 0: c = 9; break; case 1: case 2: c = 12; break; case 3: case 4: c = 14; break; case 5: c = 10; break; case 6: c = 13; break; default: c = 7; break; } SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); return 0; }
Controller.c
#define _CRT_SECURE_NO_DEPRECATE 1 #include "Model.h" #include "view.h" #include "Windows.h" #include "time.h" #include "stdio.h" int n = 0; static void _Pause() { while (1) { Sleep(300); if (GetAsyncKeyState(VK_F1)) { break; } } } int pd_wall(Face* face, int nn, int space_c, int x, int y) //判斷是否到底 { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (dia[nn][space_c].space[i][j] == 0) continue; else if (face->data[y + i][x + j] == WALL || face->data[y + i][x + j] == BOX) return 0; } } return 1; } void go_game(Game* pGame) { int nn = 0; int x = FACE_X / 2 - 2; int y = 0; int space_c = 0; //旋轉次數 nn = n; n = rand() % 7; display_kong1(FACE_X + 3, 4); color(n); display_dia(n, space_c, FACE_X + 3, 4); while (1) { color(nn); display_dia(nn, space_c, x, y); Sleep(pGame->speed); if (pd_wall(&pGame->face, nn, space_c, x - 1, y + 1) == 1 && GetAsyncKeyState(VK_LEFT)) { display_kong(nn, space_c, x, y, pGame->face); x--; } else if (pd_wall(&pGame->face, nn, space_c, x + 1, y + 1) == 1 && GetAsyncKeyState(VK_RIGHT)) { display_kong(nn, space_c, x, y, pGame->face); x++; } else if (GetAsyncKeyState(VK_DOWN)) { pGame->speed = 50; } else if (GetAsyncKeyState(VK_UP)) { pGame->speed = 300; } else if (pd_wall(&pGame->face, nn, (space_c + 1) % 4, x + 1, y) == 1 && GetAsyncKeyState(VK_SPACE)) { display_kong(nn, space_c, x, y, pGame->face); space_c = (space_c + 1) % 4; } else if (GetAsyncKeyState(VK_ESCAPE)) { system("cls"); SetCurPos(FACE_X, FACE_Y / 2); printf("---遊戲結束!---\n\n"); SetCurPos(FACE_X, FACE_Y / 2 + 2); exit(0); } else if (GetAsyncKeyState(VK_F1)) { _Pause(); } else if (GetAsyncKeyState(VK_F2)) { main(); exit(0); } if (pd_wall(&pGame->face, nn, space_c, x, y + 1) == 1) { display_kong(nn, space_c, x, y, pGame->face); y++; } else { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (dia[nn][space_c].space[i][j] == 1) { pGame->face.data[y + i][x + j] = BOX; pGame->face.color[y + i][x + j] = nn; while (Remove(pGame)); } } } color(nn); display_dia(nn, space_c, x, y); return; } } } int Remove(Game *pGame) { int sum; int i; for (i = FACE_Y - 2; i > 4; i--) { sum = 0; for (int j = 1; j < FACE_X - 1; j++) { sum += pGame->face.data[i][j]; } if (sum == 0) { break; } if (sum == FACE_X - 2)//滿了一行 { pGame->score += 10; pGame->speed -= 2; color(7); SetCurPos(2 * FACE_X + 2, FACE_Y - 4); printf("分數:%d", pGame->score); for (int j = 1; j < FACE_X - 1; j++) { pGame->face.data[i][j] = KONG; SetCurPos(2 * j, i); printf(" "); } for (int j = i; j > 1; j--) { sum = 0; for (int k = 1; k < FACE_X - 1; k++) { sum += pGame->face.data[j][k] + pGame->face.data[j - 1][k]; pGame->face.data[j][k] = pGame->face.data[j - 1][k]; if (pGame->face.data[j][k] == KONG) { SetCurPos(2 * k, j); printf(" "); } else { SetCurPos(2 * k, j); color(pGame->face.color[j][k]); printf("█"); } } if (sum == 0) { return 1; } } } } for (int j = 1; j < FACE_X - 1; j++) { if (pGame->face.data[1][j] == BOX) { Sleep(2000); system("cls"); color(7); SetCurPos(2 * (FACE_X / 3), FACE_Y / 2 - 2); if (pGame->score > pGame->maxscore) { printf("恭喜打破紀錄,目前最高記錄:%d", pGame->score); write_maxscore(&pGame->score); } else if (pGame->score == pGame->maxscore) { printf("與記錄持平,繼續努力"); } else { printf("請繼續努力,離最高記錄只差:%d", pGame->maxscore - pGame->score); } SetCurPos(2 * (FACE_X / 3), FACE_Y / 2); printf("GAME OVER!"); SetCurPos(2 * (FACE_X / 3), FACE_Y / 2 + 2); printf("是否重新開始遊戲(F3/F4): "); if (GetAsyncKeyState(VK_F3)) { main(); } else if (GetAsyncKeyState(VK_F4)) { SetCurPos(2 * (FACE_X / 3), FACE_Y / 2 + 4); printf("按任意鍵退出遊戲!"); exit(0); } } } return 0; } int main() { system("cls"); system("title 俄羅斯方塊"); color(7); system("mode con cols=60 lines=30"); Game game; srand((unsigned)time(NULL)); read_maxscore(&game.maxscore); GameInit(&game); Init_dia(); hide_cursor(); n = rand() % 7; while (1) { go_game(&game); } return 0; }
View.h
#pragma once
#include "Model.h"
void dispay_menu();
void display_face(Face* face, int maxscore, int score);
void display_kong(int nn, int space_c, int x, int y, Face face);
void display_dia(int nn, int space_c, int x, int y);
void hide_cursor();
void SetCurPos(int X, int Y);
void display_kong1(int x, int y);
void read_maxscore(int* maxsorse);
void write_maxscore(int* maxsorse);
view.c
#define _CRT_SECURE_NO_DEPRECATE 1
#include "Model.h"
#include "Windows.h"
#include "stdio.h"
void SetCurPos(int X, int Y)
{
HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
// 標準輸入/標準輸出/標準錯誤輸出
COORD coord = { X, Y };
//設定終端游標位置
SetConsoleCursorPosition(hStdOutput, coord);
}
void hide_cursor()
{
HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
GetConsoleCursorInfo(hStdOutput, &info);
info.bVisible = 0;
SetConsoleCursorInfo(hStdOutput, &info);
}
void dispay_menu()
{
SetCurPos(27, 14);
printf("俄羅斯方塊");
SetCurPos(27, 16);
system("pause");
system("cls");
}
void display_face(Face* face, int maxscore, int score)
{
int i, j;
for (i = 0; i < FACE_Y; i++)
{
for (j = 0; j < FACE_X + 10; j++)
{
if (j == 0 || j == FACE_X - 1 || j == FACE_X + 9)
{
face->data[i][j] = WALL;
SetCurPos(2 * j, i);
printf("█");
}
else if (i == FACE_Y - 1)
{
face->data[i][j] = BOX;
SetCurPos(2 * j, i);
printf("█");
}
else
{
face->data[i][j] = KONG;
}
}
}
SetCurPos(2 * FACE_X + 2, FACE_Y - 18);
printf("左移:←");
SetCurPos(2 * FACE_X + 2, FACE_Y - 16);
printf("右移:→");
SetCurPos(2 * FACE_X + 2, FACE_Y - 14);
printf("旋轉:space");
SetCurPos(2 * FACE_X + 2, FACE_Y - 12);
printf("暫停: F1");
SetCurPos(2 * FACE_X + 2, FACE_Y - 10);
printf("退出: ESC");
SetCurPos(2 * FACE_X + 2, FACE_Y - 8);
printf("重新開始: F2");
SetCurPos(2 * FACE_X + 2, FACE_Y - 6);
printf("最高記錄:%d", maxscore);
SetCurPos(2 * FACE_X + 2, FACE_Y - 4);
printf("分數:%d", score);
}
void display_kong(int nn, int space_c, int x, int y, Face face)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
SetCurPos(2 * (x + j), i + y);
if (dia[nn][space_c].space[i][j] == 1 && face.data[i + y][j + x] != 1)
{
printf(" ");
}
}
}
}
display_kong1(int x, int y)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
SetCurPos(2 * (x + j), i + y);
printf(" ");
}
}
}
void display_dia(int nn, int space_c, int x, int y)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
SetCurPos(2 * (x + j), i + y);
if (dia[nn][space_c].space[i][j] == 1)
{
printf("█");
}
}
}
}
void read_maxscore(int* maxsorse)
{
FILE* pf;
pf = fopen("俄羅斯方塊記錄.txt", "rb");
if (NULL == pf)
{
perror("open file for read");
exit(EXIT_FAILURE);
}
fread(maxsorse, sizeof(int), 1, pf);
fclose(pf);
pf = NULL;
}
void write_maxscore(int* maxsorse)
{
FILE* pf;
pf = fopen("俄羅斯方塊記錄.txt", "wb");
if (NULL == pf)
{
perror("open file for write");
exit(EXIT_FAILURE);
}
fwrite(maxsorse, sizeof(int), 1, pf);
fclose(pf);
pf = NULL;
}