IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言——俄罗斯方块小游戏 -> 正文阅读

[C++知识库]C语言——俄罗斯方块小游戏

最近正在学习C语言,于是自己就写了个俄罗斯方块小游戏,本想找一篇博文借鉴一下的,粗略的找了一圈并没有找到,于是花了2天搞了一下。初学者,代码粗陋,大佬勿喷。有哪里不对的,请不吝赐教,谢谢~
废话不多说,上图:
在这里插入图片描述
代码开始运行检测C:\GameTetris.dat文件是否是合法的存档,如果是则提示用户游戏有存档,是否读取。
按下N,则删除存档,新建新的游戏,重新开始。
按下Y,则读取文档,从上次状态保存的状态开始运在这里插入图片描述我按下了Y,所以程序读取了存档。

1、键盘信号获取
由 _kbhit(),_getch() ,函数获取
_kbhit()检测有没有键按下
_getch()读取键值

2、方块的产生
通过srand,与rand 函数实现随机产生

3、控制台
一个方块占2个横向空格长度,1个纵向空格长度,所以代码中会频繁出现横坐标 * 2的代码

4、旋转方块
我的方法是选一个中心点作为坐标原点,根据这个原点画一个坐标系,其余4个子方块在这个坐标系中相对原点的位置偏移存储在BlockXY blockXY[4];中,centerXY结构体就是原点的实际坐标,那么其余3个子方块的实际坐标就可以根据这个中心点算出来。
而左移,右移,下移都只需要移动这个中心点的实际坐标即可。
下方堆积的方块是使用一个二维数组在存储,二维数组的成员等于1,则在对应坐标上就有一个堆积方块。

一些代码函数什么的参考了如下博文(一篇讲C语言贪吃蛇的):
https://blog.csdn.net/qq_40953281/article/details/79315254

接下来上代码:(我是用VC6.0写的)

// 俄罗斯方块.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#include "windows.h"
#include "conio.h"
#include "time.h"

#define FilePath "C:\\GameTetris.dat"
#define GameX 24
#define GameY 36
#define SPEED 5  //数值越大速度越慢
//颜色
enum
{
	BLACK,
	BLUE,
	GREEN,
	CYAN,
	RED,
	MAGENTA,
	BROWN,
	LIGHTGRAY,
	DARKGRAY,
	LIGHTBLUE,
	LIGHTGREEN,
	LIGHTCYAN,
	LIGHTRED,
	LIGHTMAGENTA,
	YELLOW,
	WHITE
};
//方块元素
struct BlockXY
{
	int x;
	int y;
	int xiangXian;//方块所处相对中心点而言的象限
};
//方块形状
struct BlockShape
{
	BlockXY blockXY[4];//方块元素相对中心点的坐标
	BlockXY center;//中心旋转轴点的坐标
	int type;//方块类型
};
BlockShape* G_pBlockShape1 = NULL, *G_pBlockShape2 = NULL;
char name[200];
int score;//得分
//指令集:  w 旋转  a 左  s 下  d 右  o 结束游戏并保存   p 暂停游戏
char KEYVALUESET[] = {'w', 'a', 's', 'd', 'o', 'p', ' '};
int G_BlockScreenArr[GameX][GameY] = {0};//初始化标记已经落下堆积后的全屏方块位置二维数组, 0代表没有方块,1代表有方块


