C++控制台实现俄罗斯方块游戏

之前学了些C++的课程,一直想着说编点小游戏,可是MFC又不想学,所以就只能变成控制台的小游戏。

俄罗斯方块一定是很多人小时候玩过的游戏。接下来就说说设计想法。

主要实现,选择游戏的等级,加速下降,不同形状不同颜色,暂停和退出功能。

首先是类的设计。

class Box
{
  private:
    int map[23][12];//画面坐标,记录有方块的点,也是游戏界面
    int hotpoint[2];//当前活动的点,所有图形都是以此为基准绘制的
    int top;//当前最高位置
    int point;//分数
    int level;//等级
    int ID;//当前活动图形的ID号
    int colorID;//图形的颜色ID。
  public:
    Box()//初始化
    {
      int i,j;
      for(i=0;i<23;i++)
        for(j=0;j<12;j++)
          map[i][j]=0;
      hotpoint[0]=0;
      hotpoint[1]=5;
      point=0;
      level=1;
      top=99;
      ID=0;
    }
    void SetColor(int color);//颜色
    void DrawMap();//画游戏的大界面
    bool Judge(int x,int y);//判断当前位置能否绘制图形
    void Welcome();//欢迎界面
    void DrawBox(int x,int y,int num);//绘制图形
    void Redraw(int x,int y,int num);//擦除图形
    void Run();//运行
    void Turn();//转动方块
    void UpdataMap();//更新画面
    void Pause();//暂停
};

接下来就是一些常量和光标函数,便于保存和调用

#define A1 0//A代表长条型,B为方块,C为L型,D为闪电型
#define A2 1 

#define B 2 

#define C11 3
#define C12 4
#define C13 5
#define C14 6 

#define C21 7
#define C22 8
#define C23 9
#define C24 10 

#define D11 11
#define D12 12 

#define D21 13
#define D22 14 

void SetPos(int i,int j)//设定光标位置
{
COORD pos={i,j};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
} 

const int sharp[15][8]=
{
{0,0,1,0,2,0,3,0},{0,0,0,1,0,2,0,3},
{0,0,1,0,0,1,1,1},
{0,0,1,0,1,1,1,2},{0,1,1,1,2,0,2,1},{0,0,0,1,0,2,1,2},{0,0,0,1,1,0,2,0},
{1,0,1,1,1,2,0,2},{0,0,0,1,1,1,2,1},{0,0,0,1,0,2,1,0},{0,0,1,0,2,0,2,1},
{0,0,0,1,1,1,1,2},{0,1,1,0,1,1,2,0},
{0,1,0,2,1,0,1,1},{0,0,1,0,1,1,2,1}
};//形状点的各个坐标,先纵后横 

const int high[15]={4,1,2,2,3,2,3,2,3,2,3,2,3,2,3};//这个数组是用来保存各个形状高度的,以上面的坐标相对应

类方法的实现

void Box::SetColor(int colorID)
{
  int n_color;
  switch(colorID)
  {
    case 0: n_color = 0x08;break;
    case 1: n_color = 0x0C;break;
    case 2: n_color = 0x0D;break;
    case 3: n_color = 0x0E;break;
    case 4: n_color = 0x0A;break;
  }
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n_color);
}
void Box::DrawMap()//画界面
{
  int i; 

  SetColor(0);//界面颜色 

  for(i=0;i<14;i++)
  {
     SetPos(i*2,0);
     cout<<"■";
  }
  for(i=1;i<=24;i++)
  {
    SetPos(0,i);
    cout<<"■";
    SetPos(13*2,i);
    cout<<"■";
  }
  for(i=0;i<14;i++)
  {
     SetPos(i*2,24);
     cout<<"■";
  } 

  i=15;
  for(i=15;i<=25;i++)
  {
     SetPos(i*2,0);
     cout<<"■";
  }
  for(i=1;i<=8;i++)
  {
    SetPos(15*2,i);
    cout<<"■";
    SetPos(25*2,i);
    cout<<"■";
  }
  for(i=15;i<=25;i++)
  {
     SetPos(i*2,9);
     cout<<"■";
  } 

  SetPos(16*2,16);
  cout<<"俄罗斯方块";
  SetPos(16*2,17);
  cout<<"分数:"<<point;
  SetPos(16*2,18);
  cout<<"级别:"<<level;
} 

