您的位置:首页 > 编程语言 > C语言/C++

C语言版 彩色俄罗斯方块 控制台输出

2015-10-28 14:52 302 查看
       本代码由vc++6.0编译通过,属于本人三个晚上的作品,没什么优化 仅供学习娱乐专用。不用添加任何库文件。直接下载编译即可运行。下载地址在本文末尾处!

效果图:













源码:

/////////////////////////////////////////////////////////////////////////////////////////////////
//          名称:   俄罗斯方块 彩色版1.1.0//
//          语言:   C语言                                                        //
//上一版本:   俄罗斯方块 彩色版1.0.0//
//增加功能:   增加关卡 和 最高分//
//          环境:   Microsoft Visual C++ 6.0        //
//          作者:   鼠标猎人//
//          日期:   2015年1月19号//
/////////////////////////////////////////////////////////////////////////////////////////////////
#include<stdio.h>
#include <windows.h>
#include<conio.h>
#include<time.h>
#define _WIN32_WINNT    0x0500
void gotoxy(int x,int y);//控制光标。X表示横坐标,Y表示纵坐标
void console();//设置控制台窗口大小,为了让程序运行得更好看
void my_print();//设置界面
void my_randout();//随机出现方块,并打印在提示区
void my_printblock();//打印 4*4 的方格来显示方块
void my_up();//旋转
void my_down();//下移
void my_lift();//左移
void my_right();//右移
void my_exit();//退出前保存最高分
void clear();//消除整行
void gameover();//游戏结束
void my_stop();//游戏暂停
int  tem[4][4];//用4*4的方格来控制方块的操作和显示 这个作为传值媒介
int  block[4][4];//提示区的方块
int  BLOCK[4][4];//正在下落的方块
int  scope[25][34] = {0};//操作的范围 这里要注意,一个方格是占两个横坐标单位的
int  point_x , point_y;//方格的左上角坐标
int  fen = 0;//得分
int  pass = 1;//关卡  新增
int  hang = 0;//消除的总行数
int  max_fen = 0;//最高分 新增
FILE *fp;
bool check = true;//检查方块还能不能下落
int  block0[4][4] = {{0,1,1,0},{0,0,1,0},{0,0,1,0},{0,0,0,0}};// 7 个方块 用数组表示 正“7”
int  block1[4][4] = {{0,1,1,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}};// 反“7”
int  block2[4][4] = {{0,0,0,0},{0,0,1,1},{0,1,1,0},{0,0,0,0}};// 反“z”
int  block3[4][4] = {{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}};// 正“z”
int  block4[4][4] = {{0,0,0,0},{0,1,0,0},{1,1,1,0},{0,0,0,0}};// 倒“T”
int  block5[4][4] = {{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}};// 正方形
int  block6[4][4] = {{0,0,0,0},{0,0,0,0},{1,1,1,1},{0,0,0,0}};// 直条

void main()
{
if ((fp = fopen("test.txt","r") )== NULL)
{
fp = fopen("test.txt","w+");//打开文件 如果没有就创建
}
srand((unsigned)time(NULL));//设置随机数种子
char key;
int  i , j;
fscanf(fp, "%d", &i);
max_fen = max_fen>i?max_fen:i;//将最高分赋给max_fen
fclose(fp);//关闭文件
int time;//控制下落时间
console();
my_print();
my_randout();
while( true )//死循环
{
if( check )//如果没有正在下落的方块就执行if里面的
{
check = false;
point_x = 14;//方块最初出现的地方
point_y = 0;
for( i=0 ; i < 4 ; i++)
{
for( j = 0 ; j < 4 ; j++)
{
BLOCK[i][j] = block[i][j];//将提示区的方块数组传到下落的方块数组
}
}
my_printblock();//在point_x,point_y显示方块。
my_randout();//提示区随机换一个方块
}
if (kbhit()) //检测,如果有按键就执行if里面的
{
key = getch();//捕获按键
switch( key )
{
case 72:my_up();//上
break;
case 75:my_lift();//左
break;
case 77:my_right();//右
break;
case 80:my_down();//下
break;
case 32:my_stop();//空格 暂停或开始
break;
case 27:my_exit();//Esc 退出
default: ;
}
}
Sleep(30);//等待0.03秒 0.03秒才能执行一个按键 也降低CPU
if( 0 == ++time % (32 - pass*3))//控制下落的时间=30*30毫秒
{
my_down();//时间到自动下落一格
}
if( true == check)//当不能下落时
{
for( i=0 ; i < 4 ; i++)
{
for( j = 0 ; j < 4 ; j++)
{
if( 1 == BLOCK[i][j])
scope[point_x / 2 + j][point_y + i] = BLOCK[i][j];//把下落的方块赋值给操作区的数组
//这里的point_x除以2是因为一个小格子占两个横坐标
}
}
my_printblock();
clear();//如果有某一行满了就消除
}
}
}
//设置窗口位置和大小,为了让程序运行得更好看
void console()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息
GetConsoleScreenBufferInfo(hOut, &bInfo );// 获取窗口缓冲区信息
SetConsoleTitle("俄罗斯方块 C版"); // 设置窗口的标题
COORD size = {80, 32};//不能小于默认大小(80,25)
SetConsoleScreenBufferSize(hOut,size); // 重新设置缓冲区大小*/
SMALL_RECT rc = {0,0, 63, 31}; //不能大于缓冲区大小
SetConsoleWindowInfo(hOut,true ,&rc);// 重置窗口大小
CONSOLE_CURSOR_INFO cursor_info = {1, 0}; //第一个参数光标百分比大小。第二个参数是否可见。
SetConsoleCursorInfo(hOut, &cursor_info);//设置控制台光标
}