/************************************************************************/
/*光标跳转到指定位置*/
/************************************************************************/
void gotoxy(int x, int y, int ForgC)
{
	if(ForgC == -1)
	{
		ForgC = LIGHTGREEN;
	}
	

    // 更新光标位置 
    COORD pos;
	WORD wColor;
    HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(hOutput, pos);
	
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	
	if(GetConsoleScreenBufferInfo(hOutput, &csbi))
	{
		//设置字体颜色
		wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
		SetConsoleTextAttribute(hOutput, wColor);
	}
	// 隐藏光标 
    CONSOLE_CURSOR_INFO cursor;
    cursor.bVisible = FALSE;
    cursor.dwSize = 1;	//值介于1 ~ 100 之间 单元格底部为下划线 ~ 完全填充单元格
    SetConsoleCursorInfo(hOutput, &cursor);
	
}
/************************************************************************/
/*光标跳转到指定位置(函数重载)*/
/************************************************************************/
void gotoxy(int x, int y)
{
	gotoxy(x, y, -1);
}
/************************************************************************/
/*指定位置打印游戏边框*/
/************************************************************************/
int switchFlag = 0;
void gotoprint(int x, int y)
{
	int color = (switchFlag = ! switchFlag) ? LIGHTGRAY : LIGHTRED;
    gotoxy(x * 2, y, color);
    printf("■");
}
/************************************************************************/
/*从指定位置开始清除指定长度元素*/
/************************************************************************/
void gotodelete(int x, int y, int length)
{
	int i;
    
	for (i = 0; i < length; i++)
	{
		gotoxy(x + i, y);
		printf(" ");
	}
}
/************************************************************************/
/*清除指定位置元素*/
/************************************************************************/
void gotodelete(int x, int y)
{
	gotodelete(x, y, 1);
}
/************************************************************************/
/* 绘制游戏边框 */
/************************************************************************/
void drawGameMap()
{
	int i;
	//初始化左侧游戏窗口
	for (i = 0; i < GameX; i++)
	{
		gotoprint(i, 0);
	}
	for (i = 0; i < GameX; i++)
	{
		gotoprint(i, GameY);
	}
	for (i = 0; i < GameY; i++)
	{
		gotoprint(0, i);
	}
	for (i = 0; i < GameY; i++)
	{
		gotoprint(GameX, i);
	}

	//初始化右侧小窗口
	for (i = 0; i < 8; i++)
	{
		gotoprint(i + GameX + 2, 0);
	}
	for (i = 0; i < 8; i++)
	{
		gotoprint(i + GameX + 2, 7);
	}
	for (i = 0; i < 8; i++)
	{
		gotoprint(GameX + 2, i);
	}
	for (i = 0; i < 8; i++)
	{
		gotoprint(GameX + 2 + 7, i);
	}
}
/************************************************************************/
/*显示方块*/
/************************************************************************/
void showBlockShape(BlockShape* pBlockShape)
{
	int i;
	BlockXY *pBlockXY = pBlockShape->blockXY;
	
	for (i = 0; i < 4; i++)
	{
		gotoxy(pBlockXY[i].x + pBlockShape->center.x, pBlockXY[i].y * -1 + pBlockShape->center.y);
		printf("■");
	}
}
/************************************************************************/
/* 初始化游戏开始界面*/
/************************************************************************/
bool initGameScreen(int state)
{
	int i, j;
	bool result;
	char keyValue;

	system("title 俄罗斯方块 by 机智蛋");
	result = false;

    gotoxy(15, 10);
    printf("/**********************************************/");
    gotoxy(15, 22);
    printf("/**********************************************/");
    gotoxy(20, 13);
    printf("WELCOME TO THE GAME OF TETRIS");
    gotoxy(14, 16);
	printf("W:左移 D:右移 S:下移  空格:下落到底部  P暂停  O结束游戏并保存");
    gotoxy(20, 18);
	if(state)
	{
		printf("游戏有存档,是否读取?Y/N");
		while(1)
		{
			keyValue = _getch();
			if(keyValue == 'Y' || keyValue == 'y')//同意读档
			{
				result = true;
				break;
			}
			else if(keyValue == 'N' || keyValue == 'n')//不同意读档
			{
				DeleteFileA(FilePath); //删除存档
				score = 0;
				free(G_pBlockShape1);
				free(G_pBlockShape2);
				G_pBlockShape1 = NULL;
				G_pBlockShape2 = NULL;
				for (i = 0; i < GameX; i++)
				{
					for (j = 0; j < GameY; j++)
					{
						G_BlockScreenArr[i][j] = 0;
					}
				}
				result = false;
				break;
			}
		}
	}
	if(! result)		//不同意读档或无存档
	{
		gotodelete(20, 18, 30);
		gotoxy(20, 18);

		printf("PLEASE ENTER YOUR NAME:");
		scanf("%s", name);
	}
   	system("CLS");
	
    gotoxy(53, 20);
    printf("hello %s,Welcome To Play", name);
    gotoxy(53, 25);
    printf("Your Score Is:%d    = ̄ω ̄= ", score);
    gotoxy(53, 30);
    printf("This Game Is Created By 机智蛋");

	if(result)
	{//恢复存档堆积方块图
		for (i = 0; i < GameX; i++)
		{
			for (j = 0; j < GameY; j++)
			{
				if(G_BlockScreenArr[i][j] == 1)
				{
					gotoxy(i * 2, j);
					printf("■");
				}
			}
		}
		//恢复移动方块图
		showBlockShape(G_pBlockShape1);
		G_pBlockShape2->center.x = (GameX + 5) * 2;
		G_pBlockShape2->center.y +=2; 
		//恢复下一个方块图
		showBlockShape(G_pBlockShape2);
	}

	return result;
}
/************************************************************************/
/* 初始化游戏开始界面(函数重载)*/
/************************************************************************/
int initGameScreen()
{
	return initGameScreen(0);
}
/************************************************************************/
/* 游戏结束处理*/
/************************************************************************/
void FinishGame()
{
    system("CLS");
    gotoxy(15, 10);
    printf("/**********************************************/");
    gotoxy(15, 20);
    printf("/**********************************************/");
    gotoxy(18, 14);
    printf("GAME   OVER      o(* ̄▽ ̄*)o");
    gotoxy(20, 16);
    printf("Your Score is %d    ", score);
    gotoxy(18, 18);
    printf("还不错哦,     继续努力O(∩_∩)O");
    gotoxy(0, 27);

	gotoxy(0, 27);
    system("pause");
}