void Box::DrawBox(int x,int y,int num)//绘制图形
{
   int i;
   int nx,ny;
   if (num<2)SetColor(1);//0、1是长条
   else if(num<3) SetColor(2);//2 方块
   else if(num<11) SetColor(3);//3、4、5、6、7、8、9、10
   else SetColor(4);
   for(i=0;i<4;i++)
  {
    nx=x+sharp[num][i*2];
    ny=y+sharp[num][i*2+1];
    SetPos((ny+1)*2,nx+1);//利用sharp数组相对于点x,y绘制形状
    //SetColor(i+1);
    cout<<"■";
  }
} 

void Box::Redraw(int x,int y,int num)//擦除图形,原理同上
{
   int i;
   int nx,ny;
   for(i=0;i<4;i++)
  {
    nx=x+sharp[num][i*2];
    ny=y+sharp[num][i*2+1];
    SetPos((ny+1)*2,nx+1);
    cout<<" ";
  }
} 

void Box::Turn()//转动图形,单纯的该ID而已
{
  switch(ID)
  {
    case A1: ID=A2; break;
    case A2: ID=A1; break; 

    case B: ID=B; break; 

    case C11: ID=C12; break;
    case C12: ID=C13; break;
    case C13: ID=C14; break;
    case C14: ID=C11; break; 

    case C21: ID=C22; break;
    case C22: ID=C23; break;
    case C23: ID=C24; break;
    case C24: ID=C21; break; 

    case D11: ID=D12; break;
    case D12: ID=D11; break; 

    case D21: ID=D22; break;
    case D22: ID=D21; break;
  } 

} 

void Box::Welcome()//欢迎界面
{
  char x;
  while(1)
  {
   system("cls");
   cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;
   cout<<"■    俄罗斯方块控制台版    ■"<<endl;
   cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;
   cout<<"■   A,D左右移动 S向下加速    ■"<<endl;
   cout<<"■   W 转动方块  P暂停游戏    ■"<<endl;
   cout<<"■      Q退出游戏       ■"<<endl;
   cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;
   cout<<"■                 ■"<<endl;
   cout<<"■    按1-9选择等级!!     ■"<<endl;
   cout<<"■                 ■"<<endl;
   cout<<"■                 ■"<<endl;
   cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;
   SetPos(16,9);
   x=getch();
   if(x<='9'&&x>='1')//设置等级
   {
     level=x-'0';
     break;
   }
  }
} 

void Box::UpdataMap()//更新画面(关键)
{
   int clear;
   int i,j,k;
   int nx,ny;
   int flag;
   for(i=0;i<4;i++)//更新map数组的信息
   {
    nx=hotpoint[0]+sharp[ID][i*2];
    ny=hotpoint[1]+sharp[ID][i*2+1];
    map[nx][ny]=1;
   }
   if(hotpoint[0]<top)//如果热点高于顶点则更新顶点,这里0表示的是纵向的
     top=hotpoint[0];
   clear=0;//消除的格数
   for(i=hotpoint[0];i<hotpoint[0]+high[ID];i++)
   {
     flag=0;
     for(j=0;j<12;j++)//检测是否可以消除此行
     {
       if(map[i][j]==0)//代表有空格,不能消除
       {
         flag=1;//1表示不能消除
         break;
       }
     }
     if(flag==0)//可以消除
     {
       for(k=i;k>=top;k--)//从当前位置向上所有的点下移一行
       {
         if(k==0)//最高点特殊处理
           for(j=0;j<12;j++)
           {
             map[k][j]=0;
             SetPos((j+1)*2,k+1);
             cout<<" ";
           }
         else
         {
           for(j=0;j<12;j++)
           {
             map[k][j]=map[k-1][j];
             SetPos((j+1)*2,k+1);
             if(map[k][j]==0)
              cout<<" ";
             else
              cout<<"■";
           }
         }
       }
       top++;//消除成功,最高点下移
       clear++;
       point+=clear*10*level;
     }
   }
   SetColor(0);
   SetPos(16*2,17);
    cout<<"分数:"<<point;
} 