void my_print()
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE|FOREGROUND_INTENSITY);//黑底亮蓝字。
for(int i = 1 ; i < 30 ; i++)
printf("■\t\t\t\t■ |                           |\n");
printf("■■■■■■■■■■■■■■■■■ |---------------------------|\n");//框架
gotoxy(36,0);
printf("---------------------------");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN | FOREGROUND_RED |FOREGROUND_INTENSITY);//黑底亮黄字。
gotoxy(40,2);
printf("关  卡: %d",pass);
gotoxy(40,3);
printf("分  数: %d",fen);
gotoxy(40,4);
printf("最高分: %d",max_fen);
gotoxy(36,6);
printf("下一个方块:");
gotoxy(36,14);
printf("操作方法:");
gotoxy(40,16);
printf("↑:旋转 ↓:沉淀");
gotoxy(40,18);
printf("→:右移 ←:左移");
gotoxy(39,20);
printf("空格键:开始 / 暂停");
gotoxy(39,22);
printf("    Esc:退出");
gotoxy(36,25);
printf("关 于:");
gotoxy(40,26);
printf("俄罗斯方块 1.2.0");
gotoxy(49,27);
printf("作者:鼠标猎人");
gotoxy(50,28);
printf("2015年1月19日");
}

//设置光标输出的位置函数。坐标不能为负数
void gotoxy(int x,int y)//X表示横坐标,Y表示纵坐标。
{
HANDLE app;
COORD  pos;
pos.X=x;
pos.Y=y;
app=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(app,pos);
}
//旋转 将4*4方格顺时针旋转
void my_up()
{
int i,j;
for( i=0 ; i < 4 ; i++)
{
for( j = 0 ; j < 4 ; j++)
{
tem[i][j] = BLOCK[i][j];
if( 1 == BLOCK[i][j])
{
gotoxy(point_x + j*2 , point_y + i);
printf("  ");
}
}
}
for( i=0 ; i < 4 ; i++)
{
for( j = 0 ; j < 4 ; j++)
{
BLOCK[j][3-i] = tem[i][j];
}
}
//以上为旋转。
//下面为防止旋转后超出框架范围
for( j = 0 ; j < 2 ; j++)
{
for( i = 0 ; i < 4 ; i++)
{
if (1 == BLOCK[i][j] )
{
if(point_x+2*j < 2)
{
point_x+=2;
j--;
break;
}
else if(1 == scope[point_x / 2 + j][point_y + i] || 1 == scope[point_x / 2 + 3 - j][point_y + i])
{
for( i=0 ; i < 4 ; i++)//顺270度
{
for( j = 0 ; j < 4 ; j++)
{
BLOCK[i][j] = tem[i][j];
}
}
break;
}
}
if (1 == BLOCK[i][3-j])
{
if(point_x + 2 * (3-j)> 30)
{
point_x-=2;
j--;
break;
}
}
}
}
my_printblock();//旋转之后立即显示出来
}
//左移
void my_lift()
{
int i , j ;
for(  i = 0 ; i < 3 ; i++ )
for( j = 0 ; j < 4 ; j++ )
{
if(1 == BLOCK[j][i] && (point_x+2*i-1
4000
< 2 || 1 == scope[point_x / 2 + i - 1][point_y + j]))
{
return ;//如果到边缘 或者是左边已经有了方块
}
}
for( i = 0 ; i  < 4 ; i++ )
for( j = 0 ; j < 4 ; j++ )
if( 1 == BLOCK[i][j])
{
gotoxy(point_x + j*2 , point_y + i);
printf("  ");//把之前的擦掉
}
point_x -= 2;
my_printblock();
}

