看下游戏界面:

C语言实现俄罗斯方块-LMLPHP

不知道怎么介绍,直接上代码:

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;
}

我的GitHub中游戏链接

10-14 04:35