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

C语言游戏:俄罗斯方块

2016-05-05 13:52 507 查看
最近比较无聊,用C语言写了个俄罗斯方块,游戏效果如下:



代码如下,后续有时间再进行改进。。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string.h>
#include <termios.h>
#include <pthread.h>

#define MAP_H 21
#define MAP_L 10

#define FALL_SPEED 420000  //MICROSECOND
#define FASTER_SPEED 5000  //MICROSECOND
#define FLASH_TIME 130000

const char no_block = '.';
const char block_body = '#';
const char block_flash = '*';

int key;
int speed;
int block_type_count;
int over=0;
int next_block=0;
int point=0;
int has_bomb=0;
int block_attr_changing_flag=0;
char GameField[MAP_H][MAP_L];
static struct termios stored_settings;
pthread_t id;

typedef struct Block
{
char block_form[4][4];
int type;
int x,y;
} s_Block;
s_Block Block;
s_Block Block_Next;

enum block_type
{
Square=0,
Strip=1,
JShape,
LShape,
TShape,
ZShape,
SShape,
Bomb,
};

void Initial();
void CreateBlock();
void ShowGame();
void PrintMap();
void CheckPoints();
void KeyDetectThread(void);
void GetButton();

void move_down();
void move_left();
void move_right();
void move_up();
void move_down_faster();

void FillBlockIntoMap();
void RmBlockFromMap();
int BlockCollide(s_Block *block);
void BlockRotate(s_Block *block);
void BlockExplode(int x,int y);

void set_keypress(void);
void reset_keypress(void);

int main(int argc, char *argv[])
{
Initial();
ShowGame();
return 0;
}

void Initial()
{
int ret;
int key;

memset(GameField, no_block, sizeof(GameField));
set_keypress();
speed = FALL_SPEED;
point = 0;
over = 0;
has_bomb = 0;
system("clear");
printf("\nYou wanna get bomb block randomly? (y/n)\n ");
key=getchar();
if(key=='y')
{
block_type_count=8;
}else
block_type_count=7;
system("clear");
CreateBlock();
Block = Block_Next;
CreateBlock();
PrintMap();
getchar();
GetButton();

ret=pthread_create(&id,NULL,(void *)KeyDetectThread,NULL);
if(ret)
{
printf("Create thread error!\n");
sleep(2);
exit(0);
}
}

void CreateBlock()
{
int b_type;

memset(Block_Next.block_form,no_block,sizeof(Block_Next.block_form));
srand(time(0));
b_type=rand()%block_type_count;
Block_Next.x = 0;
Block_Next.y = 3;

switch(b_type)
{
case Square:
Block_Next.block_form[1][1]=block_body;
Block_Next.block_form[1][2]=block_body;
Block_Next.block_form[2][1]=block_body;
Block_Next.block_form[2][2]=block_body;
Block_Next.type=Square;
break;
case Strip:
Block_Next.block_form[0][1] = block_body;
Block_Next.block_form[1][1] = block_body;
Block_Next.block_form[2][1] = block_body;
Block_Next.block_form[3][1] = block_body;
Block_Next.type = Strip;
break;
case JShape:
Block_Next.block_form[0][2] = block_body;
Block_Next.block_form[1][2] = block_body;
Block_Next.block_form[2][2] = block_body;
Block_Next.block_form[2][1] = block_body;
Block_Next.type = JShape;
break;
case LShape:

4000
Block_Next.block_form[0][1] = block_body;
Block_Next.block_form[1][1] = block_body;
Block_Next.block_form[2][1] = block_body;
Block_Next.block_form[2][2] = block_body;
Block_Next.type = JShape;
break;
case TShape:
Block_Next.block_form[0][1] = block_body;
Block_Next.block_form[1][1] = block_body;
Block_Next.block_form[2][1] = block_body;
Block_Next.block_form[1][2] = block_body;
Block_Next.type = TShape;
break;
case ZShape:
Block_Next.block_form[0][2] = block_body;
Block_Next.block_form[1][2] = block_body;
Block_Next.block_form[1][1] = block_body;
Block_Next.block_form[2][1] = block_body;
Block_Next.type = ZShape;
break;
case SShape:
Block_Next.block_form[0][1] = block_body;
Block_Next.block_form[1][1] = block_body;
Block_Next.block_form[1][2] = block_body;
Block_Next.block_form[2][2] = block_body;
Block_Next.type = SShape;
break;
case Bomb:
Block_Next.block_form[0][2] = block_body;
Block_Next.block_form[1][1] = block_body;
Block_Next.block_form[1][3] = block_body;
Block_Next.block_form[2][2] = block_body;
Block_Next.type = Bomb;
break;
default:
break;
}
}