void my_right()
{
int i , j ;
for(  i = 3 ; i > 0 ; i-- )
for( j = 0 ; j < 4 ; j++ )
{
if(1 == BLOCK[j][i] && ( point_x+2*i+2 > 30 || 1 == scope[point_x / 2 + i + 1][point_y + j]))
{
return ;//如果到边缘 或者是右边已经有了方块
}
}
for( i = 0 ; i  < 4 ; i++ )
for( j = 0 ; j < 4 ; j++ )
if( 1 == BLOCK[i][j])
{
gotoxy(point_x + j*2 , point_y + i);
printf("  ");//把之前的擦掉
}
point_x += 2;
my_printblock();
}

void my_down( )
{
int i , j ;
if( true == check)
{
return ;//不能下落直接不执行
}
gotoxy(point_x,point_y);
for( i = 3 ; i >= 0 ; i-- )//检测该方格还能不能下落
for( j = 0 ; j  < 4 ; j++ )
if ( 1 == BLOCK[i][j] )
{
if (1 == scope[point_x / 2 + j][point_y + i + 1] || point_y + i + 1 > 28 ) //到最下边或是下面已经有方格
{
check = true;
return ;
}
}
for( i = 0 ; i  < 4 ; i++ )
for( j = 0 ; j < 4 ; j++ )
if( 1 == BLOCK[i][j])
{
gotoxy(point_x + j*2 , point_y + i);
printf("  ");//能下落,擦除以前的方格
}
point_y++;
my_printblock();//在下一格显示
}
//暂停
void my_stop()
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_INTENSITY);
gotoxy(10,10);printf("              ");
gotoxy(10,11);printf("  ■■■■■  ");
gotoxy(10,12);printf("  ■      ■  ");
gotoxy(10,13);printf("  ■      ■  ");
gotoxy(10,14);printf("  ■■■■■  ");
gotoxy(10,15);printf("  ■          ");
gotoxy(10,16);printf("  ■           ");
gotoxy(10,17);printf("  ■          ");
gotoxy(10,18);printf("              ");
while (true)
{
int n = getch();
if(32 == n)
{
gotoxy(10,10);printf("              ");
gotoxy(10,11);printf("  ■■■■■  ");
gotoxy(10,12);printf("          ■  ");
gotoxy(10,13);printf("          ■  ");
gotoxy(10,14);printf("  ■■■■■  ");
gotoxy(10,15);printf("          ■  ");
gotoxy(10,16);printf("          ■  ");
gotoxy(10,17);printf("  ■■■■■  ");
gotoxy(10,18);printf("              ");
Sleep(1000);
gotoxy(10,10);printf("              ");
gotoxy(10,11);printf("  ■■■■■  ");
gotoxy(10,12);printf("          ■  ");
gotoxy(10,13);printf("          ■  ");
gotoxy(10,14);printf("  ■■■■■  ");
gotoxy(10,15);printf("  ■          ");
gotoxy(10,16);printf("  ■          ");
gotoxy(10,17);printf("  ■■■■■  ");
gotoxy(10,18);printf("              ");
Sleep(1000);
gotoxy(10,10);printf("              ");
gotoxy(10,11);printf("      ■■    ");
gotoxy(10,12);printf("    ■■■    ");
gotoxy(10,13);printf("      ■■    ");
gotoxy(10,14);printf("      ■■    ");
gotoxy(10,15);printf("      ■■    ");
gotoxy(10,16);printf("      ■■    ");
gotoxy(10,17);printf("    ■■■■  ");
gotoxy(10,18);printf("              ");
Sleep(1000);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY);
for(int i = 0 ; i < 9 ; i++)//将暂停掩盖的方块再次显示出来
{
gotoxy(10  , 10 + i );
for(int j = 0 ; j < 7 ; j++ )
{
if (1 == scope[5 + j][10 + i])
{
printf("■");
}
else
{
printf("  ");
}
}
}
return ;
}
else if (27 == n)
{
my_exit();
}
}
}
//消除
void clear()
{
int i , j , k , m = 0;
for(i = point_y + 3 ; i >= point_y ; i-- )
{
for( j = 1 ; j < 16 ; j++ )
{
if( 0 == scope[j][i] )
{
break ;
}
}
if ( 16 == j )
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY);
m++;
for(k=i;k>3;k--)
{
for( j = 1 ; j < 16 ; j++ )
{
scope[j][k] = scope[j][k - 1];
gotoxy(j*2 , k );
if (1 == scope[j][k])
{
printf("■");
}
else
{
printf("  ");
}
}
}
for( j = 1 ; j < 16 ; j++ )
{
scope[j][4] = 0;
}
i++;
}
}
switch(m) {//判断一次消除了几行,来设置得分数
case 1: fen+=100;
break;
case 2: fen+=230;
break;
case 3: fen+=438;
break;
case 4: fen+=854;
break;
default: ;
}
hang += m ;
if( hang > 10 )//每10行升一关
{
hang = 0 ;
pass++;
}
max_fen = max_fen>fen?max_fen:fen;//更新最高分
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN | FOREGROUND_RED |FOREGROUND_INTENSITY);//黑底亮黄色字。
gotoxy(40,2);
printf("关  卡: %d",pass);
gotoxy(40,3);
printf("分  数: %d",fen);
gotoxy(40,4);
printf("最高分: %d",max_fen);
for( j = 7 ; j < 11 ; j++ )
{
if(1 == scope[j][4])
gameover();
}
}
//随机出现方块
void my_randout()
{
int i,j;
switch( rand()%7 )
{
case 0:for(i=0 ; i < 4 ; i++)
for(j = 0 ; j < 4 ; j++)
block[i][j] = block0[i][j];
break;
case 1: for(i=0 ; i < 4 ; i++)
for(j = 0 ; j < 4 ; j++)
block[i][j] = block1[i][j];
break;
case 2: for(i=0 ; i < 4 ; i++)
for(j = 0 ; j < 4 ; j++)
block[i][j] = block2[i][j];
break;
case 3: for(i=0 ; i < 4 ; i++)
for(j = 0 ; j < 4 ; j++)
block[i][j] = block3[i][j];
break;
case 4: for(i=0 ; i < 4 ; i++)
for( j = 0 ; j < 4 ; j++)
block[i][j] = block4[i][j];
break;
case 5: for( i=0 ; i < 4 ; i++)
for( j = 0 ; j < 4 ; j++)
block[i][j] = block5[i][j];
break;
case 6: for( i=0 ; i < 4 ; i++)
for( j = 0 ; j < 4 ; j++)
block[i][j] = block6[i][j];
break;
default: ;
}
for( i=0 ; i < 4 ; i++)
{
for( j = 0 ; j < 4 ; j++)
{
tem[i][j] = block[i][j];
}
}
switch( rand()%4 )//再设置随机旋转的方向
{
case 0 :
break;
case 1 : for( i=0 ; i < 4 ; i++)//顺时针90度
{
for( j = 0 ; j < 4 ; j++)
{
block[j][3-i] = tem[i][j];
}
}
break;
case 2 : for( i=0 ; i < 4 ; i++)//顺180度
{
for( j = 0 ; j < 4 ; j++)
{
block[3-i][3-j] = tem[i][j];
}
}
break;
case 3 : for( i=0 ; i < 4 ; i++)//顺270度
{
for( j = 0 ; j < 4 ; j++)
{
block[3-j][i] = tem[i][j];
}
}
break;
default: ;
}
//打印提示区的方块
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_INTENSITY);//黑底亮红字。
for( i=0 ; i < 4 ; i++)
{
gotoxy(44 , 8 + i);
for( j = 0 ; j < 4 ; j++)
{
if(1 == block[i][j])
{
printf("■");
}
else
{
printf("  ");
}
}
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);//黑底白字
}

