游戏主窗体的设计
在欢迎界面选择1之后就会进入游戏主窗体的界面,此界面大致可分为两部分,第一部分是左侧的方块下落界面,另一部分是右侧的得分统计,下次出现的方块和主要的案件说明。
设计思路:
1)首先把游戏主窗体画出来;
2)绘制相应的俄罗斯方块;
3)其他部分;
1.打印输出游戏界面
为了实现这一个整体框架,如下代码:
/**
* 制作游戏窗口
*/
void DrwaGameframe()
{
gotoxy(FrameX+Frame_width-5,FrameY-2); //设置游戏名称的显示位置
color(11); //将字体颜色设置为亮蓝色
printf("趣味俄罗斯方块"); //打印游戏名称
gotoxy(FrameX+2*Frame_width+3,FrameY+7); //设置上边框的显示位置
color(2); //将字体颜色设置为深绿色
printf("**********"); //打印下一个出现方块的上边框
gotoxy(FrameX+2*Frame_width+13,FrameY+7);
color(3); //将字体颜色设置为深蓝绿色
printf("下一出现方块:");
gotoxy(FrameX+2*Frame_width+3,FrameY+13);
color(2);
printf("**********"); //打印下一个出现方块的下边框
gotoxy(FrameX+2*Frame_width+3,FrameY+17);
color(14); //将字体颜色设置为黄色
printf("↑键:旋转");
gotoxy(FrameX+2*Frame_width+3,FrameY+19);
printf("空格:暂停游戏");
gotoxy(FrameX+2*Frame_width+3,FrameY+15);
printf("Esc :退出游戏");
gotoxy(FrameX,FrameY);
color(12);
printf("╔"); //打印框角
gotoxy(FrameX+2*Frame_width-2,FrameY);
printf("╗");
gotoxy(FrameX,FrameY+Frame_height);
printf("╚");
gotoxy(FrameX+2*Frame_width-2,FrameY+Frame_height);
printf("╝");
a[FrameX][FrameY+Frame_height]=2; //记住该处已有图案
a[FrameX+2*Frame_width-2][FrameY+Frame_height]=2;
for(i=2;i<2*Frame_width-2;i+=2)
{
gotoxy(FrameX+i,FrameY);
printf("═"); //打印上横框
}
for(i=2;i<2*Frame_width-2;i+=2)
{
gotoxy(FrameX+i,FrameY+Frame_height);
printf("═"); //打印下横框
a[FrameX+i][FrameY+Frame_height]=2; //标记下横框为游戏边框,防止方块出界
}
for(i=1;i<Frame_height;i++)
{
gotoxy(FrameX,FrameY+i);
printf("║"); //打印左竖框
a[FrameX][FrameY+i]=2; //标记左竖框为游戏边框,防止方块出界
}
for(i=1;i<Frame_height;i++)
{
gotoxy(FrameX+2*Frame_width-2,FrameY+i);
printf("║"); //打印右竖框
a[FrameX+2*Frame_width-2][FrameY+i]=2; //标记右竖框为游戏边框,防止方块出界
}
}
形成代码如下:
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
#define FrameX 13 //游戏窗口左上角的X轴坐标为13
#define FrameY 3 //游戏窗口左上角的Y轴坐标为13
#define Frame_height 20 //游戏窗口的高度为20
#define Frame_width 18 //游戏窗口的宽度为18
/*******定 义 全 局 变 量 *******/
int i,j,Temp,Temp1,Temp2; //temp,temp1,temp2用于记住和转换方块变量的值
//标记游戏屏幕的图案:2,1,0分别表示该位置为游戏边框、方块、无图案;初始化为无图案
int a[80][80]={0};
int b[4]; //标记4个"口"方块:1表示有方块,0表示无方块
struct Tetris //声明俄罗斯方块的结构体
{
int x; //中心方块的x轴坐标
int y; //中心方块的y轴坐标
int flag; //标记方块类型的序号
int next; //下一个俄罗斯方块类型的序号
int speed; //俄罗斯方块移动的速度
int number; //产生俄罗斯方块的个数
int score; //游戏的分数
int level; //游戏的等级
};
HANDLE hOut; //控制台句柄
/*******函 数 声 明 *******/
int color(int c); //设置文字颜色
void gotoxy(int x, int y); //光标移到指定位置
void title(); //欢迎界面上方的标题
void close(); //关闭游戏
/**
* 文字颜色函数 此函数的局限性:1、只能Windows系统下使用 2、不能改变背景颜色
*/
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字颜色
return 0;
}
/**
* 获取屏幕光标位置
*/
void gotoxy(int x, int y)
{
COORD pos;
pos.X = x; //横坐标
pos.Y = y; //纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
/**
* 菜单选项边框
*/
/**
* 制作游戏窗口
*/
void DrwaGameframe()
{
gotoxy(FrameX+Frame_width-5,FrameY-2); //设置游戏名称的显示位置
color(11); //将字体颜色设置为亮蓝色
printf("趣味俄罗斯方块"); //打印游戏名称
gotoxy(FrameX+2*Frame_width+3,FrameY+7); //设置上边框的显示位置
color(2); //将字体颜色设置为深绿色
printf("**********"); //打印下一个出现方块的上边框
gotoxy(FrameX+2*Frame_width+13,FrameY+7);
color(3); //将字体颜色设置为深蓝绿色
printf("下一出现方块:");
gotoxy(FrameX+2*Frame_width+3,FrameY+13);
color(2);
printf("**********"); //打印下一个出现方块的下边框
gotoxy(FrameX+2*Frame_width+3,FrameY+17);
color(14); //将字体颜色设置为黄色
printf("↑键:旋转");
gotoxy(FrameX+2*Frame_width+3,FrameY+19);
printf("空格:暂停游戏");
gotoxy(FrameX+2*Frame_width+3,FrameY+15);
printf("Esc :退出游戏");
gotoxy(FrameX,FrameY);
color(12);
printf("╔"); //打印框角
gotoxy(FrameX+2*Frame_width-2,FrameY);
printf("╗");
gotoxy(FrameX,FrameY+Frame_height);
printf("╚");
gotoxy(FrameX+2*Frame_width-2,FrameY+Frame_height);
printf("╝");
a[FrameX][FrameY+Frame_height]=2; //记住该处已有图案
a[FrameX+2*Frame_width-2][FrameY+Frame_height]=2;
for(i=2;i<2*Frame_width-2;i+=2)
{
gotoxy(FrameX+i,FrameY);
printf("═"); //打印上横框
}
for(i=2;i<2*Frame_width-2;i+=2)
{
gotoxy(FrameX+i,FrameY+Frame_height);
printf("═"); //打印下横框
a[FrameX+i][FrameY+Frame_height]=2; //标记下横框为游戏边框,防止方块出界
}
for(i=1;i<Frame_height;i++)
{
gotoxy(FrameX,FrameY+i);
printf("║"); //打印左竖框
a[FrameX][FrameY+i]=2; //标记左竖框为游戏边框,防止方块出界
}
for(i=1;i<Frame_height;i++)
{
gotoxy(FrameX+2*Frame_width-2,FrameY+i);
printf("║"); //打印右竖框
a[FrameX+2*Frame_width-2][FrameY+i]=2; //标记右竖框为游戏边框,防止方块出界
}
}
int main()
{
DrwaGameframe();
return 0;
}
2.绘制俄罗斯方块:
首先有下列这五种基本类型:
另外还有两种镜像图形(原图形变换是得不到的):
加上这两种镜像图形,俄罗斯方块一共有7种基本类型,然而这7种基本类型旋转之后又会得到不同的旋转图形:
1)田字没有变换;
2)“T”字方块算上本体一共四种变换;
3)"Z"和反“Z”各有两种变换;
4)“7”和反“7”各有四种变换;
5)直线方块有横竖两种变换;
一共有19种类型,这19种类型我们都要考虑!!!
/**
* 制作俄罗斯方块
*/
void MakeTetris(struct Tetris *tetris)
{
a[tetris->x][tetris->y]=b[0]; //中心方块位置的图形状态
switch(tetris->flag) //共7大类,19种类型
{
case 1: /*田字方块 ■■
■■ */
{
color(10);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 2: /*直线方块 ■■■■*/
{
color(13);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y]=b[2];
a[tetris->x+4][tetris->y]=b[3];
break;
}
case 3: /*直线方块 ■
■
■
■ */
{
color(13);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y-2]=b[2];
a[tetris->x][tetris->y+1]=b[3];
break;
}
case 4: /*T字方块 ■■■
■ */
{
color(11);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y]=b[2];
a[tetris->x][tetris->y+1]=b[3];
break;
}
case 5: /* 顺时针90°T字方块 ■
■■
■*/
{
color(11);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y]=b[3];
break;
}
case 6: /* 顺时针180°T字方块 ■
■■■*/
{
color(11);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 7: /* 顺时针270°T字方块 ■
■■
■ */
{
color(11);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 8: /* Z字方块 ■■
■■*/
{
color(14);
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x+2][tetris->y+1]=b[3];
break;
}
case 9: /* 顺时针Z字方块 ■
■■
■ */
{
color(14);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x-2][tetris->y+1]=b[3];
break;
}
case 10: /* 反转Z字方块 ■■
■■ */
{
color(14);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 11: /* 顺时针Z字方块 ■
■■
■ */
{
color(14);
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x-2][tetris->y]=b[3];
break;
}
case 12: /* 7字方块 ■■
■
■ */
{
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y-1]=b[3];
break;
}
case 13: /* 顺时针90°7字方块 ■
■■■ */
{
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 14: /* 顺时针180°7字方块 ■
■
■■ */
{
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y+1]=b[3];
break;
}
case 15: /* 顺时针270°7字方块 ■■■
■ */
{
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x-2][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 16: /* 反转7字方块 ■■
■
■ */
{
color(12);
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y-1]=b[3];
break;
}
case 17: /* 顺时针转90°7字方块 ■■■
■*/
{
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
case 18: /* 顺时针转180°7字方块 ■
■
■■ */
{
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y+1]=b[3];
break;
}
case 19: /* 顺指针转270°7字方块 ■
■■■*/
{
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
}
}
此段代码还有部分解释:
1.方块是如何画出来的:
1)我们使用的这个小方块,横向占据两个字符,纵向占据一个字符;
2)我们可以看到这些俄罗斯方块的共同点,都是有四个小方块组成;
3)基于2)我们在全局变量之中定义了数组b[4],用于保存四个小方块的位置;
4)具体如何保存:首先我们保存的是中心小方块的位置,之后基于它来定位;
2.关于我们此处使用到的坐标轴:
3.设置不同类型方块的颜色
1)因为共有7各大类,我们就可以设置7种颜色,
2)用事先定义好的color函数来设置颜色,将这个函数放在打印方块的前面,那么打印出来的就是已经设置好颜色的方块
4.使用switch分支语句做主体
注意:
1)switch后面的括号之中的表达式就是要进行判断的条件;
2)当表达式的值与某一个case后面括号里的值相等时,就执行case后面的语句;
3)若没有匹配的就执行default语句
4.打印俄罗斯方块
在上一部分我们知识定义好了俄罗斯方块的大致形状,还并没有选择用什么符号去打印,接下来要做的就是用符号“小方块”组成俄罗斯方块:
/**
* 打印俄罗斯方块
*/
void PrintTetris(struct Tetris *tetris)
{
for(i=0;i<4;i++) //数组b[4]中有4个元素,循环这4个元素,让每个元素的值都为1
{
b[i]=1; //数组b[4]的每个元素的值都为1
}
MakeTetris(tetris); //制作游戏窗口
for( i=tetris->x-2; i<=tetris->x+4; i+=2 )
{
for(j=tetris->y-2;j<=tetris->y+1;j++) //循环方块所有可能出现的位置
{
if( a[i][j]==1 && j>FrameY ) //如果这个位置上有方块
{
gotoxy(i,j);
printf("■"); //打印边框内的方块
}
}
}
//打印菜单信息
gotoxy(FrameX+2*Frame_width+3,FrameY+1); //设置打印位置
color(4);
printf("level : ");
color(12);
printf(" %d",tetris->level); //输出等级
gotoxy(FrameX+2*Frame_width+3,FrameY+3);
color(4);
printf("score : ");
color(12);
printf(" %d",tetris->score); //输出分数
gotoxy(FrameX+2*Frame_width+3,FrameY+5);
color(4);
printf("speed : ");
color(12);
printf(" %dms",tetris->speed); //输出速度
}
实际上在上述代码中不仅打印了方块,还打印了得分信息,速度,等级信息