基于ucosii+x86pc的俄罗斯方块源码

闲着没事,写的俄罗斯方块。

运行于ucosii+x86pc。显示界面为字符表示

/*
*description: 基于ucosii+x86pc的俄罗斯方块
*create data: 2015.7.12
*author: jalen_king
*/
#include "includes.h"

#ifndef NULL
#define NULL 0
#endif

#ifndef TRUE 
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#define LEFT 1
#define RIGHT 2
#define DOWN 3
#define CHANGE 4

#define DEFAULT_INIT_POSITION_X 5
#define DEFAULT_INIT_POSITION_Y 20
#define BLOCK_COUNT  7   /*block的种类*/

const char block_form[BLOCK_COUNT] = {2, 1, 4, 4, 4, 2, 2}; /*每种block的可变换样式个数*/
/*
**** 竖block的形状坐标
*/
const char block0[2][4][2] = {
				{{-1,0},{0,0},{1,0}, {2,0}},
				{{0,1},{0,0},{0,-1}, {0,-2}}
								};
/*

** 方块
**

*/									
const char block1[1][4][2] = {
				{{-1,0},{0,0},{-1,-1}, {0,-1}}
								};
/*

*
***

*/									
const char block2[4][4][2] = {
				{{1,1},{-1,0},{0,0}, {1,0}},
	
	{{0,1},{1,1},{0,0},{0,-1}},
				{{-1,0},{0,0},{1,0},{-1,-1}},
				{{0,1},{0,0},{-1,-1},{0,-1}}
									};
/*

***
*

*/									
const char block3[4][4][2] = {
				{{-1,0},{0,0},{1,0},{-1,-1}},
				{{-1,1},{0,1},{0,0},{0,-1}},
				{{1,1},{-1,0},{0,0},{1,0}},
				{{0,1},{0,0},{0,-1},{1,-1}}
								};
/*

***
 *

*/									
const char block4[4][4][2] = {
				{{-1,0},{0,0},{1,0}, {0,-1}},
				{{0,1},{-1,0},{0,0},{0,-1}},
				{{0,1},{-1,0},{0,0},{1,0}},
				{{0,1},{0,0},{1,0},{0,-1}}
								};	
/*

**
 **

*/									
const char block5[2][4][2] = {
				{{-1,0},{0,0},{0,-1}, {1,-1}},
				{{0,1},{-1,0},{0,0}, {-1,-1}}
									};	
/*

 **
** 

*/									
const char block6[2][4][2] = {
				{{0,0},{1,0},{-1,-1}, {0,-1}},
				{{-1,1},{-1,0},{0,0}, {0,-1}}
									};	

typedef struct {
	char type;  //block的形状
	char form;  //当前变换形状的状态
	char position_x; //当前所处的x坐标
	char position_y; //当前所处的y坐标
	char (*body_offset)[4][2]; //block自身包含各点的相对坐标
	
}block_t;

