Welcome 微信登录

首页 / 移动开发 / Android / Android下SDL2实现五子棋游戏

本文实例介绍了Android下用SDL2实现一个简单的五子棋游戏,分享给大家供大家参考,具体内容如下
1. Five.c

// Five.c // SDL2 五子棋// gcc -mwindows -o Five Five.c FiveData.c FiveData.h -lSDL2 -lSDL2main -lSDL2_image -lSDL2_ttf //#define _DEBUG_ #include <stdio.h>#include <string.h>#include <SDL2/SDL.h>#include <SDL2/SDL_image.h>#include <SDL2/SDL_ttf.h>#include "FiveData.c" // 资源文件char szBackGroundFile[] = "Resource/BackGround.jpg";// 棋盘背景图文件char szBlackFile[] = "Resource/BlackPiece.jpg";// 黑棋子图文件(背景色:白色)char szWhiteFile[] = "Resource/WhitePiece.jpg";// 白棋子图文件(背景色:白色)char szFontFile[]= "Resource/DroidSansFallback.ttf"; // 字体文件// 字符串常量char szTitle[]= "五子棋";char szBlack[]= "黑方";char szWhite[]= "白方";char szGameTips[] = "第 %d 手,轮到 %s 落子";char szGameOver[] = "%s 取得本局胜利,请按键继续"; _Bool OnKeyUp(int x, int y, int nSpacing);void DrawBoard(SDL_Renderer *pRenderer, int nSpacing, SDL_Color *pColor);void DrawPieces(SDL_Renderer *pRenderer, int nSpacing, SDL_Texture *pBlackTexture, SDL_Texture *pWhiteTexture);void PrintString(SDL_Renderer *pRenderer, int nSpacing, char *szString, TTF_Font *pFont, SDL_Color *pColor);void FillCircle(SDL_Renderer *pRenderer, int x, int y, int r, SDL_Color *pColor);SDL_Texture *GetImageTexture(SDL_Renderer *pRenderer, char *szFile, _Bool bTransparent, SDL_Color *pBackGroundColor);SDL_Texture *GetStringTexture(SDL_Renderer *pRenderer, TTF_Font *pFont, char *szString, SDL_Color *pColor); #undef mainint main(int argc, char **argv){int nWindowWidth, nWindowHeight;// 屏幕尺寸int nSpacing;// 棋盘线距SDL_Window*pWindow= NULL; // 主窗口SDL_Renderer *pRenderer = NULL; // 主窗口渲染器SDL_Texture *pBackTexture = NULL; // 棋盘背景图纹理SDL_Texture *pBlackTexture = NULL; // 黑棋子图纹理SDL_Texture *pWhiteTexture = NULL; // 白棋子图纹理TTF_Font *pFont = NULL; // 提示文字字体SDL_Eventevent; // 事件_Bool bRun = 1; // 持续等待事件控制循环标识char szString[256]; // 初始化if(SDL_Init(SDL_INIT_EVERYTHING)==-1 || IMG_Init(IMG_INIT_JPG)==-1 || TTF_Init()==-1){#ifdef _DEBUG_fprintf(stderr, "%s", SDL_GetError());#endifreturn 1;}// 创建主窗口及其渲染器if(SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN, &pWindow, &pRenderer)==-1){#ifdef _DEBUG_fprintf(stderr, "%s", SDL_GetError());#endifgoto label_error;}SDL_SetWindowTitle(pWindow, szTitle);SDL_GetWindowSize(pWindow, &nWindowWidth, &nWindowHeight);nSpacing = SDL_min(nWindowWidth, nWindowHeight)/(MAX_LINES+2); // 加载图片文件if(NULL==(pBackTexture = GetImageTexture(pRenderer, szBackGroundFile, 0, NULL))|| NULL==(pBlackTexture = GetImageTexture(pRenderer, szBlackFile, 1, NULL))|| NULL==(pWhiteTexture = GetImageTexture(pRenderer, szWhiteFile, 1, NULL))){#ifdef _DEBUG_fprintf(stderr, "%s", SDL_GetError());#endifgoto label_error;}// 加载字体文件if(NULL == (pFont = TTF_OpenFont(szFontFile, 20))) // 这个 20 是字体大小{#ifdef _DEBUG_fprintf(stderr, "%s", SDL_GetError());#endifgoto label_error;} // 重置棋局数据,等待事件Five_ResetData();while(bRun && SDL_WaitEvent(&event)){switch(event.type){case SDL_FINGERUP :// 触摸弹起if(g_iWho != NONE){if(OnKeyUp(event.tfinger.x*nWindowWidth, event.tfinger.y*nWindowHeight, nSpacing) && Five_isFive())g_iWho = NONE;}elseFive_ResetData();// 这里没有 break; 往下坠落重绘窗口 case SDL_WINDOWEVENT : // 有窗口消息需重绘窗口SDL_RenderClear(pRenderer);SDL_RenderCopyEx(pRenderer, pBackTexture, NULL, NULL, 0, NULL, SDL_FLIP_NONE);DrawBoard(pRenderer, nSpacing, NULL);DrawPieces(pRenderer, nSpacing, pBlackTexture, pWhiteTexture);if(g_iWho == NONE)sprintf(szString, szGameOver, g_nHands%2==1 ? szBlack : szWhite);elsesprintf(szString, szGameTips, g_nHands+1, g_iWho==BLACK ? szBlack : szWhite);PrintString(pRenderer, nSpacing, szString, pFont, NULL);SDL_RenderPresent(pRenderer);break; case SDL_QUIT :bRun = 0;break; default :break;}} label_error:// 清理if(pBackTexture != NULL) SDL_DestroyTexture(pBackTexture);if(pBlackTexture != NULL) SDL_DestroyTexture(pBlackTexture);if(pWhiteTexture != NULL) SDL_DestroyTexture(pWhiteTexture);if(pFont != NULL) TTF_CloseFont(pFont);TTF_Quit();IMG_Quit();SDL_Quit();return 0;} // 响应落子按键// 参数:(x,y) = 被点击的窗口坐标,nSpacing = 棋盘线距_Bool OnKeyUp(int x, int y, int nSpacing){// 计算落点棋盘坐标int m = (x - 0.5*nSpacing)/nSpacing;int n = (y - 0.5*nSpacing)/nSpacing;// 处理有效落点if(m>=0 && m<MAX_LINES && n>=0 && n<MAX_LINES && g_iBoard[m][n]==NONE){Five_AddPiece(m, n, g_iWho);return 1;}return 0;} // 画棋盘// 参数:pRenderer = 渲染器,nSpacing = 棋盘线距,pColor = 颜色(默认黑色)void DrawBoard(SDL_Renderer *pRenderer, int nSpacing, SDL_Color *pColor){SDL_Color c;int r, x, y, z; if(pColor == NULL)c.r = c.g = c.b = 0;elsec = *pColor; // 棋盘线SDL_SetRenderDrawColor(pRenderer, c.r, c.g, c.b, SDL_ALPHA_OPAQUE);for(int i = 1; i <= MAX_LINES; i++){SDL_RenderDrawLine(pRenderer, nSpacing, i*nSpacing, MAX_LINES*nSpacing, i*nSpacing);SDL_RenderDrawLine(pRenderer, i*nSpacing, nSpacing, i*nSpacing, MAX_LINES*nSpacing);} // 星位r = nSpacing*0.2;// 星半径x = nSpacing*4; // 第四线y = nSpacing*(MAX_LINES+1)/2;// 中线z = nSpacing*(MAX_LINES-3); // 倒数第四线FillCircle(pRenderer, x, x, r, &c);FillCircle(pRenderer, y, x, r, &c);FillCircle(pRenderer, z, x, r, &c);FillCircle(pRenderer, x, y, r, &c);FillCircle(pRenderer, y, y, r, &c);FillCircle(pRenderer, z, y, r, &c);FillCircle(pRenderer, x, z, r, &c);FillCircle(pRenderer, y, z, r, &c);FillCircle(pRenderer, z, z, r, &c);} // 画棋子// 参数:pRenderer = 渲染器,nSpacing = 棋盘线距,pBlackTexture = 黑子纹理,pWhiteTexture = 白子纹理void DrawPieces(SDL_Renderer *pRenderer, int nSpacing, SDL_Texture *pBlackTexture, SDL_Texture *pWhiteTexture){int r = 0.4*nSpacing; // 棋子半径SDL_Rect rt = {0, 0, 2*r, 2*r}; if(g_nHands <= 0)return; for(int i=0; i<MAX_LINES; i++){for(int j=0; j<MAX_LINES; j++){rt.x = (i+1)*nSpacing - r;rt.y = (j+1)*nSpacing - r;if(g_iBoard[i][j] == BLACK)SDL_RenderCopyEx(pRenderer, pBlackTexture, NULL, &rt, 0, NULL, SDL_FLIP_NONE);else if(g_iBoard[i][j] == WHITE)SDL_RenderCopyEx(pRenderer, pWhiteTexture, NULL, &rt, 0, NULL, SDL_FLIP_NONE);}}} // 提示文字// 参数:szString = 文字内容,pFont = 字体,pColor = 文字颜色(默认黑色)void PrintString(SDL_Renderer *pRenderer, int nSpacing, char *szString, TTF_Font *pFont, SDL_Color *pColor){SDL_Texture *pTextTexture;SDL_Rect rt; rt.x = nSpacing;rt.y = nSpacing*(MAX_LINES+1);rt.w = nSpacing*strlen(szString)/4; // 这个 4 和字体大小有关rt.h = nSpacing; if((pTextTexture = GetStringTexture(pRenderer, pFont, szString, pColor)) != NULL){SDL_RenderCopyEx(pRenderer, pTextTexture, NULL, &rt, 0, NULL, SDL_FLIP_NONE);SDL_DestroyTexture(pTextTexture);}} // 取得图片文件纹理// 参数:szFile = 图片文件名,bTransparent = 是否透明处理,pBackGroundColor = 背景色(默认白色)// 返回值:纹理指针SDL_Texture *GetImageTexture(SDL_Renderer *pRenderer, char *szFile, _Bool bTransparent, SDL_Color *pBackGroundColor){SDL_Texture *pTexture;SDL_Surface *pSurface;int r, g, b; if((pSurface = IMG_Load(szFile)) == NULL)return NULL;if(bTransparent){if(pBackGroundColor == NULL){r = g = b = 255;}else{r = pBackGroundColor->r;g = pBackGroundColor->g;b = pBackGroundColor->b;}SDL_SetColorKey(pSurface, 1, SDL_MapRGB(pSurface->format, r, g, b));}pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface); SDL_FreeSurface(pSurface);return pTexture;} // 取得字符串纹理// 参数:szString = 字符串内容,pFont = 字体,pColor = 文字颜色(默认黑色)// 返回值:纹理指针SDL_Texture *GetStringTexture(SDL_Renderer *pRenderer, TTF_Font *pFont, char *szString, SDL_Color *pColor){SDL_Texture *pTexture;SDL_Surface *pSurface;SDL_Color c; if(pColor == NULL)c.r = c.g = c.b = 0;elsec = *pColor; if((pSurface = TTF_RenderUTF8_Blended(pFont, szString, c)) == NULL)return NULL;pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface); SDL_FreeSurface(pSurface);return pTexture;} // 画圆(SDL2 没有画圆的函数,先用矩形框代替吧)// 参数:pRenderer = 渲染器,(x,y) = 圆心坐标,r = 半径, pCOlor = 填充色void FillCircle(SDL_Renderer *pRenderer, int x, int y, int r, SDL_Color *pColor){SDL_Rect rt = {x-r, y-r, 2*r, 2*r}; SDL_SetRenderDrawColor(pRenderer, pColor->r, pColor->g, pColor->b, SDL_ALPHA_OPAQUE);SDL_RenderFillRect(pRenderer, &rt);}
2.FiveData.c    

