Android下SDL2实现五子棋游戏
程序员文章站
2024-02-18 12:27:46
本文实例介绍了android下用sdl2实现一个简单的五子棋游戏,分享给大家供大家参考,具体内容如下
1. five.c
// five.c
//...
本文实例介绍了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 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<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; 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<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; 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<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_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
以上就是本文的全部内容,希望对大家的学习有所帮助。
下一篇: Java用for循环Map详细解析