#define MAX_SPEED 1000 
#define GAME_MAP_X 10 //游戏宽
#define GAME_MAP_Y 20 //游戏高
char game_map[GAME_MAP_X][GAME_MAP_Y + 4] = {0}; //游戏主界面
//block_t block;
int grade = 0; //成绩
int speed = MAX_SPEED; //速率初始1s
/*获取方块为type型的form状态的偏移*/
void * get_body_offset(char type, char form) 
{
	switch(type) {		
		case 0: return (void *)&block0[form];//break;
		case 1: return (void *)&block1[form];//break;
		case 2: return (void *)&block2[form];//break;
		case 3: return (void *)&block3[form];//break;
		case 4: return (void *)&block4[form];//break;
		case 5: return (void *)&block5[form];//break;
		case 6: return (void *)&block6[form];//break;
		default : return -1;
	}
	//return 0;
}
void display_next(block_t *block)   /*显示方块*/
{

	int i;
	int x,y;
	for(x = 15; x <= 18; x++) {
		for(y = 13; y <= 16; y++) {
			PC_DispChar(x, GAME_MAP_Y - y, ' ', DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
		}
	}
	for(i = 0; i < 4; i++) { 
	
		x = (*block->body_offset)[i][0] + 16;
		y = (*block->body_offset)[i][1]+ 15;

		PC_DispChar(x, GAME_MAP_Y - y, '*', DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);

	}			
}
void display_block(block_t *block, char enable) /*显示方块*/
{
	int i;
	int x,y;
	char (*offset)[4][2];

	for(i = 0; i < 4; i++) { 
	
	x = (*block->body_offset)[i][0] + block->position_x;
	y = (*block->body_offset)[i][1]+ block->position_y;

		if(enable == TRUE) {
			PC_DispChar(x, GAME_MAP_Y - y, '*', DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
		} else {
			PC_DispChar(x, GAME_MAP_Y - y, ' ', DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
		}
	}		
}

int create_new_block(block_t *block)           /*生成新块*/
{
	char buf[64];
	char type,form;
	if(block == NULL) {
		return FALSE;
	}
	type = random(BLOCK_COUNT);
	form = random(block_form[type]);
	block->type = type;
	block->form = form;

	block->position_x = DEFAULT_INIT_POSITION_X;
	block->position_y = DEFAULT_INIT_POSITION_Y;
	block->body_offset = get_body_offset(type, form);
	return TRUE;
}
/*描述:block移动
*返回值:0 可以,-1 不可以
*/
int block_move(block_t *block, char direct)
{
	if(block == NULL) {
		return FALSE;
	}
	display_block(block, FALSE); // 去除旧的显示
	switch(direct) {
		case LEFT: block->position_x--; break;
		case RIGHT: block->position_x++; break;
		case DOWN: block->position_y--; break;
		default : return FALSE;
	}
	display_block(block, TRUE); //显示新的
	return TRUE;
}
/*描述:判断当前block是否可以继续下降
*返回值:0 可以,-1 不可以
*/
int block_move_down(block_t *block)
{
	int i;
	int x = 0,y = 0;

	if(block == NULL) {
		return FALSE;
	}

	for(i = 0; i < 4; i++) {
		x = (*block->body_offset)[i][0] + block->position_x;
		y = (*block->body_offset)[i][1] + block->position_y;
	
		y--; //(x,y-1)
		if(y >= GAME_MAP_Y) {
			//continue;
		}

		if(y < 0 || game_map[x][y] != NULL) { //判断(x,y-1)的位置有没有方块
			return FALSE;			//如果有方块,则不能下移
		}
	}

	return block_move(block, DOWN);
}
/*描述:判断当前block是否可以继续下降
*返回值:0 可以,-1 不可以
*/
int block_move_left(block_t *block)
{
	int i;
	int x,y;
	if(block == NULL) {
		return FALSE;
	}
	for(i = 0; i < 4; i++) {
		x = (*block->body_offset)[i][0] + block->position_x;
		y = (*block->body_offset)[i][1] + block->position_y;
	
		x--; //(x-1,y)
		if(y >= GAME_MAP_Y) {
			continue;
		}
		if(x < 0 || game_map[x][y] != NULL) { //判断(x-1,y)的位置有没有方块
			return FALSE;			//如果有方块,则不能移
		}
	}
	return block_move(block, LEFT);
}
/*描述:判断当前block是否可以继续下降
*返回值:0 可以,-1 不可以
*/
int block_move_right(block_t *block)
{

	int i;
	int x,y;
	if(block == NULL) {
		return FALSE;
	}
	for(i = 0; i < 4; i++) {
		x = (*block->body_offset)[i][0] + block->position_x;
		y = (*block->body_offset)[i][1] + block->position_y;
		
		x++; //(x+1,y)
		if(x >= GAME_MAP_X || game_map[x][y] != NULL) { //判断(x+1,y)的位置有没有方块
			return FALSE;			//如果有方块,则不能移
		}
	}
	return block_move(block, RIGHT);
}

/*描述:判断当前block是否可以旋转
*返回值:0 可以,-1 不可以
*/
int block_spin(block_t *block)
{
	char buf[24];
	int i;
	int x,y;
	int tmp_x, tmp_y;
	int form;
	char (*body_offset)[4][2];	
	if(block == NULL) {
		return FALSE;
	}	

	form = (block->form + 1) % block_form[block->type];

	if(form == block->form) { //如果变换后还是它自身则直接返回。
		return TRUE;
	}
	
	tmp_x = block->position_x;
	tmp_y = block->position_y;
	body_offset = get_body_offset(block->type, form); //取得变换后的坐标偏移
	for(i = 0; i < 4; i++) {
		x = (*body_offset)[i][0] + tmp_x;
		y = (*body_offset)[i][1] + tmp_y;

		if(x < 0) {
			tmp_x = tmp_x - x;
		}
		if(x >= GAME_MAP_X) {
			tmp_x = tmp_x - (x - GAME_MAP_X + 1);
		}
		if(y < 0) {
			tmp_y = tmp_y - y;
		}
	}
	for(i = 0; i < 4; i++) {
		x = (*body_offset)[i][0] + tmp_x;
		y = (*body_offset)[i][1] + tmp_y;

		if(game_map[x][y] != NULL) { //判断(x,y)的位置有没有方块
			return FALSE;			//如果有方块,则不能变
		}
	}
	display_block(block, FALSE);
	block->position_x = tmp_x;
	block->position_y = tmp_y;
	block->form = form;
	block->body_offset = body_offset;//get_body_offset(block->type, form);
	display_block(block, TRUE);
	return TRUE;
}
/*描述:获取用户按键
*返回值:a==change, s== left,d==down, f==right,esc==quit, -1
*/
char get_ch()
{	
	INT16S key = 0;

	if (kbhit()) {										   /* See if a key has been pressed 		   */
		key = (INT16S)getch();							   /* Get key pressed						   */
		switch(key) {
			case 97: return CHANGE;//break;		\\space
			case 115: return LEFT;//break;
			case 102: return RIGHT;//break;
			case 100: return DOWN;//break;
			case 27: PC_DOSReturn();//break;
			default: return -1;//break;
		} 
	}
	return -1;
}
/*描述:sleep,s为毫秒
*返回值:
*/
void my_sleep(int s)
{
	if(s >= 1000) {
		OSTimeDlyHMSM(0, 0, s/1000, 0);
	} else {
		OSTimeDlyHMSM(0, 0, 0, s);
	}
}
/*描述:显示(刷新)游戏界面
*返回值:
*/
void display_game_map()
{
	int x,y;
	for(x = 0; x < GAME_MAP_X; x++) {
		for(y = 0; y < GAME_MAP_Y; y++) {
			if(game_map[x][y] == 1) {
				PC_DispChar(x, GAME_MAP_Y - y, '*', DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
			} else {
				PC_DispChar(x, GAME_MAP_Y - y, ' ', DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
			}
		}
	}
}
/*描述:显示(刷新)成绩
*返回值:
*/
void display_grade()
{
	char buf[24];
	sprintf(buf, "grade: %-3d",grade);
	PC_DispStr( 15, 16, buf, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}
/*描述:消除行
*返回值:
*/
void clear_line(int line)
{
	int x,y;

	for(y = line; y < GAME_MAP_Y; y++) {
		for(x = 0; x < GAME_MAP_X; x++) {
			game_map[x][y] = game_map[x][y+1];
		}
	}
}
/*描述:刷新游戏下降速率
*返回值:
*/
void change_speed()
{	
	int level = 0;
	level = grade / 200;
	speed = MAX_SPEED - 100 * level;
}
/*描述:处理游戏结果
*返回值:
*/
int process_result(block_t *block)
{
	int i;
	int x,y;
	char buf[64];

	for(i = 0; i < 4; i++) {
		x = (*block->body_offset)[i][0] + block->position_x;
		y = (*block->body_offset)[i][1] + block->position_y;
		
		if(y >= GAME_MAP_Y) {
			goto OVER;
		}
		game_map[x][y] = 1;
	}
	
	for(y = 0; y < GAME_MAP_Y; ) {
		for(x = 0; x < GAME_MAP_X; x++) {
			if(game_map[x][y] != 1) {
				y++;
				break;
			}
		}
		if(x == GAME_MAP_X) {
			clear_line(y);		//消除行
			grade += GAME_MAP_X; //计算得分
		}
	}
	change_speed();
	display_game_map();
	display_grade();
	return 0;
OVER: //游戏结束
	sprintf(buf, "GAME OVER");
	PC_DispStr( 15, 15, buf, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
	sprintf(buf, "grade :%-3d", grade);
	PC_DispStr( 15, 16, buf, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
	while(1) {
		get_ch();
	}
}
/*描述:主任务进程
*返回值:
*/
void block_task(void *pdata)
{
	int ret = 0;
	char ch = 0;
	block_t block, block_next;
	int game_start = 0;
	
	pdata = pdata;

	memset(game_map, 0, GAME_MAP_X * (GAME_MAP_Y + 4));
	display_game_map();
	display_grade();
	for(;;) {
		if(game_start == 0) {
			create_new_block(&block);
			create_new_block(&block_next);
			game_start = 1;
		} else {
			memcpy(&block, &block_next, sizeof(block_t));
			create_new_block(&block_next);
		}
		display_next(&block_next);
		for(;;) {
			ch = get_ch();
			switch(ch) {
				case LEFT: block_move_left(&block); break;
				case RIGHT: block_move_right(&block);break;
				case DOWN: 
					ret = block_move_down(&block);
					if(ret != TRUE) {
						goto OVER;
					}
					break;
				case CHANGE: block_spin(&block); break;
				default:
					ret = block_move_down(&block);
					if(ret != TRUE) {
						goto OVER;
					}
					my_sleep(speed);
					break;
				
			}
		}
OVER:
		process_result(&block);
	}

}

/***=======================以下为ucosii的系统初始化代码============================**/
#define TASK_STK_SIZE 1024*10
OS_STK        TaskStk[TASK_STK_SIZE];        /* Tasks stacks                                  */
OS_STK        TaskStartStk[TASK_STK_SIZE];

static  void  TaskStartDispInit (void)
{

    PC_DispStr( 0, 22, "#Tasks          :        CPU Usage:     %                                       ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
    PC_DispStr( 0, 23, "#Task switch/sec:                                                               ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
    PC_DispStr( 0, 24, "                            <-PRESS 'ESC' TO QUIT->                             ", DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY + DISP_BLINK);
/*                                1111111111222222222233333333334444444444555555555566666666667777777777 */
/*                      01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
}
static  void  TaskStartDisp (void)
{
    char   s[80];


    sprintf(s, "%5d", OSTaskCtr);                                  /* Display #tasks running               */
    PC_DispStr(18, 22, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);

#if OS_TASK_STAT_EN > 0
    sprintf(s, "%3d", OSCPUUsage);                                 /* Display CPU usage in %               */
    PC_DispStr(36, 22, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);
#endif

    sprintf(s, "%5d", OSCtxSwCtr);                                 /* Display #context switches per second */
    PC_DispStr(18, 23, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);

    sprintf(s, "V%1d.%02d", OSVersion() / 100, OSVersion() % 100); /* Display uC/OS-II's version number    */
    PC_DispStr(75, 24, s, DISP_FGND_YELLOW + DISP_BGND_BLUE);

    switch (_8087) {                                               /* Display whether FPU present          */
        case 0:
             PC_DispStr(71, 22, " NO  FPU ", DISP_FGND_YELLOW + DISP_BGND_BLUE);
             break;

        case 1:
             PC_DispStr(71, 22, " 8087 FPU", DISP_FGND_YELLOW + DISP_BGND_BLUE);
             break;

        case 2:
             PC_DispStr(71, 22, "80287 FPU", DISP_FGND_YELLOW + DISP_BGND_BLUE);
             break;

        case 3:
             PC_DispStr(71, 22, "80387 FPU", DISP_FGND_YELLOW + DISP_BGND_BLUE);
             break;
    }
}

static  void  TaskStartCreateTasks (void)
{
	OSTaskCreate(block_task, 0, &TaskStk[TASK_STK_SIZE - 1], 1);   
}

void  TaskStart (void *pdata)
{
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif
    char       s[100];
    INT16S     key;


    pdata = pdata;                                         /* Prevent compiler warning                 */

    TaskStartDispInit();                                   /* Initialize the display                   */

    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);                           /* Install uC/OS-II's clock tick ISR        */
    PC_SetTickRate(OS_TICKS_PER_SEC);                      /* Reprogram tick rate                      */
    OS_EXIT_CRITICAL();

    OSStatInit();                                          /* Initialize uC/OS-II's statistics         */

    TaskStartCreateTasks();                                /* Create all the application tasks         */

    for (;;) {
        TaskStartDisp();                                  /* Update the display                       */


       // if (PC_GetKey(&key) == TRUE) {                     /* See if key has been pressed              */
            if (key == 0x1B) {                             /* Yes, see if it's the ESCAPE key          */
                PC_DOSReturn();                            /* Return to DOS                            */
            }
        //}

        OSCtxSwCtr = 0;                                    /* Clear context switch counter             */
        OSTimeDlyHMSM(0, 0, 1, 0);                         /* Wait one second                          */
    }
}
void  main (void)
{
    PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);      /* Clear the screen                         */

    OSInit();                                              /* Initialize uC/OS-II                      */

    PC_DOSSaveReturn();                                    /* Save environment to return to DOS        */
    PC_VectSet(uCOS, OSCtxSw);                             /* Install uC/OS-II's context switch vector */

    OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
    OSStart();                                             /* Start multitasking                       */
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值