俄罗斯方块

俄罗斯方块(C语言)
小白初写,大佬勿喷。
#ifndef MYWINDOWS_H_INCLUDED
#define MYWINDOWS_H_INCLUDED

/系统调用模块/

#include<windows.h>
//初始化句柄
void initHandle();

//设置颜色
void setColor(int color);

//设置光标位置
void setPos(int x,int y);

//隐藏光标
void hideCursor();
#endif // MYWINDOWS_H_INCLUDED

#include “windows.h”

HANDLE handle;

void initHandle(){
handle =GetStdHandle(STD_OUTPUT_HANDLE);
hideCursor();
}
void setColor(int color){
SetConsoleTextAttribute(handle,color);

}
void setPos(int x,int y){
COORD coord={x*2,y};
SetConsoleCursorPosition(handle,coord);
}
void hideCursor(){
CONSOLE_CURSOR_INFO info;
info.bVisible=FALSE; //设置光标是否可见
SetConsoleCursorInfo(handle,&info);
info.dwSize=1; //设置光标的宽度
}

#ifndef DATA_H_INCLUDED
#define GAME_H_INCLUDED

/游戏逻辑模块/

#include<stdio.h>
#include<time.h>
///方块结构体
typedef struct{
int x;
int y;
int shape;
int status;
int color;

}BLOCK;

///绘制游戏池边框
void windowPrint(int x,int y);

///游戏初始化
void gameInit();

///打印操作说明
void printInfo();

///打印分数等级
void printGradeLeve(int num);

///游戏计时
void gameTime(clock_t star_time);

///打印方块
void printBlock(int x,int y,int shape,int status,int color);
///删除方块
void deleteBlock(int x,int y,int shape,int status);
///产生游戏的第一个方块
void startBlock();
///产生下一个方块
void nextBlock();
///拷贝方块
void copyBlock();
///方块下移
///返回值:标志方块是否到游戏池底部
int downBlock();
///方块左移
void leftBlock();
///方块右移
void rightBlock();

///方块暂停
int stopBlock();

///方块变形
void changeBlock();
///碰撞检测
int crash(int x,int y,int shape,int status);
///保存方块
void save();
///刷新游戏池
void updataGame();
///暂停
void pause();
///方块直接落到游戏池的底部
void bottomBlock();
///消行检测
void lineClear();
///消行下移
void lineDown(int line);
///游戏结束动画
void printOver();
///重新开始提示
void printFinish();
///重新开始游戏
void againGame();
///打印开始图案
void printStart(int x,int y);
///清除开始动画
void deleteStart(int x,int y);
///动画效果-》定时(边界控制)
void printAnimation();

#endif // GAME_H_INCLUDED

#include “game.h”
#include “data.h”
#include “mywindows.h”
#include <conio.h>

#include <mmsystem.h>
#pragma comment (lib, “winmm.lib”) ///播放音乐头文件

int grade = 0; ///分数
int level = 1; ///等级

BLOCK cur_block; ///当前方块
BLOCK next_block; ///下一个方块

void windowPrint(int x,int y)
{
int i,j;
for(i=0;i<25;i++)
{
for(j=0;j<26;j++)
{
if(windowShape[i][j] == 1)
{
setColor(0xc0);
setPos(x+j,y+i);
printf("%2s",""); //==> printf(" ");
}
}
}
}

void printInfo()
{
setColor(0x0a);

setPos(31,9);
printf("操作规则:");
setPos(31,10);
printf("按 a 或 A 左移");
setPos(31,11);
printf("按 d 或 D 右移");
setPos(31,12);
printf("按 s 或 S下移");
setPos(31,13);
printf("按 w 或 W 变形");
setPos(31,14);
printf("按 回车 直接下落");
setPos(31,15);
printf("按 空格 暂停");

}