// FiveData.c // 五子棋:数据处理模块 #include "FiveData.h"// 公共变量int g_nHands;// 总手数int g_nLastCrossing;// 100*x+y,(x,y)为最后一手的坐标enum en_COLOR g_iWho;// 轮到哪方落子:0 不可落子状态,1 黑方,2 白方int g_iBoard[MAX_LINES][MAX_LINES];// 棋盘交叉点数据:0 无子,1 黑子,2 白子// 判断最后一手棋是否形成五子连珠// 返回值:1 = 形成五子连珠, 0 = 未形成五子连珠_Bool Five_isFive(void){int i, j, nCount, x, y; if(g_nLastCrossing < 0)return 0;x = g_nLastCrossing/100;y = g_nLastCrossing%100; // 横线计数nCount = 1;i = x - 1; // 左while(i>=0 && g_iBoard[x][y]==g_iBoard[i][y]){nCount++;i--;}i = x + 1; // 右while(i<MAX_LINES && g_iBoard[x][y]==g_iBoard[i][y]){nCount++;i++;}if(nCount >= 5)return 1; // 竖线计数nCount = 1;j = y - 1; // 上while(j>=0 && g_iBoard[x][y]==g_iBoard[x][j]){nCount++;j--;}j = y + 1; // 下while(j<MAX_LINES && g_iBoard[x][y]==g_iBoard[x][j]){nCount++;j++;}if(nCount >= 5)return 1; // 左斜线计数nCount = 1;i = x - 1; // 左上j = y - 1;while(i>=0 && j>=0 && g_iBoard[x][y]==g_iBoard[i][j]){nCount++;i--;j--;}i = x + 1; // 右下j = y + 1;while(i<MAX_LINES && j<MAX_LINES && g_iBoard[x][y]==g_iBoard[i][j]){nCount++;i++;j++;}if(nCount >= 5)return 1; // 右斜线计数nCount = 1;i = x + 1; // 右上j = y - 1;while(i<MAX_LINES && j>=0 && g_iBoard[x][y]==g_iBoard[i][j]){nCount++;i++;j--;}i = x - 1; // 左下j = y + 1;while(i>=0 && j<MAX_LINES && g_iBoard[x][y]==g_iBoard[i][j]){nCount++;i--;j++;}if(nCount >= 5)return 1; return 0;} // 重置对局数据void Five_ResetData(void){for(int i=0; i<MAX_LINES; i++)for(int j=0; j<MAX_LINES; j++)g_iBoard[i][j] = NONE;g_nHands = 0;g_nLastCrossing = -1;g_iWho = BLACK;} // 记录一个落子数据// 参数:x,y = 棋子坐标,c = 棋子颜色void Five_AddPiece(int x, int y, enum en_COLOR c){g_iBoard[x][y] = c;g_nHands++;g_nLastCrossing = 100*x + y;g_iWho = (g_iWho == BLACK ? WHITE : BLACK);}
3.FiveData.h  

// FiveData.h // 五子棋:数据处理模块对外接口 #ifndef _FIVE_DATA_H#define _FIVE_DATA_Henum en_COLOR// 棋子颜色{NONE = 0,// 无子BLACK, // 黑子WHITE// 白子}; // 棋局#define MAX_LINES 15// 棋盘线数extern int g_nHands;// 总手数extern int g_nLastCrossing;// 100*x+y,(x,y)为最后一手的坐标extern enum en_COLOR g_iWho;// 轮到哪方落子:0 不可落子状态,1 黑方,2 白方extern int g_iBoard[MAX_LINES][MAX_LINES]; // 棋盘交叉点数据:0 无子,1 黑子,2 白子// 判断最后一手棋是否形成五子连珠// 返回值:1 = 形成五子连珠, 0 = 未形成五子连珠extern _Bool Five_isFive(void); // 重置对局数据extern void Five_ResetData(void); // 记录一个落子数据// 参数:x,y = 棋子坐标,c = 棋子颜色extern void Five_AddPiece(int x, int y, enum en_COLOR c);#endif
以上就是本文的全部内容,希望对大家的学习有所帮助。