void BlockExplode(int x,int y)
{
int i,j;

RmBlockFromMap();
for (i = x - 1; i <= x + 1; i++)
for (j = y - 1; j <= y + 1; j++)
{
if (i > 3 && i < MAP_H && j >= 0 && j < MAP_L)
if (GameField[i][j] == block_body)
GameField[i][j] = block_flash;
}
PrintMap();
usleep(FLASH_TIME);
for (i = x - 1; i <= x + 1; i++)
for (j = y - 1; j <= y + 1; j++)
{
if (i > 3 && i < MAP_H && j >= 0 && j < MAP_L)
if (GameField[i][j] == block_flash)
GameField[i][j] = no_block;
}
Block=Block_Next;
CreateBlock();
speed=FALL_SPEED;
}

void BlockRotate(s_Block *block)
{
int i,j;
char bf[4][4];
for(i=3;i>=0;i--)
for(j=0;j<=3;j++)
{
bf[j][3-i]=block->block_form[i][j];
}
memcpy(block->block_form,bf,sizeof(bf));
}

void move_left()
{
s_Block t_block;

t_block=Block;
t_block.y=t_block.y-1;
if(BlockCollide(&t_block))
{
return;
}else
{
RmBlockFromMap();
Block=t_block;
FillBlockIntoMap();
PrintMap();
}
}

void move_right()
{
s_Block t_block;

t_block = Block;
t_block.y = t_block.y + 1;
if (BlockCollide(&t_block))
{
return;
} else
{
RmBlockFromMap();
Block = t_block;
FillBlockIntoMap();
PrintMap();
}
}

void move_down()
{
s_Block t_block;

t_block=Block;
t_block.x=t_block.x+1;
if(BlockCollide(&t_block))
{
if(t_block.x<5)
{
over = 1;
return;
}else
{
next_block = 1;
speed = FALL_SPEED;
return;
}
}else
{
RmBlockFromMap();
Block=t_block;
FillBlockIntoMap();
}
}

void move_down_faster()
{
speed=FASTER_SPEED;
}

void move_up()  // shift the block
{
s_Block t_block;

t_block = Block;
BlockRotate(&t_block);
if (BlockCollide(&t_block))
{
return;
} else
{
block_attr_changing_flag = 1;
RmBlockFromMap();
Block = t_block;
FillBlockIntoMap();
PrintMap();
block_attr_changing_flag = 0;
}
}

void RmBlockFromMap()
{
int i, j;

for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
if (Block.block_form[i][j] == block_body)
GameField[Block.x + i][Block.y + j] = no_block;
}
}

int BlockCollide(s_Block *block)
{
int i,j;
int xx,yy;

for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if (block->block_form[i][j] == block_body)
{
if (block->x + i >= MAP_H)
{
if (block->type == Bomb)
BlockExplode(block->x + i, block->y + j);
return 1;
}

if (block->y + j < 0 || block->y + j >= MAP_L)
{
if(block->type==Bomb)
BlockExplode(block->x+i,block->y+j);
return 1;
}

if (GameField[block->x + i][block->y + j] == block_body)
{
xx = block->x + i - Block.x;
yy = block->y + j - Block.y;

if (0 <= xx && xx < 4 && 0 <= yy && yy < 4)
{
if (Block.block_form[xx][yy] == no_block)
{
if(block->type==Bomb)
BlockExplode(block->x+i,block->y+j);
return 1;
}
}else
{
if (block->type == Bomb)
BlockExplode(block->x+i,block->y+j);
return 1;
}
}
}
}
return 0;
}