void printGradeLeve(int num)
{
switch(num)
{
case 0:
break;
case 1:
grade += 10;break;
case 2:
grade += 30;break;
case 3:
grade += 50;break;
case 4:
grade += 80;break;
}

setColor(0x09);
setPos(3,6);
printf("分数:%d",grade);

setPos(3,7);
printf("等级:%d", level);
  setPos(0,18);
printf("~●█〓██▄▄▄▄▄▄ ● ●");
setPos(0,19);
printf("▄▅██████▅▄▃▂");
setPos(0,20);
printf("██████████████");
setPos(0,21);

printf("◥⊙▲⊙▲⊙▲⊙▲⊙▲⊙▲◤ ");

}

void gameTime(clock_t start_time)
{
setColor(0x0b);
setPos(3,3);
printf(“本次游戏已运行 %ld s”,(clock()-start_time)/CLOCKS_PER_SEC);
}

void printBlock(int x, int y, int shape, int status, int color)
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[shape][status][i][j] == 1)
{
setColor(color);
setPos(x+j,y+i);
printf(“■”);
}
}
}
}

void deleteBlock(int x, int y, int shape, int status)
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[shape][status][i][j] == 1)
{
setPos(x+j, y+i);
printf("%2s","");
}
}
}
}

void startBlock()
{
///第一个方块:形状/形态/颜色->随机 位置(x,y)固定的
///初始化cur_block
///设置随机数种子(时间永远不一样)
srand((unsigned)time(NULL));
cur_block.x = 22;
cur_block.y = 1;
cur_block.shape = rand()%7;
cur_block.status = rand()%4;
cur_block.color = rand()%0x10; ///0x00-0x0f
///如果随机产生的颜色是黑色,把颜色设置成白色
if(cur_block.color == 0x00)
{
cur_block.color = 0x0f;
}
printBlock(cur_block.x,cur_block.y,cur_block.shape,
cur_block.status,cur_block.color);
}

void nextBlock()
{
///形状/形态/颜色->随机,位置->固定的
///初始化next_block值
deleteBlock(next_block.x,next_block.y,
next_block.shape,next_block.status);
next_block.x = 34;
next_block.y = 2;
next_block.shape = rand()%7;
next_block.status = rand()%4;
next_block.color = rand()%0x10;
if(next_block.color == 0x00)
{
next_block.color = 0x0f;
}
printBlock(next_block.x,next_block.y,next_block.shape,
next_block.status,next_block.color);
}

void copyBlock()
{
///当前方块=下一个方块,并产生新的"下一个方块"
cur_block = next_block;
cur_block.x = 22;
cur_block.y = 1;
printBlock(cur_block.x,cur_block.y, cur_block.shape,
cur_block.status, cur_block.color);
nextBlock();
}

int downBlock()
{
///原理:删除正在显示的方块,纵坐标+1,重新打印
if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status) == -1)
{
///发生碰撞:方块落底游戏池底部
///产生新的方块:下一个方块值->当前正在下落的方块,重新产生下一个方块
///保存方块->检测消行->打印游戏池->产生新方块
save();
lineClear();
updateGame();
copyBlock();
return -1;
}else if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status) == -2)
{
///游戏结束
return -2;
}else{
deleteBlock(cur_block.x,cur_block.y,
cur_block.shape, cur_block.status);
cur_block.y += 1;
printBlock(cur_block.x,cur_block.y,cur_block.shape,
cur_block.status,cur_block.color);
return 0;
}
}

void leftBlock()
{
if(crash(cur_block.x-1,cur_block.y,cur_block.shape,cur_block.status) == -1)
{
///如果发生碰撞,什么都不做,直接返回
return;
}
deleteBlock(cur_block.x,cur_block.y,
cur_block.shape, cur_block.status);
cur_block.x -= 1;
printBlock(cur_block.x,cur_block.y,cur_block.shape,
cur_block.status,cur_block.color);
}

void rightBlock()
{
if(crash(cur_block.x+1,cur_block.y,cur_block.shape,cur_block.status) == -1)
{
///如果发生碰撞,什么都不做,直接返回
return;
}
deleteBlock(cur_block.x,cur_block.y,
cur_block.shape, cur_block.status);
cur_block.x += 1;
printBlock(cur_block.x,cur_block.y,cur_block.shape,
cur_block.status,cur_block.color);
}

