打印
[国产单片机]

扫地雷源代码Keil编写

[复制链接]
2410|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
因果|  楼主 | 2008-6-14 16:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
扫地雷的源代码分为两部分,一部分是与硬件相关的,如屏的驱动,打印图片,设置前景色,清除屏幕…..;二,扫地雷的实现,主要是计算方法。如读者需要移值,只需要第二部分的程序稍加改动。

#define _GAME_DRV_H_
#include <DP8051XP.H>
#include "..publicTypeDef.h"
#include "..publicKey.h"
#include <..publicuigameapi.h>
///为了调试,其调用了字库,屏的底层驱动
void gShowHexAscii(XWORD xwX,XWORD xwY,PXBYTE pxData,XWORD xLen) large
{

          *(PXWORD)(GAME_SWAP_RAM_ADDR +0)  = xwX;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +2)  = xwY;
          *(PXDWORD)(GAME_SWAP_RAM_ADDR+4) = (XDWORD)pxData;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +8)  = (XDWORD)xLen;
          
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 0;
          Run_Game_Api();
      
}
//打印图片子程序,bx,by为屏的坐标输入,wId为资源ID号
void gResShowPic(XWORD bx,XWORD by,XWORD wId) large
{

          *(PXWORD)(GAME_SWAP_RAM_ADDR +0)  = bx;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +2)  = by;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +4)  = wId;

          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 1;
          Run_Game_Api();

}
//设置前景色
void gSetPenColor(XWORD xwPenColor)      large
{
          *(PXWORD)(GAME_SWAP_RAM_ADDR +0)  = xwPenColor;   
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 2;
          Run_Game_Api();
}
//设置背景色
void gSetBackgdColor(XWORD xwGgColor)     large
{
          *(PXWORD)(GAME_SWAP_RAM_ADDR +0)  = xwGgColor;
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 3;
          Run_Game_Api();
}
//清屏
void gClearScreen(XWORD wColStart, XWORD wRowStart, XWORD wWidth, XWORD wHeight) large
{
          *(PXWORD)(GAME_SWAP_RAM_ADDR +0)  = wColStart;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +2)  = wRowStart;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +4)  = wWidth;
          *(PXWORD)(GAME_SWAP_RAM_ADDR +6)  = wHeight;
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 4;
          Run_Game_Api();

}
//延时,等待
void gap_sleep(XWORD xwDelayTime) large
{

          *(PXWORD)(GAME_SWAP_RAM_ADDR +0)  = xwDelayTime;
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 5;
          Run_Game_Api();

}
//获取系统消息,如时间,按键消息
XBYTE gap_get_message() large
{
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 6;
          Run_Game_Api();
          return *(PXBYTE)(GAME_SWAP_RAM_ADDR +0);
}

//设置时钟频率
void gSetGameSpeed(XBYTE xbType) large
{

          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 7;
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +0) = xbType;
          Run_Game_Api();

}
//获得一个随机数
XBYTE gGetRandVar(void) large
{

          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 8;
          Run_Game_Api();
          return *(PXWORD)(GAME_SWAP_RAM_ADDR +0);

}

XDWORD gGetGameRomFileMaxSector(void) large
{

          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 9;
          Run_Game_Api();
          return *(PXDWORD)(GAME_SWAP_RAM_ADDR +0);

}

void gfsReadOnePage(XDWORD PagePos,PXBYTE pxbTarget) large
{
          
          *(PXBYTE)(GAME_SWAP_RAM_ADDR +12) = 10;
          *(PXDWORD)(GAME_SWAP_RAM_ADDR +0)  = PagePos;
          *(PXDWORD)(GAME_SWAP_RAM_ADDR+4) = (XDWORD)pxbTarget;
          Run_Game_Api();
}


下面的程序为计算方法,我所用到的硬件是三代苹果(五个按键实现);对于下面的变量我全面申明为large,xdata的主要原因是我的系统造成的。我把游戏写为两个工程;一个工程我们可以理解为主程序,主要的功能是与硬件打交道的,如按键,定时器,关机,电池检测,屏的驱动;另一个工程为游戏的具体实现,与硬件与关的。两个工程的代码区域不一样的,xdata的区域也不一样。但是由于keil的编译系统,在工程1里面已经把data,idata占用了,如果工程2里面的变量用到data,idata的话,两个工程的变量会重叠,当定时中断时,未知的因素会发生。我这样设计的的好处是,外部的游戏可以做为文件拷入内存,而工程1无须改动。

#include <DP8051XP.H>
#include "..publicTypeDef.h"
#include "..publicKey.h"
#include <..publicuigameapi.h>
#include <SokuTek.h>

