欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

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