步骤1:显示图片
用二维数组来显示8张90×90的配对图片,用来翻转的;首先显示的是背景图片。定义一个二维数组pic[4][4] 来表示每张小图片存放的位置,数组里面存放0~7的数字,当前位置存放是0,就表示该位置要显示image0小图片。这样就可以显示所有小图片了。
步骤2: 实现可以翻转
根据鼠标点击的位置,翻转指定的小图片,而且要自动的翻转回来,主要是鼠标的获取和定位;定义一个二维数组flag[mouse_y/90][mouse_x/90] 来标志有没有翻转,鼠标点击的坐标位置除以90就可以确定点击的是哪张小图片。
步骤3: 游戏逻辑翻转
所谓逻辑翻转就是根据游戏的规则翻转和不翻转图片,就是当鼠标点击次数为偶数时,判断前面的一张图片和当前这张图片是否相同,如果是相同的,这两张图片就不要翻转回背面,否则,就把这两张图片都翻转回背面。主要还是怎样判断两张图片是否相同,解决方法是根据一开始的二维数组pic[4][4]里面存放的数字是否是相同的来判断两张图片是否是相同的。直到所有的小图片都被翻转了游戏就结束。最后利用了SDL的强大功能弄了一个动画的界面来结束游戏。
下面是完整的代码:
#include "SDL/SDL.h" #include "SDL/SDL_image.h" #include <string> #include <stdio.h> #include <time.h> const int SCREEN_WIDTH = 360; //屏幕宽 const int SCREEN_HEIGHT = 360; //屏幕高 const int SCREEN_BPP = 32; //屏幕像素 const int FRAMES_PER_SECOND = 10; const int FOO_WIDTH = 90; //小图片90*90 const int FOO_HEIGHT = 90; SDL_Surface * foo = NULL; SDL_Surface * screen = NULL; SDL_Surface *image0 = NULL; SDL_Surface *image1 = NULL; SDL_Surface *image2 = NULL; SDL_Surface *image3 = NULL; SDL_Surface *image4 = NULL; SDL_Surface *image5 = NULL; SDL_Surface *image6 = NULL; SDL_Surface *image7 = NULL; SDL_Surface *Menu = NULL; SDL_Surface *beginBg = NULL; SDL_Surface * endBg = NULL; SDL_Event event; //定义一个二维数组,用来保存图片索引 int pic[4][4]; bool flag[4][4]; //标记图像是否翻开 bool mousecheck; //记录鼠标点击状态 int pic_x, pic_y; //图片索引 int mouse_x; int mouse_y; //鼠标点击位置 bool quit = false; bool lock; int GameState;//游戏当前状态 const int BEGIN = 0;//开始状态 const int RUN = 1;//运行状态 const int END = 2;//结束状态 SDL_Rect MenuRect[2]; SDL_Rect EndRect[2]; int end_y; class Foo { private: int offSet; int velocity; int frame; public: Foo(); int handle_events(); void show(); }; Foo Show; Foo::Foo() { offSet = 0; velocity = 0; } //读入图片 SDL_Surface *load_image(std::string filename) { SDL_Surface * loadedImage = NULL; SDL_Surface * optimizedImage = NULL; loadedImage = IMG_Load(filename.c_str()); if(loadedImage != NULL) { optimizedImage = SDL_DisplayFormat(loadedImage); SDL_FreeSurface(loadedImage); if(optimizedImage != NULL) { SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, \ SDL_MapRGB(optimizedImage->format, 0, 0xF8, 0xF8)); } } return optimizedImage; } //显示图片 void apply_surface(int x, int y, SDL_Surface *source, \ SDL_Surface * destination, SDL_Rect *clip = NULL) { SDL_Rect offset; offset.x = x; offset.y = y; SDL_BlitSurface(source, clip, destination, &offset); } //初始化图片索引的函数 void initIndex() { srand(time(NULL)); int k=0; //初始化 for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { pic[i][j] = k++; k %= 8; } } //随机 for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { int x = rand()%4; int y = rand()%4; int temp = pic[i][j]; pic[i][j] = pic[x][y]; pic[x][y] = temp; } } //初始化为背面 memset(flag, 0, sizeof(flag)); mousecheck = true; pic_x = -1; lock = false; quit = false; end_y = 30; GameState = BEGIN; MenuRect[0].x = 0; MenuRect[0].y = 0; MenuRect[0].w= 125; MenuRect[0].h = 30; MenuRect[1].x = 0; MenuRect[1].y = 60; MenuRect[1].w= 125; MenuRect[1].h = 30; EndRect[0].x = 0; EndRect[0].y = 150; EndRect[0].w = 360; EndRect[0].h = 30; EndRect[1].x = 0; EndRect[1].y = 180; EndRect[1].w = 360; EndRect[1].h = 30; } bool init() { if(SDL_Init(SDL_INIT_EVERYTHING) == -1) { return false; } screen = SDL_SetVideoMode( SCREEN_WIDTH, \ SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE); if( screen == NULL) { return false; } SDL_WM_SetCaption("Memory Game", NULL); return true; } bool load_files() { beginBg = load_image("pic/begin.bmp"); endBg = load_image("pic/end.bmp"); Menu = load_image("pic/menu.bmp"); foo = load_image("pic/bgimage.bmp"); image0 = load_image("pic/image0.bmp"); image1 = load_image("pic/image1.bmp"); image2 = load_image("pic/image2.bmp"); image3 = load_image("pic/image3.bmp"); image4 = load_image("pic/image4.bmp"); image5 = load_image("pic/image5.bmp"); image6 = load_image("pic/image6.bmp"); image7 = load_image("pic/image7.bmp"); if( NULL == foo || NULL == endBg || NULL == Menu || NULL == beginBg || NULL == image0 \ || NULL == image1 || NULL == image2 || NULL == image3 || NULL == image4 \ || NULL == image5 || NULL == image6 || NULL == image7 ) { return false; } return true; } void clean_up() { SDL_FreeSurface(foo); SDL_FreeSurface(endBg); SDL_FreeSurface(image0); SDL_FreeSurface(image1); SDL_FreeSurface(image2); SDL_FreeSurface(image3); SDL_FreeSurface(image4); SDL_FreeSurface(image5); SDL_FreeSurface(image6); SDL_FreeSurface(image7); SDL_FreeSurface(Menu); SDL_FreeSurface(beginBg); SDL_Quit(); } int Foo::handle_events() { int x =0, y = 0; if(event.type == SDL_MOUSEMOTION) { //获取新鼠标偏移位置 x = event.motion.x; y = event.motion.y; if(y>=250 && y<=280 && x>= 230 && x<355) { //第一项 MenuRect[0].y = 30; } else if(y>=290 && y<=320 && x>= 230 && x<355) { //第二项 MenuRect[1].y = 90; } else { MenuRect[0].y = 0; MenuRect[1].y = 60; } } //鼠标按键按下 if( event.type == SDL_MOUSEBUTTONUP) { //如果鼠标左键已经放开 if( event.button.button == SDL_BUTTON_LEFT) { //获取鼠标的偏移位置 x = event.button.x; y = event.button.y; //如果鼠标在图片上 if(GameState == BEGIN) { if(y>=250 && y<=280 && x>= 230 && x<355) { //第一项 GameState = RUN; } else if(y>=290 && y<=320 && x>= 230 && x<355) { //第二项 quit = true; } } else if(GameState == RUN) { if(lock && !flag[y/90][x/90]) //如果没翻开,那就翻开 { flag[y/90][x/90] = true; mousecheck = !mousecheck; //变换当前状态 mouse_x = x; mouse_y = y; lock = false; } } } } } void logic() { if(GameState == RUN && lock == false) { //判断是否翻开一对 if(mousecheck) //双 { if((pic_x != -1)&&(pic[pic_x][pic_y] != pic[mouse_y/90][mouse_x/90]) ) { //取反? flag[pic_x][pic_y] = false; flag[mouse_y/90][mouse_x/90] = false; } } else//单数,记录位置 { pic_x = mouse_y/90; pic_y = mouse_x/90; } lock = true; //判断是否全部翻开 bool isopen = true; for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { if(flag[i][j] == false) //有没有翻开的 { isopen = false; } } } if(isopen) { GameState = END; } } else if(GameState == END) { end_y += 30; if(end_y > 180) { end_y = 180; //quit = true; } EndRect[0].y = 180-end_y; EndRect[0].h = end_y; EndRect[1].h = end_y; } } void Foo::show() { if(GameState == BEGIN)//如果开始状态,显示开始图片 { apply_surface(0, 0, beginBg, screen); for(int i=0; i<2; i++) { apply_surface(230, 250+i*40, Menu, screen, &MenuRect[i]); } } else if(GameState == RUN) { //遍历图像索引,在相应位置显示图像 for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { if(flag[i][j]) //翻开 { switch(pic[i][j]) { case 0: apply_surface(90*j,90*i, image0, screen); break; case 1: apply_surface(90*j,90*i, image1, screen); break; case 2: apply_surface(90*j,90*i, image2, screen); break; case 3: apply_surface(90*j,90*i, image3, screen); break; case 4: apply_surface(90*j,90*i, image4, screen); break; case 5: apply_surface(90*j,90*i, image5, screen); break; case 6: apply_surface(90*j,90*i, image6, screen); break; case 7: apply_surface(90*j,90*i, image7, screen); break; } } else//没翻开 { apply_surface(90*j,90*i, foo, screen); } } } } else if(GameState == END) { //apply_surface(0, 0, endBg, screen); apply_surface(0, 0, endBg, screen, &EndRect[0]); apply_surface(0, 360-end_y, endBg, screen, &EndRect[1]); } } int main(int argc, char *args[]) { if( init() == false) { printf("init error...\n"); return 1; } if( load_files() == false) { printf("load_files error...\n"); return 1; } initIndex(); //初始化二维数组 while( quit == false ) { logic(); //While there's events to handle while( SDL_PollEvent( &event ) ) { Show.handle_events(); //If the user has Xed out the window if( event.type == SDL_QUIT ) { //Quit the program quit = true; } if(event.type == SDL_KEYDOWN) { switch(event.key.keysym.sym) { case SDLK_ESCAPE: { printf("escape button is pressed\n"); quit = true; break; } } } } Show.show(); //Update the screen if( SDL_Flip( screen ) == -1 ) { return 1; } if(GameState == RUN) SDL_Delay(500); if(GameState == END) SDL_Delay(150); } //Clean up clean_up(); return 0; }
运行效果图片,请读者自行运行。