void Box::Run()//运行游戏
{
  int i=0;
  char x;
  int Count;//计数器
  int nextID;
  int temp;
  srand((int)time(0));//将随机数的起点设置为time(0):不带秒
  ID=rand()%15;//随机生成ID和下一个ID
  nextID=rand()%15;//这里为了方便,其实每个形状不是等概率生成的
  DrawBox(hotpoint[0],hotpoint[1],ID);//绘制图形
  DrawBox(3,17,nextID);
  Count=1000-level*100;//等级决定计数,这里是用Count控制时间,来控制下落的速度
  while(1)
  {
    if(i>=Count)
    {
      i=0;//计数器清零
      if(Judge(hotpoint[0]+1,hotpoint[1]))//如果下个位置无效(即到底)
      {
         UpdataMap();//更新画面
         ID=nextID;//生成新ID,用原等待ID替换为当前ID
         hotpoint[0]=0;//热点更新
         hotpoint[1]=5;
         Redraw(3,17,nextID);
         nextID=rand()%15;
         DrawBox(hotpoint[0],hotpoint[1],ID);
         DrawBox(3,17,nextID);
         if(Judge(hotpoint[0],hotpoint[1]))//无法绘制开始图形,游戏结束
         {
           //getch();
           system("cls");
           SetPos(25,15);
           cout<<"游戏结束!!!最终得分为:"<<point<<endl;
           system("pause");//就是在命令行上输出一行类似于“Press  any  key  to  exit”
           exit(0);//关闭所有文件,退出正在执行的程序,返回0代表正常结束
         }
      }
      else
      {
        Redraw(hotpoint[0],hotpoint[1],ID);//没有到底,方块下移一位
        hotpoint[0]++;//热点下移
        DrawBox(hotpoint[0],hotpoint[1],ID);
      }
    }
    if(kbhit())//读取键盘信息
    {
      x=getch();
      if(x=='a'||x=='A')//左移
      {
         if(Judge(hotpoint[0],hotpoint[1]-1)==0)
         {
           Redraw(hotpoint[0],hotpoint[1],ID);
           hotpoint[1]-=1;
           DrawBox(hotpoint[0],hotpoint[1],ID);
         }
      }
      if(x=='d'||x=='D')//右移
      {
         if(Judge(hotpoint[0],hotpoint[1]+1)==0)
         {
           Redraw(hotpoint[0],hotpoint[1],ID);
           hotpoint[1]+=1;
           DrawBox(hotpoint[0],hotpoint[1],ID);
         }
      }
      if(x=='s'||x=='S')//向下加速!!!!!!!!此处可以改进,可以改进加速效果。改成+3之后,会出现BUG,最后几个无法加速
      {
         if(Judge(hotpoint[0]+3,hotpoint[1])==0)
         {
           Redraw(hotpoint[0],hotpoint[1],ID);
           hotpoint[0]+=1;
           DrawBox(hotpoint[0],hotpoint[1],ID);
         }
      }
      if(x=='w'||x=='W')//转动方块
      {
        temp=ID;
        Turn();
        if(!Judge(hotpoint[0],hotpoint[1]))
         {
           Redraw(hotpoint[0],hotpoint[1],temp);
           DrawBox(hotpoint[0],hotpoint[1],ID);
         }
        else
          ID=temp;
      }
      if(x=='p'||x=='P')
      {
        //getch();
        //system("cls");
        Pause();
      }
      if(x=='q'||x=='Q')
      {
        system("cls");
        SetPos(25,15);
        cout<<"游戏结束!!!最终得分为:"<<point<<endl;
        system("pause");
        exit(0);
      }
      while(kbhit())//读掉剩下的键盘信息
        getch();
    }
    Sleep(1);//等待1毫秒
    i++;//计数器加1
  }
} 

