c语言俄罗斯方块随机,C语言实现俄罗斯方块

#include

#include

#include

//time()

//#include

//#include

#include

//kbhit()

//Author:  赖依 QQ:54142961

#define  KEY_LEFT  75

#define  KEY_RIGHT  77

#define  KEY_UP  72

#define  KEY_DOWN  80

#define false 0

#define true 1

#define LINENUM  20  //游戏界面高度,20行

typedef struct CPoint

{

int x;

int y;

}CPoint;

//方块信息

typedef struct

{

CPoint point; //一个方块的中心点位置

unsigned char  flags;

//其周围8个位的方块有无标志

}BlockInfo;

void GameOver();

void isFull();

void ShowInfo();

void CreateBlock();

void ClearBlock(unsigned short Panel[], BlockInfo

*block);

int BlockCat(unsigned short int Panel[],BlockInfo*);

void MoveBlock(int direction);

void ChangeType();

void BlockDrop();

//现有的26种方块类型

// * * *  1 2 3 0 1

0

// * + *  ==>8 + 4 1 + 1

←←←←←←←←←

// * * *  7 6 5 0 0 0

//一个方块,中间的+是中心点,必然有方块 ↑

//上图是周围8个位的位置 ↑

//比如第一个方块类型0x51=(0101 0001)b那么这个方块就是↑

unsigned char AllBlocks[26]={

0x51,0x54,0x15,0x45

,0x58,0x16,0x85,0x61

,0x43,0xd0,0x34,0x0d

,0x1c,0x07,0xc1,0x70

,0x4c,0x13,0xc4,0x31

,0x19,0x46,0x91,0x64

,0x44,0x11};

BlockInfo oldblock,currblock;

int score;

int speed;

int gameover;

unsigned short Panel[LINENUM];

int main()