//显示方格
void my_printblock()
{
int  i , j ;
for( i=0 ; i < 4 ; i++)
{
for( j = 0 ; j < 4 ; j++)
{
if (point_x / 2 + j > 0  )
{
if ( 1 == scope[point_x / 2 + j][point_y + i])
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY);
gotoxy(point_x + j*2 , point_y + i);
printf("■");
}
else if (1 == BLOCK[i][j])
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
gotoxy(point_x + j*2 , point_y + i);
printf("■");
}
}
}
}
}
void gameover()
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
gotoxy(4,10);printf("                                                        ");
gotoxy(4,11);printf("    ■■■      ■      ■      ■■■■      ■■■■  ");
gotoxy(4,12);printf("  ■      ■    ■      ■      ■            ■    ■  ");
gotoxy(4,13);printf("  ■      ■      ■  ■        ■■■■      ■■■■  ");
gotoxy(4,14);printf("  ■      ■      ■  ■        ■            ■■      ");
gotoxy(4,15);printf("    ■■■          ■          ■■■■      ■  ■    ");
gotoxy(4,16);printf("                                                        ");
gotoxy(32,17);printf("空格键:重来\tEsc:退出");
while(true)
{
int n = getch();
switch( n )
{
case 32: system("cls");//清屏
console();
memset(scope, 0, sizeof(int) * 25 * 34);//数组清零
fen = 0;
hang = 0;
pass = 1;
my_print();//输出界面
my_randout();
return;
case 27: my_exit();
return;
default:;
}
}
}
void my_exit()//退出前保存最高分
{
fp = fopen("test.txt","w");
fprintf(fp, "%d\n", max_fen);
fclose(fp);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_INTENSITY);
gotoxy(12,12);printf("================================");
gotoxy(12,13);printf("||  游戏已退出 按任意键关闭! ||");
gotoxy(12,14);printf("================================");
gotoxy(0,30);
exit(0);
}

完整代码下载地址:点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: