欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

俄罗斯方块

程序员文章站 2023-12-23 19:13:45
...

俄罗斯方块(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;

}
俄罗斯方块
俄罗斯方块
俄罗斯方块

上一篇:

下一篇: