导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→扫地雷源代码Keil编写

* 50049: 扫地雷源代码Keil编写

   因果 
因果发表的帖子 

 扫地雷源代码Keil编写
扫地雷的源代码分为两部分,一部分是与硬件相关的,如屏的驱动,打印图片,设置前景色,清除屏幕…..;二,扫地雷的实现,主要是计算方法。如读者需要移值,只需要第二部分的程序稍加改动。

#define _GAME_DRV_H_
#include   <DP8051XP.H>  
#include "..\public\TypeDef.h"
#include "..\public\Key.h"
#include   <..\public\uigameapi.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 "..\public\TypeDef.h"
#include "..\public\Key.h"
#include   <..\public\uigameapi.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[i][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][i] == 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][i] = 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][i] = 1;
          MN_TmpSchBlackMine[j][i] = 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;
  }
  }
}
}

我把整个工程及图片资源放于: ;有兴趣的朋友可以去下载


发表时间:2008年6月14日16:49:20

  
回复该帖

本主题共有 1 帖,分页:>>>>>该主题的所有内容[1]条

 *树形目录 只列出部分跟帖的标题以及简单的摘要信息 该主题的部分跟帖如下:

[上一篇帖子]:有谁现在在用ME78单片机的留名,让大家都认识,好讨论我是刚学ME87系列的单片机的,想知有多少人在
[下一篇帖子]:下载线及仿真器热卖中[color=#00BFFF][size=4]现有AT89S51,ALTERA等