CSDN博客

img jimmy_w

写的几个小玩意

发表于2008/9/28 20:02:00  548人阅读

 侃侃自己的几个课程设计

 

  大三下的那个学期,咱又做了次课程设计,题目范围是写几个游戏。

  俄罗斯方块,这个大家都玩过的,咱做这个东西花了3天,算矩阵算的头脑发昏了。。。

 

界面是这样的:


 

附加功能只有计分,没办法,人懒;

关键技术是c++win32 api,包括界面都是咱用gdi一笔一划的画出来的,这个程序是界面和游戏逻辑完全分离的,后台的算法是这样的,设置一个二维数组,然后方块也用二维数组表示,如:

1 1 1 1

1 0 0 0

0 0 0 0

0 0 0 0

这个知道是啥方块吗?

然后就是纯粹的矩阵的翻转,搬运,界面用一个timer,定时的刷新矩阵数据转换成不同颜色的方块,这样就能做出方块下落的效果,而且响应键盘方向键的消息后,后台矩阵搬运一下,界面重绘一下,就出来效果了。

给出后台游戏逻辑类的接口吧

 

 

  1. /*************************************************
  2.   Filename: Game.h
  3.   Author: Haoran Wang     
  4.   Date: 2008-06-14
  5.   Description: 游戏逻辑类CTetris的定义文件
  6.   Function(or class)List:
  7.         1.class CTetris 
  8.   History:
  9. *************************************************/
  10.  
  11. #ifndef __GAME_H__
  12. #define __GAME_H__
  13.  
  14. #include <cstdlib>
  15. #include <cstdio>
  16. #include <ctime>
  17. #include <windows.h>
  18. #include <iostream>
  19.  
  20. #define BGD_LINE    20
  21. #define BGD_ROW     10
  22.  
  23. #define FIG_SIZE        4
  24.  
  25. #define FIG_TRIADA      1
  26. #define FIG_LCORNER     FIG_TRIADA + 1               
  27. #define FIG_RCORNER     FIG_TRIADA + 2
  28. #define FIG_LZIGZAG     FIG_TRIADA + 3
  29. #define FIG_RZIGZAG     FIG_TRIADA + 4
  30. #define FIG_STICK       FIG_TRIADA + 5
  31. #define FIG_BOX         FIG_TRIADA + 6
  32.  
  33. #define GAME_FAIL       100
  34. #define GAME_WIN        GAME_FAIL + 1
  35. #define RET_OK          GAME_FAIL + 2
  36.  
  37. #define GAME_BEGIN_X    4
  38. #define GAME_BEGIN_Y    0
  39.  
  40. #define FIG_STOPPED     8
  41.  
  42. #define DIRECTION_DOWN      200
  43. #define DIRECTION_LEFT      DIRECTION_DOWN + 1
  44. #define DIRECTION_RIGHT     DIRECTION_DOWN + 2
  45.  
  46. //type
  47. typedef BYTE(*FIG_TYPE)[4];
  48.  
  49. typedef struct FigPosType
  50. {
  51.     UINT x;
  52.     UINT y;
  53. }FIGPOS;
  54.  
  55. //描述游戏逻辑的类
  56. class CTetris
  57. {
  58. public:
  59.     CTetris();
  60.     ~CTetris();
  61. public:
  62.     void Start();
  63.     UINT CreateFig();
  64.     bool MoveDown();
  65.     bool MoveLeft();
  66.     bool MoveRight();
  67.     bool TurnFig();         //旋转
  68.     UINT ClearFillLine();   //扫描并清除满行
  69.     BYTE** GetBackground();
  70.     UINT GetNextFig();      //获取下一轮方块
  71. private:
  72.     FIG_TYPE    *m_pstFigSet;       //保存所有方块种类描述的入口
  73.     BYTE        **m_pbyBackground;  //游戏屏幕背景
  74.     UINT        m_uiCurFig;         //当前方块种类
  75.     UINT        m_uiNextFig;        //下一个方块种类
  76.     FIGPOS      m_stCurPos;         //当前方块的位置,左上角坐标
  77.     UINT        m_uiCurFigLength;   //当前方块的长度
  78.     UINT        m_uiCurFigWidth;    //当前方块的宽度
  79.     BYTE        **m_pbyCurFig;      //当前方块描述,考虑到方块旋转
  80.     UINT        m_uiScore;          //分数
  81. private:
  82.     UINT RandomFig();
  83.     void SetBgdFig(UINT uiType,UINT uiX,UINT uiY);
  84.     void MatrixCopy(FIGPOS stDesPos,BYTE abySrc[4][4]);
  85.     bool IsHit(FIGPOS stPos,UINT uiDirection);
  86.     void GetCurFigLW();
  87. };
  88.  
  89. #endif


  界面有个地方要注意的就是重绘时的闪烁问题,可以利用内存位图缓冲一下:
  1. memDC = CreateCompatibleDC(hdc);//创建一个内存设备的DC
  2. memBM = CreateCompatibleBitmap(hdc,BGD_WIDTH + 100,BGD_LENGTH + 30);
  3. //创建内存位图
  4. SelectObject(memDC,memBM);
  5. ...
  6. //调用BitBlt输出到设备就行了

  除了俄罗斯,咱还做了个万年历的,公历转农历算法是网上down的,还有其他的算法,比如求今天是星期几的,求闰年之类的,相信大家都很熟了,界面是用gdi模拟日历的格式,算法是这样的:
  1. VOID CCalendar::GetGUICalendar(UINT auiDate[][7])
  2. {
  3.     int asiMonth[13]    = {0,31,0,31,30,31,30,31,31,30,31,30,31};
  4.     asiMonth[2]         = (IsLeapYear(m_sysTime.wYear) ? 29 : 28);
  5.     //暂存当前日期的day
  6.     int siTmpDay        = m_sysTime.wDay;
  7.     SetDate(m_sysTime.wYear,m_sysTime.wMonth,1);
  8.     int siWeekBeg       = QueryWeek();
  9.     int siDay           = 1;
  10.     
  11.     for (int siCnt1 = 0;siCnt1 != 5 && siDay <= asiMonth[m_sysTime.wMonth];++siCnt1)
  12.     {
  13.         for (int siCnt2 = 0;siCnt2 != 7 && siDay <= asiMonth[m_sysTime.wMonth];++siCnt2)
  14.         {
  15.             if (siCnt1 == 0)
  16.             {
  17.                 siCnt2 = siWeekBeg;
  18.                 ++siWeekBeg;
  19.             }
  20.             auiDate[siCnt1][siCnt2] = siDay;
  21.             ++siDay;
  22.         }
  23.     }
  24.     //还原时间
  25.     SetDate(m_sysTime.wYear,m_sysTime.wMonth,siTmpDay);
  26. }
  看出来了吗?给一个二维数组,模拟月历牌上的各个位置,然后算出本月第一天是星期几,之后就从第一行的第几列开始挨个赋值(1、2、3...),之后直接打印出这个数组就行了。

  另外还有个程序是网络五子棋对战,别怪我,AI太难了。。。因为程序做的太丑,就不拿出来了,原理就是udp,发来发去,很没技术含量。。。


0 0

相关博文

我的热门文章

img
取 消
img