/************************************************************************/
/*顺时针旋转方块*/
/************************************************************************/
void rotateBlock(BlockShape* pBlockShape)
{
	int i, tmp, realX, realY;
	bool forbit;
	BlockXY blockXY;
	BlockXY centerXY;
	
	centerXY = pBlockShape->center;
	forbit = false;
	if(pBlockShape->type == 3)//如果是方形方块,则不做旋转
	{
		return;
	}

	//删除原来的点
	for (i = 0; i < 4; i++)
	{
		blockXY.x = pBlockShape->blockXY[i].x;
		blockXY.y = pBlockShape->blockXY[i].y;
		gotodelete(blockXY.x + pBlockShape->center.x, blockXY.y * -1 + pBlockShape->center.y);
	}
	//旋转
	for (i = 0; i < 4; i++)
	{
		blockXY.x = pBlockShape->blockXY[i].x;
		blockXY.y = pBlockShape->blockXY[i].y;
		blockXY.xiangXian = pBlockShape->blockXY[i].xiangXian;
		//根据象限不同决定旋转后xy的偏移
		switch(blockXY.xiangXian)
		{
		case 1:
			{
				tmp = blockXY.x;
				blockXY.x = blockXY.y * 2;
				blockXY.y = tmp / 2;
				blockXY.y *= -1;
				blockXY.xiangXian = 4;
				break;
			}
		case 2:
			{
				tmp = blockXY.x * -1;
				blockXY.x = blockXY.y * 2;
				blockXY.y = tmp / 2;
				blockXY.xiangXian = 1;
				break;
			}
		case 3:
			{
				tmp = blockXY.x;
				blockXY.x = blockXY.y * 2;
				blockXY.y = tmp / 2 * -1;
				blockXY.xiangXian = 2;
				break;
			}
		case 4:
			{
				tmp = blockXY.x;
				blockXY.x = blockXY.y * 2;
				blockXY.y = tmp / 2 * -1;
				blockXY.xiangXian = 3;
				break;
			}
		}
		//检查真实坐标是否超出边界,如超出则移动中心点位置
		realX = blockXY.x + centerXY.x;
		if(realX <= 0)
		{
			centerXY.x += realX * -1 + 2;//旋转时如超出左边边界,则中心点向右移动
		}
		else if(realX >= GameX * 2)
		{
			centerXY.x -= realX - GameX * 2 + 2;//旋转时如超出右边边界,则中心点向左移动
		}
		realY = blockXY.y * -1 + centerXY.y;
		if(realY <= 0)
		{
			centerXY.y += realY * -1 + 1;//旋转时如超出顶部边界,则中心点向下移动
		}
		else if(realY >= GameY)//旋转时如碰到底部边框,则不允许旋转
		{
			forbit = true;
			break;
		}
		if(G_BlockScreenArr[realX /2 ][realY] == 1)//旋转时如碰到其他方块则不允许旋转
		{
			forbit = true;
			break;
		}
		if(! forbit)
		{
			pBlockShape->center = centerXY;
			pBlockShape->blockXY[i].x = blockXY.x;
			pBlockShape->blockXY[i].y = blockXY.y;
			pBlockShape->blockXY[i].xiangXian = blockXY.xiangXian;
		}

	}
	showBlockShape(pBlockShape);//旋转之后显示移动方块图
	
}
/************************************************************************/
/*
方块移动
@type 0 下落 1左移 2右移
return 返回true 已到底部   返回false 未到底部
*/
/************************************************************************/
bool dropBlockShape(BlockShape* pBlockShape, int type)
{
	int i, realX, realY;
	BlockXY blockXY;
	bool forbit = false;
	BlockXY centerXY;

	centerXY = pBlockShape->center;

	switch(type)
	{
	case 0://下落
		{
			centerXY.y++;
			break;
		}
	case 1:
		{
			centerXY.x-=2;//1个方块横向占2个空,纵向占1个空,所以x +- 2,y +- 1
			break;
		}
	case 2:
		{
			centerXY.x+=2;
			break;
		}
	default:
		{
			return false;
		}
	}

	for (i = 0; i < 4; i++)
	{
		blockXY.x = pBlockShape->blockXY[i].x;
		blockXY.y = pBlockShape->blockXY[i].y;

		//检查真实坐标是否超出边界,如超出则禁止移动
		realX = blockXY.x + centerXY.x;
		if(realX <= 0)
		{
			return false;
		}
		else if(realX >= GameX * 2)
		{
			return false;
		}
		realY = blockXY.y * -1 + centerXY.y;
		if(realY >= GameY)//已到底部则停止下落
		{
			return true;
		}
		else if(G_BlockScreenArr[realX / 2][realY] == 1)//判断是否碰到其他方块,是则停止下落
		{
			return true;
		}
	}
	//删除原来的点
	for (i = 0; i < 4; i++)
	{
		blockXY.x = pBlockShape->blockXY[i].x;
		blockXY.y = pBlockShape->blockXY[i].y;
		gotodelete(blockXY.x + pBlockShape->center.x, blockXY.y * -1 + pBlockShape->center.y);
	}
	pBlockShape->center = centerXY;
	showBlockShape(pBlockShape);//显示移动后的方块图
	return false;

}

