笔者刚接触C++,力图用的知识点简单一点。所以这次基本只运用了二维数组的知识,再去网上搜了输入的函数和Sleep函数就基本实现了相关功能。但我的代码也存在明显漏洞,比如一直按着移动键不放或者是在边缘处狂按会出bug,欢迎大家提出宝贵的改进建议。
最重要的是,如果您是为了交作业,希望我的代码可以给您带来崭新的思路,但是
请勿抄袭!
请勿抄袭!
请勿抄袭!
请勿抄袭!
请勿抄袭!
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
#define SCREEN_WIDTH 16
#define SCREEN_HEIGHT 25
#define BLOCK_SIZE 4
//
// 已发现的bug:在边缘处狂按移动键或按着不发,会出bug。
// 我是在教员给的基础上写的,对部分函数进行了完善。因为我设置的每次输入一个,因此多线程不是很有必要。
//初始每1秒方块下降一个,每删去一行,score加1,时间减0.01秒;
//
//全局变量
int xPos, yPos;
bool t,h;
int f;
int y; //当前方块横、纵坐标
int ground[SCREEN_HEIGHT][SCREEN_WIDTH] = { 0 }; //背景矩阵
// 1代表有方块,0代表无方块
//声明并初始化俄罗斯方块数组,将每种形状的变形列出,通过改变访问的元素改变性状
int blocks[19][4][4] = {
{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}},// l
{{0, 0, 0, 0}, {0, 1, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}},//2
{{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}},//3
{{0, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}},//
{{0, 0, 0, 0}, {0, 0, 1, 1}, {0, 1, 1, 0}, {0, 0, 0, 0}},//5
{{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}},//
{{0, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 1, 1, 0}},//7
{{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, 1, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}},//
{{0, 0, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 1, 0}},//11
{{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}, {1, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},//15
{{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}, {0, 1, 0, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}}
};
//在指定位置画一个方块
void drawBlock(int x, int y, int block[][BLOCK_SIZE]);
//把光标定位到指定坐标
void gotoxy(int x, int y);
//清除指定位置的方块
void clearBlock(int x, int y, int block[][BLOCK_SIZE]);
//向下移动方块
bool moveDown(int x, int y, int block[][BLOCK_SIZE]);
//在窗口顶部创建一个新的方块
int createBlock(); //无法创建时,返回-1,说明已经到顶。
void key(int &x,int &y,int &index,int block[][BLOCK_SIZE]);
void toLeft(int x,int y,int block[][BLOCK_SIZE]);
void toRight(int x, int y, int block[][BLOCK_SIZE]);
int man(int g[SCREEN_HEIGHT][SCREEN_WIDTH]);
void change(int &i);
int main() {
// drawBlock(8, 0, blocks[0]);
cout<<" 俄罗斯方块 "<<endl;
cout<<"< 左移; > 右移; ^ 翻转; \/ 下移; 空格键暂停,再输入任意数字,按下回车键继续游戏" ;
Sleep(6000);
for(int i=0;i<SCREEN_WIDTH+50;i++)
{
gotoxy(i,0);
cout << " " ;
}
for(int i=0;i<SCREEN_WIDTH+50;i++)
{
gotoxy(i,1);
cout << " " ;
}
for(int i=0;i<SCREEN_HEIGHT;i++)
{
gotoxy(0,i);
ground[i][0]=1;
cout << "■";
gotoxy(15,i);
ground[i][15]=1;
cout << "■";
}
for(int i=1;i<SCREEN_WIDTH-1;i++)
{
gotoxy(i,24);
ground[24][i]=1;
cout << "■";
}
//初始化背景,将边缘初始化为1
int xPos = SCREEN_WIDTH / 2 - 2; //初始坐标
int yPos = 0;
bool t=true;
bool k=true;
int index=0;
int s=0;
while(t)
{
index=createBlock();
if(index==-1)
{
break;
}
//到顶就GAME OVER了
k=true;
xPos = SCREEN_WIDTH / 2 - 2;
yPos = 0;
while (k) {
if (moveDown(xPos, yPos, blocks[index])) {
yPos++; //纵坐标加一
}
else {
k=false;
}
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
Sleep(100-s);
key(xPos,yPos,index,blocks[index]);
//挂起一秒
}
h=true;
while(h)
{
y=man(ground);
if(y>0)
s++;
for(int i=y;i>0;i--)
{
for(int d=1;d<SCREEN_WIDTH-1;d++)
{
gotoxy(d,i);
if(ground[i-1][d]==1)
{
ground[i][d]=1;
cout <<"■";
}
else if(ground[i-1][d]==0)
{
ground[i][d]=0;
cout << " " ;
}
}
}
if(f==0)
{
h=false;
}
}
}
cout<<"Game over!!"<<" your score: "<<s;;
return 0;
}
void drawBlock(int x, int y, int block[][BLOCK_SIZE])
{
for (int i = 0; i < BLOCK_SIZE; i++) {
for (int j = 0; j < BLOCK_SIZE; j++) {
if (block[i][j] == 1) {
gotoxy(x + j, y + i); //注意横纵坐标的变换
ground[y+i][x+j]=1;
cout << "■";
}
}
}
}
void gotoxy(int x, int y)
{
COORD point;
point.X = x * 2;
point.Y = y;
SetConsoleCursorPosition(
GetStdHandle(STD_OUTPUT_HANDLE), point);
}
void clearBlock(int x, int y, int block[][BLOCK_SIZE])
{
for (int i = 0; i < BLOCK_SIZE; i++) {
for (int j = 0; j < BLOCK_SIZE; j++) {
if (block[i][j] == 1) {
gotoxy(x + j, y + i);
//注意横纵坐标的变换
ground[y+i][x+j]=0;
cout << " ";
}
}
}
}
bool moveDown(int x, int y, int block[][BLOCK_SIZE])
{
bool canMoveDown = true;
for (int i = 0; i < BLOCK_SIZE; i++) { //先判断能否向下移动
for (int j = 0; j < BLOCK_SIZE; j++) {
if ((block[i][j] > 0 && block[i+1][j] == 0)
&& ((y + i + 1 == 24)
|| (ground[y + i+1][x + j] == 1))){
canMoveDown = false;
break;
}
}
if (!canMoveDown) break;
}
if (canMoveDown) {
clearBlock(x, y, block); //清除原来位置的方块
drawBlock(x, y + 1, block); //在新的位置绘制方块
}
return canMoveDown;
}
int createBlock()
{
int blockIndex = rand() % 19; //随机生成一个新的方块
xPos = SCREEN_WIDTH / 2 - 2;
yPos = 0;
for (int i = 0; i < BLOCK_SIZE; i++) {
for (int j = 0; j < BLOCK_SIZE; j++) {
if ((blocks[blockIndex][i][j] == 1) //判断能否绘制新方块
&& (ground[yPos + i][xPos + j] == 1))
return -1;
}
}
//drawBlock(xPos, yPos, blocks[blockIndex]); //绘制新方块
return blockIndex;
}
void key(int &x,int &y,int &index,int block[][BLOCK_SIZE])
{
if(kbhit( ))
{
int key;
key=_getch();
if(key==75)//输入左键
{
toLeft(x, y, blocks[index]);
x--;
}
if(key==77)//输入右键
{
toRight(x, y, blocks[index]);
x++;
}
if(key==32)//输入空格键
{
cin>>f;//暂停,输入数字继续
}
if(key==72)//输入上键
{
clearBlock(x, y, blocks[index]); //清除原来位置的方块
change(index);
drawBlock(x, y , blocks[index]);
}
if(key==80)//输入下键
{
t=moveDown(x, y, blocks[index]);
y++;
}
}
}
void toLeft(int x,int y,int block[][BLOCK_SIZE])
{
bool toleft=true;
for (int i = 0; i < BLOCK_SIZE;i++)
{
for (int j = 0; j < BLOCK_SIZE; j++)
{
if ((block[i][j] > 0 && block[i][j-1] == 0)&&
//&& ((x + i - 1 == 0)因为已经初始化,此条件可省去
(ground[y + i][x + j-1] == 1))
{
toleft = false;
break;
}
}
if (!toleft) break;
}
if (toleft) {
clearBlock(x, y, block); //清除原来位置的方块
drawBlock(x-1, y , block); //在新的位置绘制方块
}
}
void toRight(int x, int y, int block[][BLOCK_SIZE])
{
bool toright=true;
for (int i = 0; i < BLOCK_SIZE;i++)
{
for (int j = 0; j < BLOCK_SIZE; j++)
{
if ((block[i][j] > 0 && block[i][j+1] == 0)
&& ((x + i + 1 == 16)
|| (ground[y + i][x + j+1] == 1)))
{
toright = false;
break;
}
}
if (!toright) break;
}
if (toright) {
clearBlock(x, y, block); //清除原来位置的方块
drawBlock(x+1, y , block); //在新的位置绘制方块
}
}
int man(int g[SCREEN_HEIGHT][SCREEN_WIDTH])//从下往上遍历返回第一个满行的行数,若为0,说明没有满行的
{
int a= SCREEN_HEIGHT-2;
for(int r= SCREEN_HEIGHT-2;r>0;r--)
{
for(int i=1;i<SCREEN_WIDTH-1;i++)
{
if(g[r][i]!=1)
a=r-1;
}
if(a==r)
{
break;
}
}
return a;
}
void change(int &i)//将每种形状的变形列出,通过改变访问的元素改变性状
{
if(i==0)
i++;
else if(i==1)
i--;
else if(i==3)
i++;
else if(i==4)
i--;
else if (i==5)
i++;
else if (i==6)
i--;
else if (i==7 || i==8 || i==9)
i++;
else if(i==10)
i=7;
else if(i==11 || i==12 || i==13)
i++;
else if (i==14)
i=11;
else if(i==15 || i==16 || i==17)
i++;
else if (i==18)
i=15;
}
程序设计课上,老师布置了俄罗斯方块作为我们的大作业。在自己写完以后,我也分享一下我的心得体会。
首先是审题,老师已经给了一部分代码,应该就是要我继续往后写,所以必须先弄懂老师设置的各个函数的意思。
最后就是不断的尝试啦,失败是成功之母!
最后,感谢其他博主的分享!
相关链接: