本文实例介绍了Android下用SDL2实现一个简单的五子棋游戏,分享给大家供大家参考,具体内容如下
1. Five.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
// 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
// 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
|
以上就是本文的全部内容,希望对大家的学习有所帮助。