/************************************************************************/
/* 生成新的方块*/
/************************************************************************/
BlockShape* creatBlockShape()
{	
	BlockShape* pBlockShape = (BlockShape*)malloc(sizeof(BlockShape));

	pBlockShape->type = rand() % 7;  //总共7种方块
	
	switch (pBlockShape->type)
	{
	case 0:// 直条方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 1;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = 2;
			pBlockShape->blockXY[2].y = 0;
			pBlockShape->blockXY[2].xiangXian = 1;
			pBlockShape->blockXY[3].x = 4;
			pBlockShape->blockXY[3].y = 0;
			pBlockShape->blockXY[3].xiangXian = 1;
			break;
		}
	case 1 :// L1型方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 1;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = 2;
			pBlockShape->blockXY[2].y = 0;
			pBlockShape->blockXY[2].xiangXian = 1;
			pBlockShape->blockXY[3].x = -2;
			pBlockShape->blockXY[3].y = -1;
			pBlockShape->blockXY[3].xiangXian = 3;
			break;
		}
	case 2:// L2型方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 1;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = 2;
			pBlockShape->blockXY[2].y = 0;
			pBlockShape->blockXY[2].xiangXian = 1;
			pBlockShape->blockXY[3].x = 2;
			pBlockShape->blockXY[3].y = -1;
			pBlockShape->blockXY[3].xiangXian = 4;
			break;
		}
	case 3:// 方型方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 1;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = -2;
			pBlockShape->blockXY[2].y = -1;
			pBlockShape->blockXY[2].xiangXian = 3;
			pBlockShape->blockXY[3].x = 0;
			pBlockShape->blockXY[3].y = -1;
			pBlockShape->blockXY[3].xiangXian = 4;
			break;
		}
	case 4:// 倒Z型方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 2;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = 0;
			pBlockShape->blockXY[2].y = 1;
			pBlockShape->blockXY[2].xiangXian = 2;
			pBlockShape->blockXY[3].x = 2;
			pBlockShape->blockXY[3].y = 1;
			pBlockShape->blockXY[3].xiangXian = 1;
			break;
		}
	case 5:// Z型方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 1;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = 0;
			pBlockShape->blockXY[2].y = -1;
			pBlockShape->blockXY[2].xiangXian = 4;
			pBlockShape->blockXY[3].x = 2;
			pBlockShape->blockXY[3].y = -1;
			pBlockShape->blockXY[3].xiangXian = 4;
			break;
		}
	case 6:// T型方块
		{
			pBlockShape->center.x = GameX;
			pBlockShape->center.y = 2;

			pBlockShape->blockXY[0].x = -2;
			pBlockShape->blockXY[0].y = 0;
			pBlockShape->blockXY[0].xiangXian = 3;
			pBlockShape->blockXY[1].x = 0;
			pBlockShape->blockXY[1].y = 0;
			pBlockShape->blockXY[1].xiangXian = 0;
			pBlockShape->blockXY[2].x = 2;
			pBlockShape->blockXY[2].y = 0;
			pBlockShape->blockXY[2].xiangXian = 1;
			pBlockShape->blockXY[3].x = 0;
			pBlockShape->blockXY[3].y = 1;
			pBlockShape->blockXY[3].xiangXian = 2;
			break;
		}
	}
	return pBlockShape;
}
/************************************************************************/
/*读档游戏*/
/************************************************************************/
bool readGameFile()
{
	FILE *fp;
	int blockScreenArr[GameX][GameY] = {0};
	int s, i, j;
	BlockShape *pBlockShape1, *pBlockShape2;

	if((fp = fopen(FilePath, "rb")) == NULL)
	{
		return 0;
	}
	pBlockShape1 = (BlockShape*)malloc(sizeof(BlockShape));
	pBlockShape2 = (BlockShape*)malloc(sizeof(BlockShape));

	fread(blockScreenArr, sizeof(blockScreenArr), 1, fp);
	fread(pBlockShape1, sizeof(BlockShape), 1, fp);
	fread(pBlockShape2, sizeof(BlockShape), 1, fp);
	fread(&s, sizeof(int), 1, fp);
	fread(name, sizeof(name), 1, fp);
	fclose(fp);
	if(pBlockShape1->type > 6 || pBlockShape1->type < 0 || pBlockShape2->type> 6 || pBlockShape2->type < 0 || s < 0)
	{
		free(pBlockShape1);
		free(pBlockShape2);
		return false;
	}
	G_pBlockShape1 = pBlockShape1;
	G_pBlockShape2 = pBlockShape2;
	score = s;
	for (i = 0; i < GameX; i++)
	{
		for (j = 0; j < GameY; j++)
		{
			G_BlockScreenArr[i][j] = blockScreenArr[i][j];
		}
	}
	return true;

}
/************************************************************************/
/*保存游戏*/
/************************************************************************/
void saveGame()
{
	FILE *fp;
	
	if((fp = fopen(FilePath, "wb")) == NULL)
	{
		gotoxy(0, 27);
		printf("游戏保存失败\n");
		return;
	}
	fwrite(G_BlockScreenArr, sizeof(G_BlockScreenArr), 1, fp);
	fwrite(G_pBlockShape1, sizeof(BlockShape), 1, fp);
	fwrite(G_pBlockShape2, sizeof(BlockShape), 1, fp);
	fwrite(&score, sizeof(score), 1, fp);
	fwrite(name, sizeof(name), 1, fp);
	fclose(fp);
}
/************************************************************************/
/*判断按键*/
/************************************************************************/
bool jugeKeyValue(char key)
{
	int i;
	for (i = 0; i < sizeof(KEYVALUESET); i++)
	{
		if(key == KEYVALUESET[i])
		{
			break;
		}
	}
	if(i >= sizeof(KEYVALUESET))		//判断按键是否在指令集中,如不在其中则不做处理
	{
		return true;
	}
	if(key == 'o')	//结束游戏并保存
	{
		saveGame();
		FinishGame();
		return false;
	}
	else if(key == 'p')//暂停游戏
	{
		gotoxy(0, GameY + 2);
		printf("按任意键继续......");
		_getch();
		gotodelete(0, GameY + 2, 20);
	}
	else if(key == 'w')//旋转方块
	{
		rotateBlock(G_pBlockShape1);
	}
	else if(key == 'a')//左移方块
	{
		dropBlockShape(G_pBlockShape1, 1);//左移
	}
	else if(key == 'd')//右移方块
	{
		dropBlockShape(G_pBlockShape1, 2);//右移
	}
	return true;
}
/************************************************************************/
/*将方块各个点的坐标在全屏方块二维数组中标记出来*/
/************************************************************************/
void addInBlockScreenArr(BlockShape* pBlockShape)
{
	int i;
	for (i = 0; i < 4; i++)
	{
		G_BlockScreenArr[(pBlockShape->blockXY[i].x + pBlockShape->center.x) / 2][pBlockShape->blockXY[i].y * -1 + pBlockShape->center.y]
			= 1;
	}
}
/************************************************************************/
/*检测堆积的方块是否到达顶端
return  true 到达顶端  false 未到达
*/
/************************************************************************/
bool checkBlockReachTop()
{
	int i;
	for (i = 1; i < GameX; i++)
	{
		if(G_BlockScreenArr[i][1] == 1)
		{
			return true;
		}
	}
	return false;
}
/************************************************************************/
/*检测某一行的方块是否已满并消除
return  true 代表有一行方块消除  false 代表无消除
*/
/************************************************************************/
bool checkBlockLineIsFull()
{
	int i, j, count;
	for (j = GameY - 1; j > 0; j--)
	{
		count = 0;
		for (i = 1; i < GameX; i++)
		{
			if(G_BlockScreenArr[i][j] == 1)
			{
				count++;
			}
		}
		if(count == GameX - 1)//一行已满
		{
			score++;
			gotoxy(67, 25);
			printf("%d", score);	//打印分数

			for (i = 1; i < GameX; i++)//消除一行方块,并标记消除
			{
				gotodelete(i * 2, j);
				G_BlockScreenArr[i][j] = 0;
			}
			Sleep(300);
			//被消除的一行上方所有方块全部下移一行
			for (j = j - 1; j > 0; j--)
			{
				count = 0;
				for (i = 1; i < GameX; i++)
				{
					gotodelete(i * 2, j);
					if(G_BlockScreenArr[i][j] == 1)
					{
						G_BlockScreenArr[i][j] = 0;
						count++;
						G_BlockScreenArr[i][j + 1] = 1;
						gotoxy(i * 2, j + 1);
						printf("■");
					}
				}
				if(count == 0)
				{
					break;
				}
			}
			return true;
		}
		else if(count == 0)//如果这一行没有方块,则说明检测的堆积方块到达最高度
		{
			return false;
		}
	}
	return false;
}
int main(int argc, char* argv[])
{
	char c;
	bool onBottom, dropFast;
	int speedCount = 0;
	int i;

	dropFast = false;//快速下落

	srand(time(0));

	initGameScreen(readGameFile());//检测游戏存档并初始化游戏显示

	drawGameMap();//绘制游戏边框
	while(1)
	{
		if (_kbhit())//判断是否有按键按下
        {
            c = _getch();//读取按下的键值
			if(! jugeKeyValue(c))		//判断指令是否合法
			{
				return 0;
			}
        }
		if(G_pBlockShape2 == NULL)//创建新的方块
		{
			G_pBlockShape2 = creatBlockShape();
			if(G_pBlockShape1 == NULL)
			{
				G_pBlockShape1 = G_pBlockShape2;
				G_pBlockShape2 = NULL;
			}
			else
			{
				//右侧小窗口显示下一个要出现的方块
				G_pBlockShape2->center.x = (GameX + 5) * 2;
				G_pBlockShape2->center.y +=2; 
				showBlockShape(G_pBlockShape2);
			}
			showBlockShape(G_pBlockShape1);
		}
		if(c == ' ')//按下空格快速下落
		{
			dropFast = true;
		}
		if(c == 's' || dropFast || speedCount++ == SPEED)//按下s 或 按下空格   或  自动下落
		{
			speedCount = 0;
 			onBottom = dropBlockShape(G_pBlockShape1, 0);//下落,true则无法下落
			if(onBottom)
			{
				dropFast = false;
				if(checkBlockReachTop())//检测是否到达边界顶点
				{
					FinishGame();
					return 0;
				}
				addInBlockScreenArr(G_pBlockShape1);//将方块各个成员在全屏二维数组坐标中标记
 				while(checkBlockLineIsFull()){};//循环一行一行的消除
				free(G_pBlockShape1);
				//清除右侧小窗口中显示的方块
				for (i = 0; i < 4; i++)
				{
					gotodelete(G_pBlockShape2->center.x + G_pBlockShape2->blockXY[i].x, G_pBlockShape2->center.y + G_pBlockShape2->blockXY[i].y * -1);
				}
				//将下一个方块置为当前移动的方块
				G_pBlockShape1 = G_pBlockShape2;
				G_pBlockShape1->center.x = GameX;
				G_pBlockShape2->center.y -=2; 
 				G_pBlockShape2 = NULL;
			}
		}
		
		Sleep(100);
		c = '\0';


	}
	return 0;
}


全篇完~

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:19:22  更:2021-08-01 14:21:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 5:17:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码