void ShowGame()
{
int key;

while(1)
{
usleep(speed);
if(block_attr_changing_flag)
continue;
block_attr_changing_flag=1;
move_down();
block_attr_changing_flag=0;
if(over)
{
PrintMap();
printf("\nGame Over!!!\n");
printf("Continue? (y/n)\n");
pthread_cancel(id);
key=getchar();
if(key=='y')
{
Initial();
continue;
}else if(key=='n')
{
printf("Exit Game SlidingBlocks...\n");
reset_keypress();
exit(0);
}
}else if(next_block)
{
CheckPoints();
Block=Block_Next;
CreateBlock();
next_block=0;
}
PrintMap();
}
}

void CheckPoints()
{
int i,j,k;
int sum=0;      // sum of block body in each line
int point_ascend = 50;
int flash_flag=0;
char t_game_field[MAP_H][MAP_L];

for (i = MAP_H - 1; i > 3; i--)
{
for (j = 0; j < MAP_L; j++)
{
if(GameField[i][j]!= block_body) break;
sum++;
}
if(sum==MAP_L)
{
for (k = 0; k < MAP_L; k++)
{
GameField[i][k] = block_flash;
}
flash_flag=1;
point=point+point_ascend;
point_ascend=point_ascend+50;
}
sum=0;
}

if(flash_flag)
{
PrintMap();
usleep(FLASH_TIME);
memset(t_game_field,no_block,sizeof(GameField));

k = MAP_H - 1;
for (i = MAP_H - 1; i > 3; i--)
{
if (GameField[i][0] != block_flash)
{
for (j = 0; j < MAP_L; j++)
{
t_game_field[k][j] = GameField[i][j];
}
k--;
}else
continue;
}
memcpy(GameField,t_game_field,sizeof(GameField));
}
}

void FillBlockIntoMap()
{
int i,j;

for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
if (Block.block_form[i][j] == block_body)
GameField[Block.x + i][Block.y + j] = Block.block_form[i][j];
}
}

void PrintMap()
{
int i,j,k;

system("clear");
printf("----<SLIDING  BLOCKS>----\n\n");
for (i = 4; i < MAP_H; i++)
//for (i = 0; i < MAP_H; i++)
{
9f64
for (j = 0; j < MAP_L; j++)
{
printf("%c ", GameField[i][j]);
}
if(i==4)
{
printf("\tPOINT : %d",point);
}

if (i == 6)
{
printf("\tNext Block");
}

if(i>=8&&i<=11)
{
printf("\t ");
for(k=0;k<4;k++)
{
if(Block_Next.block_form[i-8][k]==no_block)
{
printf("  ");
}else
printf("%c ",Block_Next.block_form[i-8][k]);
}
}
printf("\n");
}

printf("\nA small Game: Sliding Blocks\n");
printf("Press any key to start...\n");
}

void KeyDetectThread(void)
{
while(1)
{
GetButton();
}
}

void GetButton()
{
if (block_attr_changing_flag)
return;
key = getchar();
if (key != 91)
return;
key = getchar();
block_attr_changing_flag = 1;
switch (key)
{
case 68:
move_left();    //left
break;
case 67:
move_right();   //right
break;
case 65:
move_up();      //up
break;
case 66:
move_down_faster();  //down
break;
default:
break;
}
block_attr_changing_flag = 0;
}

void set_keypress(void)       //设置终端为RAW模式,并关闭回显
{
struct termios new_settings;
tcgetattr(0,&stored_settings);
new_settings = stored_settings;

new_settings.c_lflag &= (~ICANON);
new_settings.c_lflag &= (~ECHO);
new_settings.c_cc[VTIME] = 0;
new_settings.c_cc[VMIN] = 1;
tcsetattr(0,TCSANOW,&new_settings);
return;
}

void reset_keypress(void)      //恢复终端属性
{
tcsetattr(0,TCSANOW,&stored_settings);
return;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息