void changeBlock()
{
///通过数组下标+1获得下一个形态,下标[0-3]
if(crash(cur_block.x,cur_block.y,cur_block.shape,(cur_block.status+1)%4) == -1)
{
return;
}
deleteBlock(cur_block.x,cur_block.y,
cur_block.shape, cur_block.status);
cur_block.status = (cur_block.status+1)%4;
printBlock(cur_block.x,cur_block.y,cur_block.shape,
cur_block.status,cur_block.color);
}

int crash(int x, int y, int shape, int status)
{
///基于下一个位置的检测,参数为下一个位置或下一个形态
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[shape][status][i][j] == 1)
{
if(windowShape[i+y][j+x-15] == 1)
{
///发生碰撞
if(cur_block.x == 22 && cur_block.y == 1)
{
///方块产生就发生碰撞,游戏结束
return -2;
}
///方块落到游戏池底部,发生碰撞
return -1;
}
}
}
}
return 0;
}

void save()
{
///根据方块在界面上的坐标,把坐标对应到游戏池下标的对应位置
///方块为1的保存到windowShape数组
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[cur_block.shape][cur_block.status][i][j] == 1)
{
windowShape[i+cur_block.y][j+cur_block.x-15] = 1;
}
}
}
}

void updateGame()
{
int i,j;
for(i=23;i>0;i–)
{
for(j=1;j<15;j++)
{
if(windowShape[i][j] == 1)
{
setColor(0x0e);
setPos(15+j,i);
printf(“■”);
}else{
setColor(0x00);
setPos(15+j,i);
printf("%2s","");
}
}
}
}

void pause()
{
while(1)
{
if(getch() == 32)
{
break;
}
}
}

void bottomBlock()
{
while(1)
{
if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status) == -1)
{
///发生碰撞
save();
lineClear();
updateGame();
copyBlock();
return;
}else if(crash(cur_block.x,cur_block.y+1,cur_block.shape,cur_block.status) == -2)
{
///游戏结束
return;
}else{
++cur_block.y;
}
}
}

void lineClear()
{
///遍历windowShape,判断是否有满行:这行所有值加起来为14
int i,j;
int number = 0;
for(i=23;i>0;i–)
{
int total = 0;
for(j=1;j<15;j++)
{
total += windowShape[i][j];
}
if(14 == total)
{
lineDown(i);
i += 1;
///统计一次消几行
number += 1;
}
}
printGradeLeve(number);
}

void lineDown(int line)
{
///从第line行开始,i = i-1
int i,j;
for(i=line;i>1;i–) ///i>1,保证边界不被下移
{
for(j=1;j<15;j++)
{
windowShape[i][j] = windowShape[i-1][j];
}
}
}

void printOver()
{
int i,j;
for(i=23;i>0;i–)
{
for(j=1;j<15;j++)
{
setColor(0x76);
setPos(j+15,i);
printf(“★”);
Sleep(5);
}
}
}

void printFinish()
{
setColor(0x0d);
setPos(20,8);
printf("游戏结束! ");
setPos(17,9);
printf("按Y重新开始 ");
setPos(23,9);
printf("按N结束游戏 ");

///检测用户按键
switch(getch())
{
case 'y':
case 'Y':
    againGame();break;
case 'n':
case 'N':
    ///关闭音乐
    mciSendString(TEXT("stop a"), NULL, 0, NULL);
    break;
default:
    printFinish();break;
}

}

void againGame()
{
/// 重置分数\等级\游戏池数据->开始游戏
level = 1;
grade = 0;

///重置游戏池数组
int i,j;
for(i=1;i<24;i++)
{
    for(j=1;j<15;j++)
    {
        windowShape[i][j] = 0;
    }
}
setColor(0x00);
system("cls");      ///清屏
gameInit();

}