void Timer0(void) interrupt 1 using 2
{

}

#define  MINE_MAX_X           17
#define  MINE_MAX_Y           11
#define  MINE_FLAG            9

#define  MINE_START_X         3
#define  MINE_START_Y         26
#define  MINE_BMP_WIDTH       9
#define  MINE_BMP_HEIGHT      9

#define  MN_LAUGH_FACE_X      72
#define  MN_LAUGH_FACE_Y      4

#define  MN_MINE_NUM          MINE_MAX_X + MINE_MAX_Y


#define INT16U      XWORD
#define ResShowPic   gResShowPic



INT16U   MN_Mine[MINE_MAX_X*MINE_MAX_Y];
INT16U   MN_Turn[MINE_MAX_X*MINE_MAX_Y];
INT16U   MN_Mark[MINE_MAX_X*MINE_MAX_Y];
INT16U   MN_TmpSchBlackMine[MINE_MAX_Y][MINE_MAX_X];
 
INT16U  MN_MarkNum;

INT16U  MN_RandSeed;
INT16U  MN_RandOffset;
INT16U  MN_RandMaxValue;
INT16U  MN_curx;
INT16U  MN_cury;

INT16U MN_Random() large;
void MN_IniMineMap() large;
void MN_TurnBack(INT16U xx, INT16U yy) large;
INT16U MN_Edge_Stack(INT16U xx, INT16U yy) large;
void MN_Edge(INT16U xx, INT16U yy) large;
void MN_FailGame() large;
INT16U MN_LButton(INT16U xx, INT16U yy) large;
INT16U MN_RButton(INT16U xx,INT16U yy) large;
INT16U MN_ChkSuccess() large;
void RestoreCurMine() large;
void ShowMinesMap() large;
void ShowIniGameBckMap() large;
void  iniMineGame() large;
void MarkCurMine() large;
void MN_New_Edge(INT16U xx, INT16U yy) large;
extern rand();

INT16U MN_Random()     large
{
INT16U x,y;
     MN_RandSeed = MN_RandSeed*109 + 57;
     x = MN_RandSeed + MN_RandOffset;
     y = x & MN_RandMaxValue;
     return y;
}

void MN_IniMineMap() large
{
       INT16U x, y,i;
      for(y = 0;y<MINE_MAX_Y;y++)
        for(x = 0;x <MINE_MAX_X;x++)
        {
            MN_Mine[y * MINE_MAX_X + x] = 0;
            MN_Turn[y * MINE_MAX_X + x] = 0;
            MN_Mark[y * MINE_MAX_X + x] = 0;
      }

    for(i = 0;i<MN_MINE_NUM;i++) 
    {
        x = MN_Random();
      while (MN_Mine[x] || (x >=MINE_MAX_X*MINE_MAX_Y - 1)) 
        {
        x = MN_Random();
        }
        MN_Mine[x] = MINE_FLAG;
    }

    for (y=0;y<MINE_MAX_Y;y++)
            for (x=0;x<MINE_MAX_X;x++)
            {
                i=0;
                if (MN_Mine[y*MINE_MAX_X +x]!=MINE_FLAG)
                {
                if ((MN_Mine[y*MINE_MAX_X +x-1]==MINE_FLAG)&&(x>=1)) i++;
                if ((MN_Mine[y*MINE_MAX_X +x+1]==MINE_FLAG)&&((x+1)<MINE_MAX_X)) i++;
                if ((MN_Mine[(y-1)*MINE_MAX_X +x]==MINE_FLAG)&&(y>=1)) i++;
                if ((MN_Mine[(y+1)*MINE_MAX_X +x]==MINE_FLAG)&&((y+1)<MINE_MAX_Y)) i++;
                if ((MN_Mine[(y-1)*MINE_MAX_X +x-1]==MINE_FLAG)&&(x>=1)&&(y>=1)) i++;
                if ((MN_Mine[(y-1)*MINE_MAX_X +x+1]==MINE_FLAG)&&((x+1)<MINE_MAX_X)&&(y>=1)) i++;
                if ((MN_Mine[(y+1)*MINE_MAX_X +x+1]==MINE_FLAG)&&((x+1)<MINE_MAX_X)&&((y+1)<MINE_MAX_Y)) i++;
                if ((MN_Mine[(y+1)*MINE_MAX_X +x-1]==MINE_FLAG)&&(x>=1)&&((y+1)<MINE_MAX_Y)) i++;
                MN_Mine[y*MINE_MAX_X +x]=i;
             }
            }
}
void MN_TurnBack(INT16U xx, INT16U yy)     large

    if(!MN_Turn[yy*MINE_MAX_X+xx]) 
         MN_Turn[yy*MINE_MAX_X+xx] = 2 + MN_Mine[yy*MINE_MAX_X+xx];
    }


