本文实例介绍了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

#include

#include

#include

#include

#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 main

int 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_Event event; // 事件

_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());

#endif

return 1;

}

// 创建主窗口及其渲染器

if(SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN, &pWindow, &pRenderer)==-1)

{

#ifdef _DEBUG_

fprintf(stderr, "%s", SDL_GetError());

#endif

goto 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());

#endif

goto label_error;

}

// 加载字体文件

if(NULL == (pFont = TTF_OpenFont(szFontFile, 20))) // 这个 20 是字体大小

{

#ifdef _DEBUG_

fprintf(stderr, "%s", SDL_GetError());

#endif

goto 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;

}

else

Five_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);

else

sprintf(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=0 && n

{

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;

else

c = *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

{

for(int j=0; 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;

else

c = *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

{

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

{

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

{

nCount++;

i++;

j++;

}

if(nCount >= 5)

return 1;

// 右斜线计数

nCount = 1;

i = x + 1; // 右上

j = y - 1;

while(i=0 && g_iBoard[x][y]==g_iBoard[i][j])

{

nCount++;

i++;

j--;

}

i = x - 1; // 左下

j = y + 1;

while(i>=0 && j

{

nCount++;

i--;

j++;

}

if(nCount >= 5)

return 1;

return 0;

}

// 重置对局数据

void Five_ResetData(void)

{

for(int i=0; i

for(int j=0; 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_H

enum 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

以上就是本文的全部内容,希望对大家的学习有所帮助。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