{

int i;

char direction;

currblock.point.x=5;

currblock.point.y=5;

currblock.flags=0x15;

Panel[0]=0xffff;

Panel[LINENUM-1]=0xffff;

//界面和左右边界

for(i=1;i

speed=1;

//直到获取一个非0速度

do

{

printf("Please input the

value of speed:\n");

scanf("%d",&speed);

}while(speed == 0);

score=0;

gameover=0;

srand(time(0));

CreateBlock();

while(direction!='q' &&

gameover==0) //没有按下q键,且游戏者未挂掉

{

if(direction == KEY_DOWN)

{

_sleep(1000);

BlockDrop();

}

//游戏者未挂,且没有按键则自动下落

while(gameover==0 &&

!kbhit())

{

_sleep(600/speed);

//delay(60000/speed);

BlockDrop();

}

direction=getch(); //获取移动方向

if(direction == KEY_UP)ChangeType();//如果是上键,则变换方块类型

else if(direction != KEY_DOWN)

MoveBlock(direction);//如果不是上,不是下,则按方向移动方块

}

return 0;

}

void BlockDrop()

{

//原先方块的信息保存到oldblock中,后边相同的我就不注释了

oldblock.flags=currblock.flags;

oldblock.point.x=currblock.point.x;

oldblock.point.y=currblock.point.y;

//当前方块下落一格

currblock.point.y+=1;

//清除原先方块

ClearBlock(Panel,&oldblock);

if(!BlockCat(Panel,&currblock))//如果currblock是非法的,则

{

BlockCat(Panel,&oldblock);//把原先的方块放回界面上去

//不能下落了,则说明一个非常严重的问题--这个方块到底儿了

//1、判断是否有满行,并且进行处理

isFull();

//2、创建一个新的方块

CreateBlock();

}

//方块的现状显示出来

ShowInfo();

}

void ChangeType()

{

unsigned char now;

oldblock.flags=currblock.flags;

oldblock.point.x=currblock.point.x;

oldblock.point.y=currblock.point.y;

//now是原先的类型

now=currblock.flags;

now >>= 6;

//右移6位,now中剩下的是最左边2位

currblock.flags<<=2;//左移2位剩下的是右边的6位

currblock.flags|=now;//两者逻辑或,这样实现的操作如下图所示

// 1 2 3  7 8 1

// 8 + 4  ==>6 + 2

// 7 6 5  5 4 3

//也就是从12345678 变成了34567812,即方块向右旋转一次

ClearBlock(Panel,&oldblock);//清除原先方块

if(!BlockCat(Panel,&currblock))//如果可以currblock不合法,则

{

//将原先方块放回去

BlockCat(Panel,&oldblock);

//currblock永远保存的是当前方块

currblock.flags=oldblock.flags;

currblock.point.x=oldblock.point.x;

currblock.point.y=oldblock.point.y;

return; //没有变化,不用再次显示

}

ShowInfo();

}

void MoveBlock(int direction)

{

if(direction==KEY_LEFT)

{

oldblock.flags=currblock.flags;

oldblock.point.x=currblock.point.x;

oldblock.point.y=currblock.point.y;

currblock.point.x-=1; //向左移动一步

ClearBlock(Panel,&oldblock);

if(!BlockCat(Panel,&currblock))

{

BlockCat(Panel,&oldblock);

currblock.point.x++;

}

ShowInfo();

}

else if(direction==KEY_RIGHT)

{

oldblock.flags=currblock.flags;

oldblock.point.x=currblock.point.x;

oldblock.point.y=currblock.point.y;

currblock.point.x+=1;

ClearBlock(Panel,&oldblock);

if(!BlockCat(Panel,&currblock))

{

BlockCat(Panel,&oldblock);

currblock.point.x--;

}

ShowInfo();

}

}

int BlockCat(unsigned short Panel[], BlockInfo

*currblock)

{

int row=currblock->point.y;

int col=currblock->point.x;

if((currblock->flags & 1)

&& (Panel[row-1]

& 1<<15-col))

return false;

if((currblock->flags &

1<<1)

&& (Panel[row-1]

& 1<<15-col-1))

return false;

if((currblock->flags &

1<<2)

&& (Panel[row]

& 1<<15-col-1))

return false;

if((currblock->flags &

1<<3)

&& (Panel[row+1]

& 1<<15-col-1))

return false;

if((currblock->flags &

1<<4)

&& (Panel[row+1]

& 1<<15-col))

return false;

if((currblock->flags &

1<<5)

&& (Panel[row+1]

& 1<<15-col+1))

return false;

if((currblock->flags &

1<<6)

&& (Panel[row]

& 1<<15-col+1))

return false;

if((currblock->flags &

1<<7)

&& (Panel[row-1]

& 1<<15-col+1))

return false;

if(Panel[row] &

1<<15-col)return false;

if(currblock->flags & (1)

) Panel[row-1] |=

(1<<15-col)  ;

if(currblock->flags &

(1<<1) ) Panel[row-1] |=

(1<<15-col-1) ;

if(currblock->flags &

(1<<2) ) Panel[row]

|= (1<<15-col-1)

;

if(currblock->flags &

(1<<3) ) Panel[row+1] |=

(1<<15-col-1) ;

if(currblock->flags &

(1<<4) ) Panel[row+1] |=

(1<<15-col)  ;

if(currblock->flags &

(1<<5) ) Panel[row+1] |=

(1<<15-col+1) ;

if(currblock->flags &

(1<<6) ) Panel[row]

|= (1<<15-col+1)

;

if(currblock->flags &

(1<<7) ) Panel[row-1] |=

(1<<15-col+1) ;

Panel[row] |=(1<<15-col);

return true;

}

void ClearBlock(unsigned short Panel[], BlockInfo

*block)

{

int row=block->point.y;

int col=block->point.x;

Panel[row]  &=

~(1<<15-col);

if(block->flags & (1)

){Panel[row-1]

&= ~(1<<15-col)

;}

if(block->flags &

(1<<1) ){Panel[row-1]

&= ~(1<<15-col-1)

;}

if(block->flags &

(1<<2) ){Panel[row]

&=

~(1<<15-col-1) ;}

if(block->flags &

(1<<3) ){Panel[row+1]

&= ~(1<<15-col-1)

;}

if(block->flags &

(1<<4) ){Panel[row+1]

&= ~(1<<15-col)

;}

if(block->flags &

(1<<5) ){Panel[row+1]

&= ~(1<<15-col+1)

;}

if(block->flags &

(1<<6) ){Panel[row]

&=

~(1<<15-col+1) ;}

if(block->flags &

(1<<7) ){Panel[row-1]

&= ~(1<<15-col+1)

;}

}

void CreateBlock()

{

int i,j;

//方块初始位置固定为5,2,也就是第6行,第3列

currblock.point.x=5;

currblock.point.y=2;

//currblock.flags=0;

//随机产生一个类型的方块

currblock.flags=AllBlocks[rand()&];

//如果放不下这个方块,则说明游戏结束了

if(!BlockCat(Panel,&currblock))

{

gameover=1;

GameOver();

}

}

void ShowInfo()

{

char *panel;

int i,j;

char str[32];

unsigned int temp;

// gotoxy(1,1);

// clrscr();

system("cls");//清屏

//显示得分

printf("\n");

printf("SCORE: [  %d

]\n",score);

//循环输出每一行

for(i=0;i

{

j=30;//共有16个位和15个空格,所以是0~30,第31个字符是'\0'

temp=Panel[i];

while(temp)

{

if(temp%2==0)str[j--]=' '; //这个位是0则输出空格

else str[j--]='1'; //是1则输出1

str[j--] = ' '; //前边都加个空格是为了界面好看

temp/=2;

}

str[31]='\0';

printf(str); //输出本行

printf("\n");

}

}

void isFull()

{

int i,j;

for(i=LINENUM-2;i>0;i--)

{

if((unsigned short)~Panel[i]==3)//满了的行会是这样的(1 111111111111 1

00),非运算后是3

{ // ↑  ↑

Panel[i]=0x8004; //  左边界  方块 右边界

score+=10;

for(j=i;j>1;j--)Panel[j]=Panel[j-1];//满的行消除,其余行依次下落

Panel[1]=0x8004;

}

}

}

void GameOver()

{

printf("Game Over");

}

* *俄罗斯方块源程序 */ #include #include #include #include /*图形函数库*/ /*定义按键码*/ #define VK_LEFT 0x4b00 #define VK_RIGHT 0x4d00 #define VK_DOWN 0x5000 #define VK_UP 0x4800 #define VK_ESC 0x011b #define TIMER 0x1c /*设置中断号*/ /*定义常量*/ #define MAX_BOX 19 /*总共有19种各形态的方块*/ #define BSIZE 20 /*方块的边长是20个象素*/ #define Sys_x 160 /*显示方块界面的左上角x座标*/ #define Sys_y 25 /*显示方块界面的左上角y座标*/ #define Horizontal_boxs 10 /*水平的方向以方块为单位的长度*/ #define Vertical_boxs 15 /*垂直的方向以方块为单位的长度,也就说长是15个方块*/ #define Begin_boxs_x Horizontal_boxs/2 /*产生第一个方块时出现的起始位置*/ #define FgColor 3 /*前景颜色,如文字.2-green*/ #define BgColor 0 /*背景颜色.0-blac*/ #define LeftWin_x Sys_x+Horizontal_boxs*BSIZE+46 /*右边状态栏的x座标*/ #define false 0 #define true 1 /*移动的方向*/ #define MoveLeft 1 #define MoveRight 2 #define MoveDown 3 #define MoveRoll 4 /*以后坐标的每个方块可以看作是像素点是BSIZE*BSIZE的正方形*/ /*定义全局变量*/ int current_box_numb; /*保存当前方块编号*/ int Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*x,y是保存方块的当前坐标的*/ int flag_newbox=false; /*是否要产生新方块的标记0*/ int speed=0; /*下落速度*/ int score=0; /*总分*/ int speed_step=30; /*每等级所需要分数*/ void interrupt (*oldtimer)(void);/* 指向原来时钟中断处理过程入口的中断处理函数指针 */ struct BOARD /*游戏底板结构,表示每个点所具有的属性*/ { int var; /*当前状态 只有0和1,1表示此点已被占用*/ int color; /*颜色,游戏底板的每个点可以拥有不同的颜色.增强美观*/ }Table_board[Vertical_boxs][Horizontal_boxs]; /*方块结构*/ struct SHAPE { char box[2]; /*一个字节等于8位,每4位来表示一个方块的一行 如:box[0]="0x88",box[1]="0xc0"表示的是: 1000 1000 1100 0000*/ int color; /*每个方块的颜色*/ int next; /*下个方块的编号*/ };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值