INT16U MN_Edge_Stack(INT16U xx, INT16U yy)    large
{
INT16U ZZ;

     if ( (xx&0x8000) || (xx>MINE_MAX_X -1)) return 0;
    if ( (yy&0x8000) || (yy>MINE_MAX_Y -1)) return 0;

    ZZ=MN_Turn[yy*MINE_MAX_X+xx];
    if (ZZ)  return 0 ;

      MN_TurnBack(xx,yy);
     if (MN_Mine[yy*MINE_MAX_X+xx] == 0) return 1;
     return 0;
}

void MN_Edge(INT16U xx, INT16U yy)     large
{

        MN_New_Edge(xx,yy);

}
///以前的程序是递归调用,我进行了修改,原因是如果递归的深度过于深的话,堆栈会溢出。我重新改写了程序
void MN_New_Edge(INT16U xx, INT16U yy)      large
{
INT16U i,j,tmpcnt;
      for(i = 0;i<MINE_MAX_Y;i++)
            for(j = 0;j<MINE_MAX_X;j++)
             MN_TmpSchBlackMine[j] = 0;

      MN_TmpSchBlackMine[yy][xx]= 1;
 
      while(1)
      {
      tmpcnt = 0;
      for(j = 0;j<MINE_MAX_Y;j++)
            for(i = 0;i<MINE_MAX_X;i++)
                if (MN_TmpSchBlackMine[j] == 1)
                {
                MN_Edge_Stack(i,j);
                if (MN_Edge_Stack(i-1,j)) MN_TmpSchBlackMine[j][i-1] = 1;
                if (MN_Edge_Stack(i,j-1)) MN_TmpSchBlackMine[j-1] = 1;
                if (MN_Edge_Stack(i+1,j)) MN_TmpSchBlackMine[j][i+1] = 1;
                if (MN_Edge_Stack(i,j+1)) MN_TmpSchBlackMine[j+1] = 1;
                MN_TmpSchBlackMine[j] = 0;   
                tmpcnt = 1;
                }
       if (tmpcnt==0) break;
      }
}
void MN_FailGame()      large
{
INT16U x; 
     for(x = 0;x<MINE_MAX_X*MINE_MAX_Y;x++)
           if( MN_Mine[x]==MINE_FLAG) MN_Turn[x]= 2 + MINE_FLAG;
}

INT16U MN_LButton(INT16U xx, INT16U yy)     large
{
 if ( (xx<MINE_MAX_X) && (yy<MINE_MAX_Y))  
  {
  if ( (MN_Mine[yy*MINE_MAX_X + xx] == MINE_FLAG) &&(MN_Turn[yy*MINE_MAX_X + xx]==0) ) 
          { 
              MN_FailGame(); 
              MN_Turn[yy*MINE_MAX_X + xx]= 2 + MINE_FLAG + 2;
              return 0;
          }
  if (MN_Mine[yy*MINE_MAX_X + xx] == 0)
       {
       MN_Edge(xx,yy);
      }
  else
       MN_TurnBack(xx,yy);
  return 1;
  }
  return 2;
}

INT16U MN_RButton(INT16U xx,INT16U yy)    large
{
INT16U x;
 if((MN_Turn[yy*MINE_MAX_X+xx]<2))
     {
     x = 0;
     if(MN_Turn[yy*MINE_MAX_X+xx]==0) {MN_Turn[yy*MINE_MAX_X+xx] = 1; x = MINE_FLAG; }    
     else if(MN_Turn[yy*MINE_MAX_X+xx]==1) MN_Turn[yy*MINE_MAX_X+xx] = 0;
     
     MN_Mark[yy*MINE_MAX_X+xx] = x;
     MN_MarkNum=0;

     for(x = 0;x<MINE_MAX_X*MINE_MAX_Y;x++)
           if (MN_Mark[x]==MINE_FLAG) MN_MarkNum++;
     return 1;
     }
  return 2;
}

INT16U MN_ChkSuccess()    large
{
INT16U x,y;
    y = 0;
       for(x = 0;x<MINE_MAX_X*MINE_MAX_Y;x++)
          if(MN_Turn[x]<2) y++;
       if (y == MN_MINE_NUM) 
       {
       for(x = 0;x<MINE_MAX_X*MINE_MAX_Y;x++)
          if(MN_Turn[x]==0) MN_Turn[x]=1;
       return 1;
    }
    return 0;
}

