俄罗斯方块项目
1.分文件的创建
game.h
game.c
main.c
2.游戏主体编辑
1. main.c模块
#define _CRT_SECURE_NO_WARNINGS 1
#include"Game.h"
void main()
{
srand((unsigned)time(NULL));
GmaeLoop();
}
2. game.h模块
#pragma once
#include<stdio.h>
#include<conio.h> //改变光标的头文件
#include<stdlib.h>
#include<Windows.h>
#include<time.h>//时间函数头文件
#define GAME_ROWS 20
#define GAME_COLS 14
//初始化背景
void InitBackGround();
//显示背景
void ShowBackGround();
//游戏循环
void GmaeLoop();
//放置方块
void PutBlock();
//删除方块
void DeleteBlock();
//设置光标
void MoveTo(int x, int y);
//判断是否移动--//1是可以移动 0不能移动
int IsBlockMove(int nX, int nY);
//生成新的方块
void CreateBlock();
//处理输入
void ProcessingInput();
//是否可以消行
int IsDeteleLine(int nRow);
//消行
void DeteleLine();
//旋转
void Rotate();
2. game.c模块
全局变量
int scort = 0;//分数
int maxTime = 1000;//下落间隔
int Grade = 1;//等级
int BackGround[GAME_ROWS][GAME_COLS] = { 0 };//背景数组
int Block[4][4] = { 0 };//方块数组
int x;//方块的起始位置x坐标
int y;//方块的起始位置y坐标
int nTime = 0;//最大时间间隔
int NextBlock[4][4] = { 0 };//下一个模块
//产生2种方块的数组
int Two[2][4][4] =
{
0, 0, 0, 0,
0, 1, 1, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0
};
//7种方块的总数组
int Blocks[7][4][4] =
{
0, 0, 0, 0,
0, 1, 1, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
0, 1, 1, 0,
0, 0, 1, 0,
0, 0, 0, 0,
0, 0, 1, 0,
0, 1, 1, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 1, 0, 0,
1, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
游戏循环的主体
//游戏循环
void GmaeLoop()
{
InitBackGround();
CreateBlock();
while (1)
{
PrintExplain();//打印说明
MoveTo(0, 0);//设置光标到0.0
ShowBackGround();//,打印整体背景
AutoDown();//自动下落
ProcessingInput();//手动输入
}
}
各功能模块封装
/判断是否可以移动 0不能 1能
int IsBlockMove(int nX, int nY)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (Block[i][j] == 1)
{
if (BackGround[nY + i][nX + j] == 1)
{
return 0;
}
}
}
}
return 1;
}
//产生新的方块
void CreateBlock()
{
x = 5;
y = 0;
//随机一个方块
int nType = rand() % 8;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
Two[1][i][j] = Blocks[nType][i][j];
}
}
//第一个拿来用
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
//
Block[i][j] = Two[0][i][j];
//把后面一个给前一个
Two[0][i][j] = Two[1][i][j];
//显示下一个
NextBlock[i][j] = Two[1][i][j];
}
}
if (!IsBlockMove(x,y))//1是可以移动 0不能移动
{
printf("GAME OVER");
exit(0);
}
}
//移动光标
void MoveTo(int x1, int y1)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = { x1,y1 };
SetConsoleCursorPosition(handle, coord);
}
//初始化
void InitBackGround()
{
for (int i = 0; i < GAME_ROWS; i++)
{
for (int j = 0; j < GAME_COLS; j++)
{
if (j == 0 || i == GAME_ROWS - 1 || j == GAME_COLS - 1)
{
BackGround[i][j] = 1;
}
else
{
BackGround[i][j] = 0;
}
}
}
}
//显示背景
void ShowBackGround()
{
for (int i = 0; i < GAME_ROWS; i++)
{
for (int j = 0; j < GAME_COLS; j++)
{
if (BackGround[i][j] == 0)
{
printf(" ");//▢
}
else
{
printf("■");
}
}
printf("\n");
}
}
//放置方块
void PutBlock()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (Block[i][j] == 1)
{
BackGround[y + i][x + j] = 1;
}
}
}
}
//删除方块
void DeleteBlock()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (Block[i][j] == 1)
{
BackGround[y + i][x + j] = 0;
}
}
}
}
//旋转
void Rotate()
{
int temp[4][4] = {0};
//先拷贝原来的形状
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
temp[i][j] = Block[i][j];
}
}
//旋转
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
Block[i][j] = temp[j][3 - i];
}
}
//判断旋转后的图形是否撞墙了
int ret = 1;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (BackGround[y + i][x + j] == 1 && Block[i][j] == 1)
{
ret = 0;
}
}
}
//撞墙就还原
if (ret == 0)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
Block[i][j] = temp[i][j];
}
}
}
}
//处理输入
void ProcessingInput()
{
if (!_kbhit())//如果按键返回真
{
return;
}
char ch = _getch();
if (ch >= 'A' && ch <= 'Z')
{
ch += 32;
}
switch (ch)
{
case ' ':
{
DeleteBlock();
while (IsBlockMove(x,y+1))
{
y++;
}
PutBlock();
DeteleLine();
CreateBlock();
break;
}
case 'w':
DeleteBlock();
Rotate();
PutBlock();
break;
case 'a':
{
DeleteBlock();
if (IsBlockMove(x - 1, y))
{
x--;
PutBlock();
}
else
{
PutBlock();
}
break;
}
case 's':
{
DeleteBlock();
if (IsBlockMove(x, y + 1))
{
y++;
PutBlock();
}
else
{
PutBlock();
DeteleLine();
CreateBlock();
}
break;
}
case 'd':
{
DeleteBlock();
if (IsBlockMove(x + 1, y))
{
x++;
PutBlock();
}
else
{
PutBlock();
}
break;
}
default:
break;
}
}
//判断是否可以消行
int IsDeteleLine(int nRow)
{
for (int nCol = 0; nCol < GAME_COLS; nCol++)
{
if (BackGround[nRow][nCol] == 0)
{
return 0;
}
}
return 1;
}
//消行
void DeteleLine()
{
for (int nRow = 0; nRow < GAME_ROWS-1; nRow++)
{
if (IsDeteleLine(nRow))
{
//可以消行+
scort += 10; //分数+10
Grade++; //等级+10
maxTime -= 50; //时间加快
for (int i = nRow; i >= 0; i--)
{
for (int j = 1; j < GAME_COLS-1; j++)
{
BackGround[i][j] = BackGround[i - 1][j];
}
}
//在判断一次
nRow--;
}
}
}
void PrintExplain()
{
MoveTo(30, 3);
printf("等级: %d", Grade);
MoveTo(30, 4);
printf("分数: %d", scort);
MoveTo(30, 6);
printf("游戏按键:");
MoveTo(30, 7);
printf("A左移 D右移");
MoveTo(30, 8);
printf("W旋转 S下落");
MoveTo(30, 9);
printf("下一个方块:");
for (int i = 0; i < 4; i++)
{
MoveTo(30, 11 + i);
for (int j = 0; j < 4; j++)
{
if (NextBlock[i][j] == 1)
{
printf("■");
}
else
{
printf(" ");
}
}
}
}
//自动下落
void AutoDown()
{
//自动下落
if (clock() - nTime > maxTime)
{
DeleteBlock();
if (IsBlockMove(x, y + 1))
{
y++;
PutBlock();
}
else
{
PutBlock();
DeteleLine();
CreateBlock();
}
nTime = clock();
}
}
旋转算法