int Box::Judge(int x,int y)//判断当前是否可以绘制方块
{
  int i;
  int nx,ny;
  for(i=0;i<4;i++)
  {
    nx=x+sharp[ID][i*2];
    ny=y+sharp[ID][i*2+1];
    if(nx<0||nx>=23||ny<0||ny>=12||map[nx][ny]==1)//不能,返回1
      return 1;
  }
  return 0;
}
void Box::Pause()
{
  system("cls");
  while(1)
  {
    SetPos(30,13);
    cout<<"暂停等待,咖啡时间^-^"<<endl;
    if(getch()=='p'||getch()=='P')
      break;
  }
  SetPos(30,13);
  cout<<"              "<<endl;
  DrawMap();
  int i ,j;
  for(i=0;i<23;i++)
    for(j=0;j<12;j++)
      if(map[i][j]==1)
      {
        SetPos((j+1)*2,i+1);
        cout<<"■";
      }
}
void main()//主函数
{
  Box game;
  game.Welcome();
  system("cls");
  game.DrawMap();
  game.Run();
}

待改进的点: 

1、加速下降的时候,从代码中也可以发现,最后几格没法加速。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • VC++ 6.0 C语言实现俄罗斯方块详细教程

    今天把我之前写的大作业分享一下吧,并教你们如何实现,希望你们看了前面的教程也能自己写一个. 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph(x, y);这是先创建一个窗口的函数,以左上角为(0,0),向右为x轴,向下为y轴,其中x表示长x个单位,y表示宽y个单位. 3.关闭图像窗口:closegraph();结束时用来关闭用的. 4.按任意键继续:getch();这个就和getchar();差不多,为了防止以运行完就关了,这样能停顿一下,他的头文件是

  • linux环境下C++实现俄罗斯方块

    本文实例为大家分享了C++实现俄罗斯方块的具体代码,供大家参考,具体内容如下 本程序的运行环境是linux,用到了多线程.创建了一个用来绘图的线程和一个获取按键的线程.程序中有一些需要改善的地方,比如336-338行定义的全局变量以及声明的对象.本来声明的Block和Table对象应该在main函数里面,然后将这两个对象作为参数传递给线程函数getkey.但是好像只能传递一个对象参数给线程函数.希望高手能够对程序进行改进. ps:由于用到了多线程,而pthread不是linux的默认库,所以编译

  • 使用C++一步步实现俄罗斯方块

    一.实验介绍 1.1 实验内容 本节实验我们进行设计俄罗斯方块前的思路分析,以及介绍ncurses 库的使用方法. 1.2 实验知识点 C++ 编程基础 ncurses 库的使用 俄罗斯方块逻辑设计 1.3 实验环境 xface 终端 g++ 编译器 ncurses 库 1.4 适合人群 本课程难度一般,适合有 C++ 编程基础,对游戏设计.逻辑分析感兴趣的同学. 1.5 代码获取 git clone https://github.com/Gamerchen/game_zero.git 二.开发

  • C++制作俄罗斯方块

    缘起: 在玩Codeblocks自带的俄罗斯方块时觉得不错,然而有时间限制.所以想自己再写一个. 程序效果: 主要内容: 程序中有一个board数组,其中有要显示的部分,也有不显示的部分,不显示的部分都存储1. 如下图: shape采用4*4数组(shape)保存.如: 0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 另外用变量row和column保存shape数组左上角在board中的位置. 每次下落或左右移动,先对row和column做出改变,然后检测当前row和column

  • 使用C++一步步实现俄罗斯方块后续

    一.实验简介 1.1 实验内容 本节实验我们将实现俄罗斯方块主要函数的设计,完成基本功能并运行. 1.2 实验知识点 窗口的绘制 方块类的设计 旋转算法 移动.消除函数 1.3 实验环境 xface 终端 g++ 编译器 ncurses 库 1.4 编译程序 编译命令要加上 -l 选项引入 ncurses 库: g++ main.c -l ncurses 1.5 运行程序 ./a.out 1.6 运行结果 二.实验步骤 2.1 头文件 首先包含头文件以及定义一个交换函数和随机数函数,后面用到(交

  • C++实现俄罗斯方块(windows API)

    本文分享的这些俄罗斯方块代码是我最近放假在家里自己写的,虽然以前有过看别人写的代码,但是那个游戏代码好像不是很全面,因为无法实现全部的方块和实现随机的产生任意方向的方块,现在也基本上是忘光了当时的代码,下面的这些代码是我最近写的,没有参考其他人的代码,真正写俄罗斯方块起来感觉真的是挺难的,关键是在于方块的旋转.当然下面的代码仅仅是一个框架,只能够实现大致上的功能,还不全面,贴出来和大家交流学习. 编译器是code::block  +  MinGW ,感觉CB这个IDE真的是太强大,太棒了,下面的

  • C++俄罗斯方块游戏 无需图形库的俄罗斯方块

    本文实例为大家分享了C++俄罗斯方块游戏的具体实现代码,供大家参考,具体内容如下. #include<stdio.h> #include<stdlib.h> #include<windows.h> #include<time.h> #include<conio.h> #define MOD 28 #define SIZE_N 19 #define SIZE_M 12 int cur_x,cur_y; int score,mark,next,map

  • Linux下用C++实现俄罗斯方块

    本文实例为大家分享了C++实现俄罗斯方块游戏代码,供大家参考,具体内容如下 1.block.c #include <stdio.h> #include <termios.h> #include <unistd.h> #include <stdlib.h> #include <setjmp.h> #include <sys/time.h> #include <string.h> #include "block.h&

  • C++控制台实现俄罗斯方块游戏

    之前学了些C++的课程,一直想着说编点小游戏,可是MFC又不想学,所以就只能变成控制台的小游戏. 俄罗斯方块一定是很多人小时候玩过的游戏.接下来就说说设计想法. 主要实现,选择游戏的等级,加速下降,不同形状不同颜色,暂停和退出功能. 首先是类的设计. class Box { private: int map[23][12];//画面坐标,记录有方块的点,也是游戏界面 int hotpoint[2];//当前活动的点,所有图形都是以此为基准绘制的 int top;//当前最高位置 int poin

  • C语言实现简单的控制台三子棋游戏

    用C语言实现简单的控制台三子棋游戏 首先,确定一局游戏的基本流程: 1.创建棋盘并初始化.(将棋盘看作一个二维数组) 2.打印显示出棋盘. 3.玩家落子(玩家通过输入行列坐标的方式来落子). 4.判定胜负关系.(如果玩家胜出,则退出游戏.) 5.电脑落子(随机位置落子) . 6.判定胜负关系(如果电脑胜出,退出游戏.否则,回到步骤 2 继续执行.) 第一步,此处通过构造menu()函数搭建一个简单的交互菜单和玩家交互,用来判断是否开始进行一局游戏. #define _CRT_SECURE_NO_

  • C语言实现控制台扫雷小游戏

    C语言实现控制台"扫雷"小游戏 根据以往的游戏经验,我们能首先可以确定扫雷游戏胜利的规则是:翻开所有不是雷的区域才能算是胜利. 接下来我们需要确定整个程序的设计思路: 1.首先,我们定义两个9*9的二维数还是未翻开的状态组.第一个数组用来表示雷区地图的展开情况,即每个素组元素的位置的状态是处于展开状态还是未展开状态,我们命名为showMap().第二个数组我们用来表示地雷的分布情况,素组中的每个元素位置都被标记为是否为地雷,我们命名为minMap(). 2.初始化两个地图,并将地图打印

  • 用Python编写一个简单的俄罗斯方块游戏的教程

    俄罗斯方块游戏,使用Python实现,总共有350+行代码,实现了俄罗斯方块游戏的基本功能,同时会记录所花费时间,消去的总行数,所得的总分,还包括一个排行榜,可以查看最高记录. 排行榜中包含一系列的统计功能,如单位时间消去的行数,单位时间得分等. 附源码: from Tkinter import * from tkMessageBox import * import random import time #俄罗斯方块界面的高度 HEIGHT = 18 #俄罗斯方块界面的宽度 WIDTH = 10

  • JavaScript实现俄罗斯方块游戏过程分析及源码分享

    观摩一下<编程之美>:"程序虽然很难写,却很美妙.要想把程序写好,需要写好一定的基础知识,包括编程语言.数据结构与算法.程序写得好,需要缜密的逻辑思维能力和良好的梳理基础,而且熟悉编程环境和编程工具." 学了几年的计算机,你有没有爱上编程.话说,没有尝试自己写过一个游戏,算不上热爱编程. 俄罗斯方块曾经造成的轰动与造成的经济价值可以说是游戏史上的一件大事,它看似简单但却变化无穷,令人上瘾.相信大多数同学,曾经为它痴迷得茶不思饭不想. 游戏规则 1.一个用于摆放小型正方形的平

  • JS+Canvas实现的俄罗斯方块游戏完整实例

    本文实例讲述了JS+Canvas实现的俄罗斯方块游戏.分享给大家供大家参考,具体如下: 试玩(没有考虑兼容低版本浏览器): ********************************************************************** 9月3日更新: 修复了隐藏的比较深的BUG 加上暂停.再来一次功能 速度随分数增高而递减 添加log日志 ****************************************************************

  • Python使用pygame模块编写俄罗斯方块游戏的代码实例

    文章先介绍了关于俄罗斯方块游戏的几个术语. 边框--由10*20个空格组成,方块就落在这里面. 盒子--组成方块的其中小方块,是组成方块的基本单元. 方块--从边框顶掉下的东西,游戏者可以翻转和改变位置.每个方块由4个盒子组成. 形状--不同类型的方块.这里形状的名字被叫做T, S, Z ,J, L, I , O.如下图所示: 模版--用一个列表存放形状被翻转后的所有可能样式.全部存放在变量里,变量名字如S_SHAPE_TEMPLATE or J_SHAPE_TEMPLATE 着陆--当一个方块

  • 一个MIDP俄罗斯方块游戏的设计和实现

    文章来源:csdn 作者:陈万飞 作者简介 陈万飞,男,中南大学数软系学士,曾任北京长城软件高级程序员,系统分析师.有较为丰富的j2se,j2ee开发经验.目前致力于j2me研究工作.可通过chen_cwf@163.net与他联系 摘要 本文给出了一个基于MIDP1.0的俄罗斯方块游戏的设计方案,并给出全部实现源代码.该游戏的最大特色是屏幕自适应,无论各种手机,PDA的屏幕大小如何,该游戏总是能获得最佳的显示效果.游戏在J2me wireless toolkit 2.1的4种模拟器上测试通过.

  • python和pygame实现简单俄罗斯方块游戏

    本文为大家分享了python实现俄罗斯方块游戏的具体代码,供大家参考,具体内容如下 Github:Tetris 代码: # -*- coding:utf-8 -*- import pygame, sys, random, copy from pygame.locals import * pygame.init() CubeWidth = 40 CubeHeight = 40 Column = 10 Row = 20 ScreenWidth = CubeWidth * (Column + 5) S

随机推荐