void printStart(int x, int y)
{
///随机图案颜色
int color = rand()%0x10;
if(color == 0x00)
{
color = 0x0f;
}

///绘制图案
setColor(color);
setPos(x,y);
printf("■■■■■  ■■■■■  ■■■■■ ■■■■  ■■■  ■■■■");
setPos(x,y+1);
printf("    ■      ■              ■     ■    ■    ■    ■");
setPos(x,y+2);
printf("    ■      ■■■■        ■     ■■■■    ■      ■■■");
setPos(x,y+3);
printf("    ■      ■              ■     ■  ■      ■          ■");
setPos(x,y+4);
printf("    ■      ■■■■■      ■     ■    ■  ■■■  ■■■");

setPos(25,15);
printf("按任意键开始游戏!");

}

void deleteStart(int x, int y)
{
int i,j;
for(i=y;i<=y+4;i++)
{
for(j=x;j<=x+33;j++)
{
setPos(j,i);
printf("%2s","");
}
}
}

void printAnimation()
{
clock_t time1,time2;
time1 = clock();
int x = 5;
printStart(x,5);
while(1)
{
time2 = clock();
if(time2-time1 > 300) ///时间间隔300ms
{
time1 = time2;
deleteStart(x,5);
printStart(++x,5);
if(25 == x)
{
deleteStart(x,5);
x=5;
}
}
///按任意键退出:检测是否有按键输入,若有则返回一个非0值,否则返回0
if(kbhit())
{
break;
}
}
system(“cls”);
}

void gameInit()
{
///初始化句柄,必须放在最开始
initHandle();
///打开音乐文件
mciSendString(“open D:\shixun\project\tetris\bin\Debug\俄罗斯方块游戏背景音乐.mp3 alias a”,
NULL,0,NULL);
///播放音乐
mciSendString(TEXT(“play a”), NULL, 0, NULL);

///开始动画
printAnimation();
windowPrint(15,0);
printInfo();
printGradeLeve(0);

///游戏开始时间
clock_t startTime = clock();

///定时器
clock_t time1,time2;
time1 = clock();

startBlock();
nextBlock();

while(1)
{
    ///检测是否有按键按下
    if(kbhit())
    {
        switch(getch())
        {
        case 'w':
        case 'W':
        case 72:
            ///方块变形
            changeBlock();break;
        case 'a':
        case 'A':
        case 75:
            ///方块左移
            leftBlock();break;
        case 'd':
        case 'D':
        case 77:
            ///方块右移
            rightBlock();break;
        case 's':
        case 'S':
        case 80:
            ///方块下移
            downBlock();break;
        case 32:
            ///暂停
            pause();break;
        case 13:
            ///方块落底
            bottomBlock();break;
        }
    }
    time2 = clock();
    ///每0.45s下落一次
    ///(time2-time1)/CLOCKS_PER_SEC > 0.45
    if(time2-time1>0.45*CLOCKS_PER_SEC)
    {
        ///游戏计时
        gameTime(startTime);
        if(downBlock() == -2)
            break;
        time1 = time2;
    }
}
printOver();
printFinish();

}

#ifndef DATA_H_INCLUDED
#define DATA_H_INCLUDED

/数据模块/

//界面数组
int windowShape[25][26] =
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};//边框为1,游戏长度为14
///第一维:七种类型的方块
///第二维:每种方块有四种形态
///第三维,第四维:保存方块数据
int block[7][4][4][4] =
{
{///z
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}
},
{///s
{{0,1,1,0},{1,1,0,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,1,0},{1,1,0,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}}
},
{///L
{{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}},
{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}
},
{///J
{{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},
{{1,0,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}}
},
{///I
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}
},
{///T
{{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}
},
{///田
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}
}
};

#endif // DATA_H_INCLUDED

#include <stdio.h>
#include <stdlib.h>

#include “game.h”
int main()
{
gameInit();

//printf("Hello world!\n");
return 0;

}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
**

撒花! 码字整理不易,感谢各位大佬支持↓↓↓↓↓↓↓↓↓↓↓

、【微信】二维码:如本文对你所帮助,就赏个吧

在这里插入图片描述

**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值