C語言代碼實現俄羅斯方塊

這裡為大傢敲寫一段怎樣用C語言實現俄羅斯方塊:

首先推薦大傢使用CodeBlocks這個軟件,方便添加不同的工程。
代碼中有很多註釋便於理解!

下面是效果圖和全部的代碼以及註釋,大傢可以觀看並自己新增內容!

1、首先是main.c文件:

#include <stdio.h>
#include <stdlib.h>
#include "game.h"

int main()
{
 gameInit();
 return 0;
}

2、然後是mywindows.h文件:

#ifndef MYWINDOWS_H_INCLUDED
#define MYWINDOWS_H_INCLUDED

// 封裝系統函數-系統調用模塊
#include <windows.h>

// 初始化句柄
extern void initHandle();

// 設置顏色
extern void setColor(int color);

// 設置光標位置
extern void setPos(int x, int y);

// 設置光標是否可見
extern void setCursorVisible(int flag);

// 關閉句柄
extern void closeHandle();

#endif // MYWINDOWS_H_INCLUDED

3、接下來是mywindows.c文件:

#include "mywindows.h"

HANDLE handle;

// 初始化句柄
void initHandle()
{
 handle = GetStdHandle(STD_OUTPUT_HANDLE);
}

// 設置顏色
void setColor(int color)
{
 SetConsoleTextAttribute(handle, color);
}

void setPos(int x, int y)
{
 //, ,
 COORD coord = {x*2, y};
 SetConsoleCursorPosition(handle, coord);
}

// 設置光標是否可見
void setCursorVisible(int flag)
{
 CONSOLE_CURSOR_INFO info;
 info.bVisible = flag; //光標是否可見
 info.dwSize = 100;  //光標寬度1-100
 SetConsoleCursorInfo(handle, &info);
}

// 關閉句柄
void closeHandle()
{
 CloseHandle(handle);
}

4、下面是data.h文件,也就是數據庫的存儲地址:

#ifndef DATA_H_INCLUDED
#define DATA_H_INCLUDED


//函數聲明\變量聲明
// 存儲數據-數據模塊
//界面數組
extern int windowShape[25][26];

extern int block[7][4][4][4];

#endif // DATA_H_INCLUDED

5、數據庫內容:data.c

#include "data.h"

//函數的定義

int windowShape[25][26] =
{
 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};// 邊框為1,遊戲池長度為14


