本來是一天上傳一點的,結果一次性上傳了( ̄▽ ̄)",尷尬。
HANDLE Output;
void printPrompting(); //顯示提示信息
void gotoxyWithFullwidth(short x,short y); //進行全角定位
void printScore(const Manager *manager); //顯示分數
void printPoolBorder(); //顯示遊戲池邊界
void initGame(Manager *manager,Control *control); //初始化遊戲
void startGame(Manager *manager,Control *control); //開始遊戲
void printNextTetris(const Manager *manager); //顯示下一個和下下一個方塊
void printTetrisPool(const Manager *manager,const Control *control); //顯示遊戲池
void initTetris(Manager *manager); //方塊初始化,構造當前方塊
void insertTetris(Manager *manager); //把當前方塊插入遊戲池中
void setPoolColor(const Manager *manager,Control *control); //設置顏色
void printCurrentTetris(const Manager *manager,const Control *control); //顯示當前方塊
bool checkCollision(const Manager *manager); //碰撞檢測
void runGame(Manager *manager,Control *control); //運行遊戲
void moveDownTetris(Manager *manager,Control *control); //向下移動方塊
void removeTetris(Manager *manager); //移去方塊
bool checkErasing(Manager *manager,Control *control); //檢測消行
void horzMoveTetris(Manager *manager,Control *control); //左右移動
void rotateTetris(Manager *manager,Control *control); //旋轉方塊
void keydownControl(Manager *manager,Control *control,int key); //鍵入指令
void dropDownTetris(Manager *manager,Control *control); //消行
bool ifPlayAgain(); //重新遊戲
這是所有的函數。
#include <stdio.h>
#include <stdlib.h>
#include"day8.h"
int main()
{
Manager manager;
Control control;
//初始化函數
initGame(&manager,&control);
//initTetris(&manager);
//runGame(&manager,&control);
//初始化結構體
// Output=GetStdHandle(STD_OUTPUT_HANDLE);
do
{ printPrompting();
//printScore(&manager);
printPoolBorder();
// printNextTetris(&manager);//顯示下一個和下下一個方塊
// printTetrisPool(&manager,&control);//顯示遊戲池
// setPoolColor(&manager,&control);
// insertTetris(&manager);
// setPoolColor(&manager,&control);
runGame(&manager,&control);
if(ifPlayAgain())
{
SetConsoleTextAttribute(Output,0x7);
system("cls");//清屏
startGame(&manager,&control);
}
else
{
break;
}
}while(1);
}
//進行全角定位
void gotoxyWithFullwidth(short x,short y)
{
static COORD cd;
cd.X=(x*2);
cd.Y=y;
SetConsoleCursorPosition(Output,cd);
}
//顯示提示信息
void printPrompting()
{
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(26,10);
printf("■控制:");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,12);
printf("□向左移動:← A 4");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,13);
printf("□向右移動:→ D 6");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,14);
printf("□向下移動:↓ S 2");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,15);
printf("□順時針轉:↑ W 8");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,16);
printf("□逆時針轉:0");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,17);
printf("□直接落地:空格");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,18);
printf("□暫停遊戲:回車");
}
//顯示分數
void printScore(const Manager *manager)
{
static const char *tetrisbName="ITLJZSO";
int i;
SetConsoleTextAttribute(Output,14);
gotoxyWithFullwidth(2,2);
printf("■得分:%u",manager->score);
//顯示消行總數
gotoxyWithFullwidth(1,6);
printf("■消行總數:%u",manager->erasedTotal);
for(i=0;i<4;++i)
{
gotoxyWithFullwidth(2,8+i);
printf("□消%d:%u",i+1,manager->erasedCount[i]);
}
//輸出方塊總數
gotoxyWithFullwidth(1,15);
printf("■方塊總數:%u",manager->tetrisTotal);
//輸出每一行方塊數
for(i=0;i<7;++i)
{
gotoxyWithFullwidth(2,17+i);
printf("□%c形:%u",tetrisbName[i],manager->tetrisCount[i]);
}
}
//顯示遊戲池邊界
void printPoolBorder()
{ int j;
//背景高亮白 11110000
SetConsoleTextAttribute(Output,0xf0);
/* //顯示縱線
for(i=1;i<24;++i)
{
gotoxyWithFullwidth(10,i);
printf("%2s","");
gotoxyWithFullwidth(23,i);
printf("%2s","");
}
//顯示橫線
for(j=0;j<12;++j)
{gotoxyWithFullwidth(11+j,23);
printf("%2s","");
}
*/
for(j=4;j<26;++j)
{
//顯示縱線
gotoxyWithFullwidth(10,j-3);
printf("%2s","");
gotoxyWithFullwidth(23,j-3);
printf("%2s","");
}
//顯示橫線
gotoxyWithFullwidth(10,j-3);
printf("%28s","");
}
//初始化遊戲
void initGame(Manager *manager,Control *control)
{
//設置一個光標隱藏變量並初始化
CONSOLE_CURSOR_INFO cursorInfo={1,FALSE};
//獲取控制檯輸入句柄
Output=GetStdHandle(STD_OUTPUT_HANDLE);
//設置光標隱藏
SetConsoleCursorInfo(Output,&cursorInfo);
//設置控制檯標題
SetConsoleTitle("俄羅斯方塊");
//調用一個遊戲開始函數
startGame(manager,control);
}
//開始遊戲
void startGame(Manager *manager,Control *control)
{
//初始化結構體
memset(manager,0,sizeof(Manager));
memset(control,0,sizeof(Control));
//初始化遊戲池
memcpy(manager->pool,gs_uInitialTetrisPool,sizeof(unsigned int[28]));
//設置隨機數種子
srand((unsigned)time(NULL));
//初始化下一個方塊
manager->type[1]=rand()%7;
manager->orientation[1]=rand()%4;
//初始化下下一個方塊
manager->type[2]=rand()%7;
manager->orientation[2]=rand()%4;
memset(control,0,sizeof(Control));
//初始化遊戲
initTetris(manager);//給下一個方塊
//設置顏色
setPoolColor(manager,control);
}
//顯示下一個和下下一個方塊
void printNextTetris(const Manager *manager)
{
unsigned int tetris;
int i;
//邊框
SetConsoleTextAttribute(Output,15);
gotoxyWithFullwidth(26,1);
printf("■■■■■■■■■■■");
gotoxyWithFullwidth(26,2);
printf("■%8s■%8s■","","");
gotoxyWithFullwidth(26,3);
printf("■%8s■%8s■","","");
gotoxyWithFullwidth(26,4);
printf("■%8s■%8s■","","");
gotoxyWithFullwidth(26,5);
printf("■%8s■%8s■","","");
gotoxyWithFullwidth(26,6);
printf("■■■■■■■■■■■");
//顯示下一個方塊
tetris=TetrisTable[manager->type[1]][manager->orientation[1]];
SetConsoleTextAttribute(Output,manager->type[1]|8);
for(i=0;i<16;++i)
{
gotoxyWithFullwidth((i&3)+27,(i>>2)+2);
((tetris>>i)&1)?(printf("■")):printf("%2s","");
};
//顯示下下一個方塊
tetris=TetrisTable[manager->type[2]][manager->orientation[2]];
SetConsoleTextAttribute(Output,manager->type[2]|8);
for(i=0;i<16;++i)
{
gotoxyWithFullwidth((i&3)+32,(i>>2)+2);
((tetris>>i)&1)?(printf("■")):printf("%2s","");
};
gotoxyWithFullwidth(50,27);
printf("by:yaoe");
}
//顯示遊戲池 gotoxyInPool(2,4)等價於gotoxyWithFullwidth(11,1)
#define gotoxyInPool(x,y) gotoxyWithFullwidth(x+9,y-3)
void printTetrisPool(const Manager *manager,const Control *control)
{
int x,y;
for (y=4;y<=25;++y)
{
gotoxyInPool(2,y);//把光標打到每行的開頭
for(x=2;x<=13;++x)
{
if((manager->pool[y]>>x)&1)//將每一行都遍歷一遍
{
//用相應顏色,顯示一個實心方塊
SetConsoleTextAttribute(Output,control->color[y][x]);
printf("■");
}
else//沒有方塊,顯示空白
{
SetConsoleTextAttribute(Output,0);
printf("%2s","");
}
}
}
}
//方塊初始化,構造當前方塊
void initTetris(Manager *manager)
{
unsigned int tetris;
manager->type[0]=manager->type[1];//下一個方塊變成當前方塊
manager->orientation[0]=manager->orientation[1];
manager->type[1]=manager->type[2];//下下一個方塊變成當前方塊
manager->orientation[1]=manager->orientation[2];
manager->type[2]=rand()%7;//隨機生成下下下一個方塊
manager->orientation[2]=rand()%4;
tetris=TetrisTable[manager->type[0]][manager->orientation[0]];//當前方塊
manager->y=0;
manager->x=6;
if(checkCollision(manager))
{
manager->dead=true;
}
else
{
insertTetris(manager);//將當前方塊加入遊戲池
}
++manager->tetrisTotal;//方塊總數
++manager->tetrisCount[manager->type[0]];//對應方塊數
printScore(manager);
printNextTetris(manager);//顯示下一個方塊
}
//把當前方塊插入遊戲池中
void insertTetris(Manager *manager)
{
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
//當前方塊每4位取出,位或到遊戲池相應位置,即完成插入方塊
manager->pool[manager->y+0]|=(((tetris>>0x0)&0x000f)<<manager->x);//取方塊的最低4位,放入遊戲池中,取4
manager->pool[manager->y+1]|=(((tetris>>0x4)&0x000f)<<manager->x);//取方塊的次低4位,放入遊戲池中,取3
manager->pool[manager->y+2]|=(((tetris>>0x8)&0x000f)<<manager->x);//取方塊的最高4位,放入遊戲池中,取2
manager->pool[manager->y+3]|=(((tetris>>0xc)&0x000f)<<manager->x);//取方塊的最高4位,放入遊戲池中,取1
}
//設置顏色
void setPoolColor( const Manager *manager, Control *control)
{
int i,x,y;
//當前方塊
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
for(i=0;i<16;++i)
{
y=(i>>2)+manager->y;//待設置的列
if(y>26)//超過底部限制
{
break;
}
x=(i&3)+manager->x;//待設置的行
if((tetris>>i)&1)//檢測的到消方格屬於當前方塊區域
{
control->color[y][x]=(manager->type[0]|8);//設置顏色
}
}
}
//顯示當前方塊
void printCurrentTetris(const Manager *manager,const Control *control)
{
int x,y;
y=(manager->y>4)?(manager->y-1):4;//向上擴展一行
for(;y<26&&y<manager->y+4;++y)
{
x=(manager->x>2)?(manager->x-1):2;//向左擴展一列
for(;x<14&&x<manager->x+5;++x)
{
gotoxyInPool(x,y);
if((manager->pool[y]>>x)&1)
{
SetConsoleTextAttribute(Output,control->color[y][x]);
printf("■");
}
else
{
SetConsoleTextAttribute(Output,0);
printf("%2s","");
}
}
}
}
//碰撞檢測
bool checkCollision(const Manager *manager)
{
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
unsigned int dest=0;//存放我們在新的位置取出來的16位數
//取dest的最低4位
dest|=(((manager->pool[manager->y+0]>>manager->x)<<0x0)&0x000f);
//取dest的次低4位
dest|=(((manager->pool[manager->y+1]>>manager->x)<<0x4)&0x00f0);
//取dest的次高4位
dest|=(((manager->pool[manager->y+2]>>manager->x)<<0x8)&0x0f00);
//取dest的最高4位
dest|=(((manager->pool[manager->y+3]>>manager->x)<<0xc)&0xf000);
return((dest&tetris)!=0);
}
//運行遊戲
void runGame(Manager *manager,Control *control)
{
clock_t clockLast,clockNow;//這裏的clock_t爲長整型,clock_t是用來保存時間
clockLast=clock();//計時
printTetrisPool(manager,control);//顯示遊戲池
while(!manager->dead)//沒掛
{
while(_kbhit())//有鍵按下
{
keydownControl(manager,control,getch());//處理按鍵
}
if(!control->pause)//未暫停
{
clockNow=clock();//計時
//兩次計時的間隔超過0.45秒
if(clockNow-clockLast>0.45F*CLOCKS_PER_SEC)//CLOCKS_PER_SER爲常量,值爲1000
{
clockLast=clockNow;
moveDownTetris(manager,control);
}
}
}
}
//向下移動方塊
void moveDownTetris(Manager *manager,Control *control)
{
int y=manager->y;
removeTetris(manager);//移去當前方塊
++manager->y;
if(checkCollision(manager))
{
manager->y=y;
insertTetris(manager);//放入當前方塊,不需要設置顏色
if(checkErasing(manager,control))
{
printTetrisPool(manager,control);
}
}
else
{
insertTetris(manager);
setPoolColor(manager,control);
printCurrentTetris(manager,control);
}
}
//移去方塊
void removeTetris(Manager *manager)
{
//當前方塊
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
//當前方塊每4位取出,按位取反後位與到遊戲池相應位置,即完成移除方塊
manager->pool[manager->y+0]&=~(((tetris>>0x0)&0x000F)<<manager->x);
manager->pool[manager->y+1]&=~(((tetris>>0x4)&0x000F)<<manager->x);
manager->pool[manager->y+2]&=~(((tetris>>0x8)&0x000F)<<manager->x);
manager->pool[manager->y+3]&=~(((tetris>>0xc)&0x000F)<<manager->x);
}
bool checkErasing(Manager *manager,Control *control)
{
static const unsigned scores[5]={0,10,30,90,150};
int count=0;//本次的消行數
int y=manager->y+3;//從下往上檢測
do
{
if(y<26&&manager->pool[y]==0xffff)//有效區域內
{
++count;//
memmove(manager->pool+1,manager->pool,sizeof(unsigned int )*y);
memmove(control->color[1],control->color[0],sizeof(int [16])*y);
}
else
{
--y;
}
}while(y>=manager->y);
manager->erasedTotal+=count;//消行總分
manager->score+=scores[count];//得分
if(count>0)
{
++manager->erasedCount[count-1];//消行
}
initTetris(manager);//初始化方塊
setPoolColor(manager,control);//設置顏色
return(count>0);
}
void horzMoveTetris(Manager *manager,Control *control)
{
int x=manager->x;//記錄原列位置
removeTetris(manager);//在原來的位置移除方塊
control->direction==0?(--manager->x):(++manager->x);//選擇移動
if(checkCollision(manager))
{
manager->x=x;//恢復原來的位置
insertTetris(manager);//放入當前方塊,由於位置未變,不需要設置顏色
}
else
{
insertTetris(manager);//在新位置放入方塊
setPoolColor(manager,control);//設置顏色
printCurrentTetris(manager,control);//顯示當前方塊
}
}
void rotateTetris(Manager *manager,Control *control)
{
int ori=manager->orientation[0];//記錄原旋轉狀態
removeTetris(manager);//
manager->orientation[0]=(control->clockwise)?((ori+1)&3):((ori+3)&3);
if(checkCollision(manager))
{
manager->orientation[0]=ori;//恢復原來的位置
insertTetris(manager);//放入當前方塊,由於位置未變,不需要設置顏色
}
else
{
insertTetris(manager);//在新位置放入方塊
setPoolColor(manager,control);//設置顏色
printCurrentTetris(manager,control);//顯示當前方塊
}
}
void keydownControl(Manager *manager,Control *control,int key)
{
if(key==13)//暫停或解除暫停
{
control->pause=!control->pause;
}
if(control->pause)//暫停狀態,不作處理
{
return;
}
switch(key)
{
case 72://上
rotateTetris(manager,control);//旋轉方塊
break;
case 80://下
moveDownTetris(manager,control);//向下移動方塊
break;
case 75://左
control->direction=0;
horzMoveTetris(manager,control);//水平移動方塊
break;
case 77://右
control->direction=1;
horzMoveTetris(manager,control);//水平移動方塊
break;
case ' '://直接落地
dropDownTetris(manager,control);
break;
default:
break;
}
}
void dropDownTetris(Manager *manager,Control *control)
{
removeTetris(manager);//移走當前方塊
for(;manager->y<26;++manager->y)
{
if(checkCollision(manager))//檢測到碰撞
{
break;
}
}
--manager->y;
insertTetris(manager);
setPoolColor(manager,control);
checkErasing(manager,control);
printTetrisPool(manager,control);
}
//重玩一次
bool ifPlayAgain()
{
int ch;
SetConsoleTextAttribute(Output,0xf0);
gotoxyWithFullwidth(15,10);
printf("遊戲結束");
gotoxyWithFullwidth(13,11);
printf("按Y重玩,按N退出");
do
{
ch=_getch();
if(ch=='Y'||ch=='y')
{
return true;
}
else if(ch=='N'||ch=='n')
{
return false;
}
}while(1);
}
容我偷回懶O(∩_∩)O
#ifndef DAY8_H_INCLUDED
#define DAY8_H_INCLUDED
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include<time.h>
#include<conio.h>
#include<windows.h>
#include<stdbool.h>
typedef struct TetrisManager
{
unsigned int pool[28]; //遊戲池 //遊戲池
int x; //當前方塊橫座標,此處座標爲X軸左上角橫座標
int y; //當前方塊縱座標,此處座標爲Y軸左上角縱座標
int type[3]; //當前、下一個和下下一個方塊的類型
int orientation[3]; //當前、下一個和下下一個方塊的旋轉狀態
unsigned score; //得分
unsigned erasedCount[4]; //消行數
unsigned erasedTotal; //消行總數
unsigned tetrisCount[7]; //消方塊數
unsigned tetrisTotal; //方塊總數
bool dead; //遊戲是否結束
}Manager;
typedef struct TetrisControl
{
bool pause; //暫停
bool clockwise; //旋轉方向:順時針爲true
int direction; //移動方向:0向左運動,1向右運動
int color[28][16];
}Control;
static const unsigned int TetrisTable[7][4]=
{
{0x00f0,0x2222,0x00F0,0x2222}, //I型
{0x0072,0x0262,0x0270,0x0232}, //T型
{0x0223,0x0074,0x0622,0x0170}, //L型
{0x0226,0x0470,0x0322,0x0071}, //J型
{0x0063,0x0264,0x0063,0x0264}, //Z型
{0x006C,0x0462,0x006c,0x0462}, //S型
{0x0660,0x0660,0x0660,0x0660} //O型
};
static const unsigned int gs_uInitialTetrisPool[28]= //初始狀態的遊戲池,還沒有插入方塊
{
0xc003,0xc003,0xc003,0xc003,0xc003,0xc003,0xc003,
0xc003,0xc003,0xc003,0xc003,0xc003,0xc003,0xc003,
0xc003,0xc003,0xc003,0xc003,0xc003,0xc003,0xc003,
0xc003,0xc003,0xc003,0xc003,0xc003,0xffff,0xffff
};
HANDLE Output;
void printPrompting(); //顯示提示信息
void gotoxyWithFullwidth(short x,short y); //進行全角定位
void printScore(const Manager *manager); //顯示分數
void printPoolBorder(); //顯示遊戲池邊界
void initGame(Manager *manager,Control *control); //初始化遊戲
void startGame(Manager *manager,Control *control); //開始遊戲
void printNextTetris(const Manager *manager); //顯示下一個和下下一個方塊
void printTetrisPool(const Manager *manager,const Control *control); //顯示遊戲池
void initTetris(Manager *manager); //方塊初始化,構造當前方塊
void insertTetris(Manager *manager); //把當前方塊插入遊戲池中
void setPoolColor(const Manager *manager,Control *control); //設置顏色
void printCurrentTetris(const Manager *manager,const Control *control); //顯示當前方塊
bool checkCollision(const Manager *manager); //碰撞檢測
void runGame(Manager *manager,Control *control); //運行遊戲
void moveDownTetris(Manager *manager,Control *control); //向下移動方塊
void removeTetris(Manager *manager); //移去方塊
bool checkErasing(Manager *manager,Control *control);
void horzMoveTetris(Manager *manager,Control *control);
void rotateTetris(Manager *manager,Control *control);
void keydownControl(Manager *manager,Control *control,int key);
void dropDownTetris(Manager *manager,Control *control);
bool ifPlayAgain();
#endif // DAY8_H_INCLUDED
頭文件 ↑
暫且寫這些以後再改(o゚v゚)ノ
2018.6