
/* XOXO 井字游戏 主要功能完成 (无AI) */
/* 下面只贴了些下功能函数 */
/* df_game_winner 检测谁赢了, X玩家和值3赢,O玩家和值15赢 */
static void df_game_winner (int player)
{
int i, j, k;
cairo_t * cr;
cr = cairo_create (surface);
j = -1;
k = -1;
/* 检测三横和值 */
for (i = 0; i < 9; i += 3)
{
if (xoxo -> data[i] + xoxo -> data[i+1] + xoxo -> data[i+2] == player * 3)
{
j = i;
k = i + 2;
break;
}
}
/* 检测三纵和值 */
for (i = 0; i < 3; i++)
{
if (xoxo -> data[i] + xoxo -> data[i + 3] + xoxo -> data[i + 6] == player * 3)
{
j = i;
k = i + 6;
break;
}
}
/* 检测两斜线和值 */
if (xoxo -> data[0] + xoxo -> data[4] + xoxo -> data[8] == player * 3)
{
j = 0;
k = 8;
}
if (xoxo -> data[2] + xoxo -> data[4] + xoxo -> data[6] == player * 3)
{
j = 2;
k = 6;
}
/* 有人胜出,画连线表示完成 */
if (j >= 0)
{
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width (cr, xoxo -> radius * 0.2);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.6);
cairo_move_to (cr, xoxo -> center[j].x, xoxo -> center[j].y);
cairo_line_to (cr, xoxo -> center[k].x, xoxo -> center[k].y);
xoxo -> status = 255;
cairo_stroke (cr);
}
cairo_destroy (cr);
}
/* df_init_gui_data 初始化界面数据 * width, height 游戏界面宽与高 */
static void df_init_gui_data (double width, double height)
{
int i, j;
xoxo -> width = width;
xoxo -> height = height;
xoxo -> radius = (xoxo -> width < xoxo -> height) ? xoxo -> width / 6 : xoxo -> height / 6;
/* 设置界面十六个点坐标 */
for (i = 0; i < 16; i += 4)
{
for (j = 0; j < 4; j++)
{
xoxo -> grid[i + j].x = j * xoxo -> width / 3;
xoxo -> grid[i + j].y = i / 4 * xoxo -> height / 3;
}
}
/* 设置界面九个中心点坐标 */
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
xoxo -> center[i + j * 3].x = (2 * i + 1) * xoxo -> width / 6;
xoxo -> center[i + j * 3].y = (2 * j + 1) * xoxo -> height / 6;
}
}
/* 终端命令行打印十六个点坐标 */
g_print (" %f , %f , %f \n ", xoxo -> width, xoxo -> height, xoxo -> radius);
for (i = 0; i < 16; i++)
{
g_print ("网格坐标%2d : %12f %12f \n", i, xoxo -> grid[i].x, xoxo -> grid[i].y);
}
/* 终端命令行打印九个中心点坐标 */
for (i = 0; i < 9; i++)
{
g_print ("方格中心坐标%2d : %12f %12f \n", i, xoxo -> center[i].x, xoxo -> center[i].y);
}
}
/* 在指定的中心坐标画 玩家标志X */
static void df_game_draw_x (int index)
{
int i, k;
cairo_t *cr;
k = xoxo -> radius - 50;
cr = cairo_create (surface);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
for (i = 0; i < 2; i++)
{
if (i == 0)
{
cairo_set_line_width (cr, xoxo -> radius * 0.4);
cairo_set_source_rgb (cr, 0.8, 0.7, 0.0);
}
else
{
cairo_set_line_width (cr, xoxo -> radius * 0.3);
cairo_set_source_rgb (cr, 0.4, 0.2, 0.0);
}
cairo_move_to (cr, xoxo -> center[index].x - k, xoxo -> center[index].y - k);
cairo_line_to (cr, xoxo -> center[index].x + k, xoxo -> center[index].y + k);
cairo_move_to (cr, xoxo -> center[index].x - k, xoxo -> center[index].y + k);
cairo_line_to (cr, xoxo -> center[index].x + k, xoxo -> center[index].y - k);
cairo_stroke (cr);
}
cairo_destroy (cr);
}
/* 在指定的中心坐标画 玩家标志O */
static void df_game_draw_o (int index)
{
cairo_t *cr;
cr = cairo_create (surface);
cairo_set_line_width (cr, xoxo -> radius * 0.4);
cairo_set_source_rgb (cr, 0.2, 0.7, 0.9);
cairo_arc (cr, xoxo -> center[index].x, xoxo -> center[index].y, xoxo -> radius - 60, 0, 2 * M_PI);
cairo_stroke (cr);
cairo_set_line_width (cr, xoxo -> radius * 0.3);
cairo_set_source_rgb (cr, 0.1, 0.4, 0.5);
cairo_arc (cr, xoxo -> center[index].x, xoxo -> center[index].y, xoxo -> radius - 60, 0, 2 * M_PI);
cairo_stroke (cr);
cairo_destroy (cr);
}
/* 依据方格数据全部重绘 */
static void df_game_draw_all (void)
{
int i;
for (i = 0; i < 9; i++)
{
switch (xoxo -> data[i])
{
case 1: /* 玩家 X */
df_game_draw_x (i);
break;
case 5: /* 玩家 O */
df_game_draw_o (i);
break;
default:
break;
}
}
}
/* 处理鼠标按键按下后的数据处理 */
static void df_game_button_press (GtkWidget *widget, gdouble x, gdouble y)
{
int i, j;
/* 判断鼠标所在方格位置 */
j = -1; /* 记录鼠标所在方格 */
for (i = 0; i < 9; i++)
{
switch (i)
{
case 0:
if ((x > xoxo -> grid[0].x && x < xoxo -> grid[5].x) && (y > xoxo -> grid[0].y && y < xoxo -> grid[5].y))
j = 0;
break;
case 1:
if ((x > xoxo -> grid[1].x && x < xoxo -> grid[6].x) && (y > xoxo -> grid[1].y && y < xoxo -> grid[6].y))
j = 1;
break;
case 2:
if ((x > xoxo -> grid[2].x && x < xoxo -> grid[7].x) && (y > xoxo -> grid[2].y && y < xoxo -> grid[7].y))
j = 2;
break;
case 3:
if ((x > xoxo -> grid[4].x && x < xoxo -> grid[9].x) && (y > xoxo -> grid[4].y && y < xoxo -> grid[9].y))
j = 3;
break;
case 4:
if ((x > xoxo -> grid[5].x && x < xoxo -> grid[10].x) && (y > xoxo -> grid[5].y && y < xoxo -> grid[10].y))
j = 4;
break;
case 5:
if ((x > xoxo -> grid[6].x && x < xoxo -> grid[11].x) && (y > xoxo -> grid[6].y && y < xoxo -> grid[11].y))
j = 5;
break;
case 6:
if ((x > xoxo -> grid[8].x && x < xoxo -> grid[13].x) && (y > xoxo -> grid[8].y && y < xoxo -> grid[13].y))
j = 6;
break;
case 7:
if ((x > xoxo -> grid[9].x && x < xoxo -> grid[14].x) && (y > xoxo -> grid[9].y && y < xoxo -> grid[14].y))
j = 7;
break;
default:
j = 8;
break;
}
if (j >= 0) break;
}
if (j < 0) return;
g_print ("x : %12f , y : %12f ,鼠标所在方格 : %d Status %3d \n ", x, y, j, xoxo -> status);
/* 如果方格所在的值大于0,说明该位置已经被占用,就直接返回 */
if (xoxo -> data[j]) return;
/* 根据游戏状态,处理游戏数据 */
switch (xoxo -> status)
{
case 1: /* 玩家X */
df_game_draw_x (j);
xoxo -> data[j] = 1;
xoxo -> status = 5; /* 设置为O玩家状态 */
df_game_winner (1); /* 判断玩家X是否赢得游戏 */
break;
case 5: /* 玩家O */
df_game_draw_o (j);
xoxo -> data[j] = 5;
xoxo -> status = 1;
df_game_winner (5);
break;
case 255:
break;
default:
break;
}
}