int block[7][4][4][4] =
{
 {
  //Z{}
  {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
  {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
  {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
  {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}
 },
 {
  //S
  {{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
  {{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}
 },
 {
  //L{}
  {{1,0,0,0},{1,0,0,0},{1,1,0,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,0}}
 },
 {
  //J
  {{0,1,0,0},{0,1,0,0},{1,1,0,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,0}},
  {{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}}
 },
 {
  //I{}
  {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},
  {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}
 },
 {
  //T
  {{1,1,1,0},{0,1,0,0},{0,0,0,0},{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}},
  {{1,0,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}
 },
 {
  //田
  {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
  {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}
 }


};

6、遊戲頭部:game.h:

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

// 遊戲邏輯模塊

#include <stdio.h>
#include <time.h>

typedef struct{
 int x;
 int y;
 int shape;
 int status;
 int color;
}BLOCK;

// 定義當前正在下落的方塊,和下一個方塊
BLOCK curBlock;
BLOCK nextBlock;

// 繪制遊戲池邊框
extern void gamePool(int x, int y);

// 打印操作說明
extern void printRule();

// 打印分數和等級
extern void printGradeLevel(int num);

// 遊戲計時
extern void gameTime(clock_t startTime);

// 打印一個方塊
extern void printBlock(int x, int y, int shape, int status, int color);

// 刪除一個方塊
extern void delBlock(int x, int y, int shape, int status);

//方塊左移
extern void leftBlock();

//方塊右移
extern void rightBlock();

//方塊下移
extern int downBlock();

//方塊變形
extern void changeBlock();

//方塊直接落底
extern void bottomBlock();

//遊戲暫停
extern void pause();

//隨機產生遊戲第一個方塊
extern void startBlock();

//隨機產生下一個方塊
extern void blockNext();

//拷貝方塊:把下一個方塊變成當前正在下落的方塊
extern void copyBlock();

//碰撞檢測
extern int crash(int x, int y, int shape, int status);

//保存方塊
extern void saveBlock();

//刷新遊戲池
extern void updateGamePool();

//消行檢測
extern void lineClear();

//消行下移
extern void lineDown(int line);

// 初始化遊戲
extern void gameInit();


#endif // GAME_H_INCLUDED

7、最後一部分,遊戲內容,game.c文件:

#include "game.h"
#include "mywindows.h"
#include "data.h"
#include <conio.h>

int level = 1;
int grade = 100;

// 打印遊戲池
void gamePool(int x, int y)
{
 int i, j;
 for(i=0;i<25;i++)
 {
  for(j=0;j<26;j++)
  {
   if(windowShape[i][j] == 1)
   {
    setColor(0xc0);
    setPos(x+j,y+i);
    printf(" "); // printf("%2s", "");
   }
  }
 }
}

// 打印操作說明
void printRule()
{
 setColor(0x0f);
 setPos(31, 9);
 printf("操作規則:");
 setPos(32, 11);
 printf("按a或A左移");
 setPos(32, 12);
 printf("按d或D右移");
 setPos(32, 13);
 printf("按s或S下移");
 setPos(32, 14);
 printf("按w或W變形");
 setPos(32, 15);
 printf("按空格暫停");
 setPos(32, 16);
 printf("按回車直接下落");

}

void printGradeLevel(int num)
{
 switch(num)
 {
  case 0: break;
  case 1: grade += 10;break;
  case 2: grade += 25;break;
  case 3: grade += 50;break;
  case 4: grade += 70;break;
 }

 //等級-->作業

 setColor(0x09);
 setPos(3,6);
 printf("分數:%d", grade);

 setColor(0x0a);
 setPos(3,7);
 printf("等級:%d", level);
}

void gameTime(clock_t startTime)
{
 //clock_t endTime = clock();
 //clock_t ti = (endTime-startTime)/CLOCKS_PER_SEC;
 setColor(0x0d);
 setPos(3,8);
 printf("本次遊戲運行時間:%ld", (clock()-startTime)/CLOCKS_PER_SEC);
}

// 打印一個方塊
void printBlock(int x, int y, int shape, int status, int color)
{
 int i,j;
 setColor(color);
 for(i=0;i<4;i++)
 {
  for(j=0;j<4;j++)
  {
   if(1 == block[shape][status][i][j])
   {
    setPos(x+j,y+i);
    printf("■");
   }
  }
 }
}

// 刪除一個方塊
void delBlock(int x, int y, int shape, int status)
{
 int i, j;
 for(i=0;i<4;i++)
 {
  for(j=0;j<4;j++)
  {
   if(1 == block[shape][status][i][j])
   {
    setPos(x+j,y+i);
    printf(" "); //打印兩個空格
   }
  }
 }
}

//方塊左移
void leftBlock()
{
 //已經顯示的方塊刪除,改變坐標,重新打印
 if(crash(curBlock.x-1, curBlock.y, curBlock.shape,curBlock.status) == -1)
 {
  return;
 }
 delBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status);
 curBlock.x -= 1;
 printBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status,curBlock.color);
}

//方塊右移
void rightBlock()
{
 if(crash(curBlock.x+1, curBlock.y, curBlock.shape,curBlock.status) == -1)
 {
  return;
 }
 delBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status);
 curBlock.x += 1;
 printBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status,curBlock.color);
}

//方塊下移
int downBlock()
{
 if(crash(curBlock.x, curBlock.y+1,curBlock.shape,curBlock.status) == -1)
 {
  //落到遊戲池底部,產生新方塊
  saveBlock();
  lineClear();
  updateGamePool();
  copyBlock();
  return -1;
 }else if(crash(curBlock.x, curBlock.y+1,curBlock.shape,curBlock.status) == -2)
 {
  //遊戲結束
  return -2;
 }else{
  delBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status);
  curBlock.y += 1;
  printBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status,curBlock.color);
  return 0;
 }

}

//方塊變形
void changeBlock()
{
 if(crash(curBlock.x, curBlock.y, curBlock.shape, (curBlock.status+1)%4) == -1){
  return;
 }
 delBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status);
 curBlock.status = (curBlock.status+1)%4;
 printBlock(curBlock.x,curBlock.y,curBlock.shape,
    curBlock.status,curBlock.color);
}

//方塊直接落底
void bottomBlock()
{
 while(1){
  //流程參考方塊下落
  if(downBlock() !=0){
   return;
  }
 }
}

//遊戲暫停
void pause()
{
 //
}

//隨機產生遊戲第一個方塊
void startBlock()
{
 //設置時間為隨機數種子
 srand((unsigned)time(NULL));
 //初始化curBlock
 curBlock.x = 22;
 curBlock.y = 1;
 //rand取一個隨機整數
 curBlock.shape = rand()%7; //0-6
 curBlock.status = rand()%4; //0-3
 curBlock.color = rand()%0x10;
 if(0x00 == curBlock.color)
 {
  curBlock.color = 0x0f;
 }
 printBlock(curBlock.x, curBlock.y, curBlock.shape,
    curBlock.status, curBlock.color);
}

//隨機產生下一個方塊
void blockNext()
{
 //初始化nextBlock
 delBlock(nextBlock.x,nextBlock.y,
    nextBlock.shape,nextBlock.status);
 nextBlock.x = 34;
 nextBlock.y = 2;
 nextBlock.shape = rand()%7;
 nextBlock.status = rand()%4;
 nextBlock.color = rand()%0x10;
 if(0x00 == nextBlock.color)
 {
  nextBlock.color = 0x0f;
 }
 printBlock(nextBlock.x,nextBlock.y,
    nextBlock.shape,nextBlock.status,nextBlock.color);
}

//拷貝方塊:把下一個方塊變成當前正在下落的方塊
void copyBlock()
{
 //當前方塊=下一個方塊
 curBlock = nextBlock;
 curBlock.x = 22;
 curBlock.y = 1;
 printBlock(curBlock.x, curBlock.y, curBlock.shape,
    curBlock.status, curBlock.color);
 blockNext();
}

//碰撞檢測
//x,y為方塊的下一個位置, status下一種形態
//碰撞返回-1,未碰撞返回0, 遊戲結束返回-2
int crash(int x, int y, int shape, int status)
{
 int i,j;
 for(i=0;i<4;i++)
 {
  for(j=0;j<4;j++)
  {
   if(block[shape][status][i][j] == 1)
   {
    if(windowShape[i+y][j+x-15] == 1)
    {
     //方塊一產生就發生碰撞
     if(curBlock.x == 22 && curBlock.y == 1)
     {
      return -2;
     }
     return -1;
    }
   }
  }
 }
 return 0;
}

//保存方塊
void saveBlock()
{
 int i,j;
 for(i=0;i<4;i++)
 {
  for(j=0;j<4;j++)
  {
   if(block[curBlock.shape][curBlock.status][i][j] == 1)
   {
    windowShape[i+curBlock.y][j+curBlock.x-15] = 1;
   }
  }
 }
}

//刷新遊戲池
void updateGamePool()
{
 int i,j;
 //從下到上刷新遊戲池
 for(i=23;i>0;i--)
 {
  for(j=1;j<15;j++)
  {
   if(windowShape[i][j] == 1)
   {
    setColor(0x0e);
    setPos(j+15,i);
    printf("■");
   }else{
    setColor(0x00);
    setPos(j+15,i);
    printf(" ");
   }
  }
 }
}

//消行檢測
//檢測滿行->這一行所有值都為1
void lineClear()
{
 int i,j;
 int num = 0; //統計一次消行數目
 for(i=23;i>0;i--)
 {
  int total = 0;
  for(j=1;j<15;j++)
  {
   total += windowShape[i][j];
  }
  if(total == 14)
  {
   //滿行
   lineDown(i);
   i += 1;
   num += 1;
  }
 }
 printGradeLevel(num);
}

//消行下移
//從滿行的這行開始,上面所有行順序下移
void lineDown(int line)
{
 int i,j;
 for(i=line;i>1;i--)
 {
  for(j=1;j<15;j++)
  {
   windowShape[i][j] = windowShape[i-1][j];
  }
 }
}


// 初始化遊戲
void gameInit()
{
 //第一步,必須初始化句柄
 //clock_t startTime = clock();
 initHandle();
 setCursorVisible(FALSE);

 gamePool(15,0);
 printRule();
 printGradeLevel(0);

 startBlock();
 blockNext();
 //定時開始時間,結束時間,通過控制時間差實現定時
 clock_t start,stop;
 start = clock();

 while(1)  //for(;;)
 {
  //檢測是否有按鍵按下
  if(kbhit())
  {
   switch(getch())
   {
   case 'a':
   case 'A':
   case 75:
    leftBlock();break;
   case 'd':
   case 'D':
   case 77:
    rightBlock();break;
   case 's':
   case 'S':
   case 80:
    downBlock();break;
   case 'w':
   case 'W':
   case 72:
    changeBlock();break;
   case 32:
    pause();break;
   case 13:
    bottomBlock();break;
   }
  }
  //獲取時間
  stop = clock();
  if(stop-start>0.5*CLOCKS_PER_SEC)
  {
   downBlock();
   //重新計時
   start = stop;
  }
 }
}

好,到現在這個遊戲也就結束瞭!

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: