11 - 小练习(俄罗斯方块,C语言数组写法)

俄罗斯方块项目

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不能 1int 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();
	}
}

旋转算法

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值