void RestoreCurMine()  large
{

        ResShowPic(MINE_START_X+MINE_BMP_WIDTH*MN_curx,
                   MINE_START_Y+ MINE_BMP_HEIGHT* MN_cury,
                   MN_Turn[MINE_MAX_X*MN_cury+MN_curx]+p_RGMINE00);
}

void MarkCurMine() large
{
        ResShowPic(MINE_START_X+MINE_BMP_WIDTH*MN_curx,
                   MINE_START_Y+ MINE_BMP_HEIGHT* MN_cury,
                   MN_Turn[MINE_MAX_X*MN_cury+MN_curx]+p_RGMINE20);

}

void ShowMinesMap() large
{
XWORD i,j;
     for(i=0;i<MINE_MAX_Y;i++)
       for(j = 0;j<MINE_MAX_X;j++)
       {
       
        ResShowPic(MINE_START_X+MINE_BMP_WIDTH*j,
                   MINE_START_Y+ MINE_BMP_HEIGHT* i,
                   MN_Turn[MINE_MAX_X*i+j]+p_RGMINE00);
       }
}

void ShowIniGameBckMap() large
{

         ResShowPic(0,0,p_RGMINEBLKGRND);
         ResShowPic(MN_LAUGH_FACE_X,MN_LAUGH_FACE_Y,p_RGMINE14);
         ShowMinesMap();
         MarkCurMine();       
}


void  iniMineGame()    large
{
        EA = 0;
        MN_curx = 0;
        MN_cury = 0;

        MN_RandSeed = gGetRandVar();
        MN_RandOffset = gGetRandVar();
        MN_RandMaxValue = 255;

        MN_IniMineMap();
        ShowIniGameBckMap();
        EA = 1;

}


void main()         large
{

XBYTE xbKey;
XBYTE SkipKeyRunFlag;

       iniMineGame();
       SkipKeyRunFlag = 0;
      
      while(1)
      {  
       xbKey = gap_get_message();
       if (xbKey!=AP_KEY_NULL)
       {
       
       switch(xbKey)
        {
         case AP_KEY_VOLUP | AP_KEY_UP:
              if(SkipKeyRunFlag==1)
              {
              SkipKeyRunFlag = 0;
              break;
              }
              RestoreCurMine();      
              MN_cury++;
              if (MN_cury == MINE_MAX_Y) MN_cury=0;
              MarkCurMine(); 
              break;

         case AP_KEY_POWER | AP_KEY_UP:
            if(MN_LButton(MN_curx,MN_cury)==0)
               {                                   // failure
               ShowMinesMap();
               ResShowPic(MN_LAUGH_FACE_X,MN_LAUGH_FACE_Y,p_RGMINE15);
               iniMineGame();
               }
               else if(MN_ChkSuccess())
               {                                 //success  
               ShowMinesMap();
               ResShowPic(MN_LAUGH_FACE_X,MN_LAUGH_FACE_Y,p_RGMINE16);
               iniMineGame();
               }
        
              else
              {
              ShowMinesMap();
              MarkCurMine(); 
              }
              break;

         case AP_KEY_VOLUP |AP_KEY_LONG:
              SkipKeyRunFlag = 1;
              MN_RButton(MN_curx,MN_cury);
              if(MN_ChkSuccess()) 
                                 {
              ShowMinesMap();
              ResShowPic(MN_LAUGH_FACE_X,MN_LAUGH_FACE_Y,p_RGMINE16);
                      iniMineGame();
                                 }                  //sucess
              else
               {
               
              ShowMinesMap();
              MarkCurMine(); 
               }
              break;

         case AP_KEY_RIGHT:
         case AP_KEY_RIGHT | AP_KEY_HOLD:
              RestoreCurMine();      
              MN_curx++;
              if (MN_curx == MINE_MAX_X) MN_curx=0;
              MarkCurMine();
              break;

         case AP_KEY_LEFT:
         case AP_KEY_LEFT | AP_KEY_HOLD:
              RestoreCurMine();         
              if (MN_curx==0) MN_curx= MINE_MAX_X;
              MN_curx --;
              MarkCurMine(); 
              break;

         case AP_KEY_FUNC |AP_KEY_UP:
              RestoreCurMine();         
              if (MN_cury==0) MN_cury= MINE_MAX_Y;
              MN_cury --;
              MarkCurMine(); 
              break;

         default:
              break;
        }
        }
}
}

我把整个工程及图片资源放于: http://www.sokutek.com/document.asp;有兴趣的朋友可以去下载

相关帖子

沙发
McuPlayer| | 2008-6-14 22:16 | 只看该作者

楼主的游戏不错啊

你们公司的网站做得太简洁了啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

9

帖子

1

粉丝