妙妙小豆子

胆子大一点,想开一点。长风破浪会有时,直挂云帆济沧海

嵌套井字棋 银牌收录

程序简介

嵌套井字棋,是以前同桌带我玩哒。我介绍一下具体规则:

1.双方,回合制。每次落子的范围应是某个特定的小九宫格。如果这个特定的小九宫格无位置了或是开局第一手,则落子的范围是整个大九宫格。

2.大九宫格由九个小九宫格组成(像数独)。每次落子的这一个特定的小九宫格,相对于大九宫格的位置;正对应着上一次落子的格子,相对小九宫格的位置。

3.初步胜利:每个小九宫格满足井字棋规则。一旦某次落子后,出现某个小九宫格三子一线(同色),这个小九宫格归达成者,里面九个格子,无论状态,都放上达成者的棋子,标志着无法逆转了。

4.最终胜利:大九宫格满足井字棋规则。一旦某次落子后,出现某个小九宫格三子一线(同色),小九宫格归达成者,接着某三个小九宫格也三子一线(同色),则达成者胜利。

初次提交,我只以还原玩法为目标,双方棋子是用不同颜色的圆表示,落子范围是用不同颜色的线描绘出来的,十分简陋。ai 也是傻乎乎的。

第一次更新:

  1. 我参考老师给与的网络同款游戏截图进行仿制,包括按钮绘制,棋子绘制,棋盘绘制,落子范围的描绘,以及两套主题颜色,并且重构了代码。

第二次更新:

  1. 标题样式单独绘制。
  2. 按钮文字居中。
    3.“主题”名称的更换。
  3. 添加落子闪烁效果。
  4. 修改开局悔棋的 bug(bug 是由于在游戏中重开后,未修改历史记录,导致重开后能悔棋)。
  5. 增加特殊模式:取消落子范围的限定,落子范围不再由上次落子位置决定,而是全部格子。
  6. 添加胜利时格子闪烁效果。

第三次更新:

  1. ai 的更新。普通模式,就是 9 次井字棋游戏,所以无失误情况下,是 9 次平局。嵌套模式,比较复杂,重点是决策树的叶子结点的赋值,是凭借我对这个游戏的理解在赋值,我对不同的情况给予不同的权值。可以说,情况的多少和权值的分配决定 ai 智能的程度。虽然我不确定现在程序里的设置离最佳设置有多远,但是和之前的 ai 相比,已经是肉眼可见的大大增强了。
  2. 文章细节的更新。

第四次更新:

  1. 图片的更新,边距的缩小
  2. 代码更新,现兼容 vc2010,也兼容 vc6.0

程序运行效果:

完整源代码:

// 程序:嵌套井字棋
// 作者:Gary
// 编译环境:Visual C++ 6.0/Visual C++ 2010,EasyX_20211109
// 编写日期:2020-2-13

# include <math.h>
# include <graphics.h>


////////////////////////////// 游戏进程头文件 //////////////////////////////


// 头文件
// 头文件编译开始
#ifndef CIRCLE_H
#define CIRCLE_H

// 定义变量
static double pi = acos (-1.0);		// 圆周率π
static HWND hOut;					// 画布

// 定义一个结构体,格子
struct Node1
{
	int bigboxnum;					// 所在大格编号
	int smallboxnum;				// 所在小格编号
	int posx, posy;					// 坐标
	int type;						// 格子从属状态
};

// 定义一个结构体,操作手
struct Node2
{
	int nowboxnum;					// 本次落子的大格编号
	int nextboxnum;					// 下次落子的大格编号
	int type;						// 执手判断
};

// 定义一个结构体,按钮
struct Node3
{
	int posx1, posy1, posx2, posy2;	// 坐标
	double r;						// 原按钮半径
	LPTSTR text;					// 按钮文本
	int type;						// 按钮激活状态
};

// 定义一个结构体,主题
struct Node4
{
	COLORREF blockcolor[4];			// 叉叉主体	;叉叉光影		;圈圈主体	;圈圈光影
	COLORREF bkcolor[3];			// 大背景	;落子范围背景	;按钮背景
	COLORREF linecolor[3];			// 小格子线	;大格子线		;落子范围线
	int type;						// 主题模式
};

// 定义一个结构体,记录
struct Node5
{
	int bigboxnum[90];				// 所在大格编号
	int smallboxnum[90];			// 所在小格编号
	int flag;						// 哨兵
	int type;						// 记录开启状态模式
};

// 定义一个类,game
class game
{
public:
	// 函数
	// 游戏进程源文件
	int carry_main ();									// 游戏进程主循函数

	void draw_button ();								// 按钮绘制函数
	void draw_circle (double size, int posx, int posy);	// 圈圈棋子绘制函数
	void draw_crosses (double size, int posx, int posy); // 十字架棋子绘制函数
	void draw_word (double size, int posx, int posy);	// 标题绘制函数

	void check_big (int back_or_not);					// 大格判断函数
	void check_small (int back_or_not);					// 小格判断函数

	void machine ();										// 人机函数
	int machine_check ();								// 人机决策树函数
	void mod_scene_change ();							// 主题参数变更后,颜色结构体参数更新函数
	void read_mod_scene (int a);							// 主题参数读取函数

	// 准备进程源文件
	void carry_prepare ();								// 准备进程主循函数
	void initialization_prepare ();						// 准备进程初始化函数	
	void draw_scene_prepare ();							// 准备进程绘制函数

	// 开始进程源文件
	void carry_start ();								// 开始进程主循函数
	void initialization_start ();						// 开始进程初始化函数
	void draw_scene_start ();							// 开始进程绘制函数

	// 结构体
	Node1 box[10][10];									// 格子,一百个
	Node2 block;										// 操作手
	Node3 boxm[20];										// 按钮,预制二十个
	Node4 color;										// 颜色	
	Node5 record;										// 记录

	// 变量
	int ma[2];											// 人机输出的两个值,代表人机下棋子的位置
	int num_button;										// 按钮数量
	int exit_carry;										// 主进程主循函数控制参数
	int exit_start;										// 开始进程主循函数控制参数
	int mod_scene;										// 主题模式参数,两种
	int mod_start;										// 游戏模式参数,六种
	int back_or_not;									// 悔棋参数,置一表示是悔棋操作中,跳过闪烁显示
	int eat[9];											// 存临时九宫格状态
};

// 头文件编译结束
#endif




////////////////////////////// 主程序源文件 //////////////////////////////




// 窗口初始化
void initialization ()
{
	// 窗口定义,整个程序仅定义一次
	hOut = initgraph (601, 501);
	// 窗口标题
	SetWindowText (hOut, _T ("嵌套井字棋"));
}



// 总进程主循函数
void carry ()
{
	// 总进程参数初始化
	int exit_carry = 0;
	// 进程控制
	BeginBatchDraw ();
	// 创建游戏类对象
	game G;
	// 初始化主题
	G.read_mod_scene (2);
	// 游戏进程
	while (exit_carry == 0)
	{
		// 执行游戏总进程,并接收游戏进程结束时返回值
		// 准备进程时,点击退出按钮结束返回 1
		// 开始进程时,点击返回按钮结束返回 0
		exit_carry = G.carry_main ();
	}
	EndBatchDraw ();
	// 关闭窗口
	closegraph ();
}



// 主函数
int main (void)
{
	// 初始化
	initialization ();
	// 总进程主循函数
	carry ();
	return 0;
}



////////////////////////////// 游戏进程源文件 //////////////////////////////




// 游戏进程主循函数
int game::carry_main ()
{
	// 游戏进程参数初始化
	exit_carry = 0;
	// 准备进程初始化函数
	initialization_prepare ();
	// 准备进程主循函数
	carry_prepare ();
	// 准备进程结束
	// 准备进程时,点击退出按钮结束,游戏进程参数为 1
	// 准备进程时,正常进入游戏,游戏进程参数为 0
	if (exit_carry == 0)
	{
		// 开始进程初始化函数
		initialization_start ();
		// 开始进程主循函数
		carry_start ();
	}
	// 开始进程结束
	// 点击返回按钮结束,或者正常游戏结束,游戏进程参数不变
	return exit_carry;
}



// 按钮绘制函数
void game::draw_button ()
{
	// 根据颜色结构体设置参数
	setlinecolor (color.linecolor[0]);
	setfillcolor (color.bkcolor[2]);
	setbkcolor (color.bkcolor[2]);
	settextcolor (color.bkcolor[0]);
	settextstyle (30, 15, _T ("Consolas"));
	setlinestyle (PS_SOLID, 10);

	// 根据按钮数量参数绘制
	for (int i = 0; i < num_button; i++)
	{
		if (boxm[i].type == 0)
		{
			// 边框
			fillroundrect (boxm[i].posx1, boxm[i].posy1, boxm[i].posx2, boxm[i].posy2, 25, 25);
			// 文字
			outtextxy (boxm[i].posx1 + (boxm[i].posx2 - boxm[i].posx1) / 2 - textwidth (boxm[i].text) / 2, boxm[i].posy1 + 15, boxm[i].text);
		}
	}
	FlushBatchDraw ();
}



// 主题模式参数改变后,颜色结构体参数更新函数
void game::mod_scene_change ()
{
	mod_scene = mod_scene == 2 ? 1 : 2;
	// 白天模式
	if (mod_scene == 1)
	{
		// 十字架棋子主题颜色
		color.blockcolor[0] = RGB (234, 14, 15);

		// 十字架棋子光影颜色
		color.blockcolor[1] = RGB (247, 125, 128);

		// 圈圈架棋子主题颜色
		color.blockcolor[2] = RGB (31, 16, 235);

		// 圈圈架棋子光影颜色
		color.blockcolor[3] = RGB (137, 128, 237);

		// 背景颜色
		color.bkcolor[0] = RGB (250, 250, 250);
		color.bkcolor[1] = RGB (234, 128, 128);
		color.bkcolor[2] = RGB (88, 88, 88);

		// 线条颜色
		color.linecolor[0] = RGB (125, 125, 125);
		color.linecolor[1] = RGB (2, 2, 2);
		color.linecolor[2] = RGB (215, 24, 24);
	}
	// 夜间模式
	else if (mod_scene == 2)
	{
		// 十字架棋子主题颜色
		color.blockcolor[0] = RGB (234, 123, 5);

		// 十字架棋子光影颜色
		color.blockcolor[1] = RGB (234, 179, 129);

		// 圈圈架棋子主题颜色
		color.blockcolor[2] = RGB (123, 235, 13);

		// 圈圈架棋子光影颜色
		color.blockcolor[3] = RGB (181, 235, 126);

		// 背景颜色
		color.bkcolor[0] = RGB (0, 0, 0);
		color.bkcolor[1] = RGB (233, 180, 128);
		color.bkcolor[2] = RGB (254, 254, 254);

		// 线条颜色
		color.linecolor[0] = RGB (125, 125, 125);
		color.linecolor[1] = RGB (254, 254, 254);
		color.linecolor[2] = RGB (233, 124, 19);
	}
}



// 读取主题模式参数函数,仅针对第一次	
void game::read_mod_scene (int a)
{
	mod_scene = a;
	// 主题模式参数更新后,颜色结构体参数更新
	mod_scene_change ();
}



// 十字架绘制函数
void game::draw_crosses (double size, int posx, int posy)
{
	int i;
	// 绘制
	POINT p[12];

	// 定义一个结构体
	struct Node1
	{
		// 单位坐标
		double x, y;
	};
	Node1 pts[12];

	// 主体
	setfillcolor (color.blockcolor[0]);
	setlinecolor (color.linecolor[1]);
	setlinestyle (PS_SOLID, 2);
	// 单位坐标定位
	pts[0].x = -0.5; pts[0].y = -1.0;
	pts[1].x = 0.0; pts[1].y = -0.5;
	pts[2].x = 0.5; pts[2].y = -1.0;
	pts[3].x = 1.0; pts[3].y = -0.5;
	pts[4].x = 0.5; pts[4].y = 0.0;
	pts[5].x = 1.0; pts[5].y = 0.5;
	pts[6].x = 0.5; pts[6].y = 1.0;
	pts[7].x = 0.0; pts[7].y = 0.5;
	pts[8].x = -0.5; pts[8].y = 1.0;
	pts[9].x = -1.0; pts[9].y = 0.5;
	pts[10].x = -0.5; pts[10].y = 0.0;
	pts[11].x = -1.0; pts[11].y = -0.5;

	// 形参代入
	for (i = 0; i < 12; i++)
	{
		p[i].x = long (pts[i].x * size + posx);
		p[i].y = long (pts[i].y * size + posy);
	}

	// 绘制
	fillpolygon (p, 12);


	// 光影
	setfillcolor (color.blockcolor[1]);
	setlinecolor (color.blockcolor[1]);
	setlinestyle (PS_SOLID, 1);

	// 单位坐标定位
	pts[0].x = 0.135; pts[0].y = -0.5;
	pts[1].x = 0.5; pts[1].y = -0.865;
	pts[2].x = 0.865; pts[2].y = -0.5;
	pts[3].x = 0.82; pts[3].y = -0.455;
	pts[4].x = 0.5; pts[4].y = -0.78;
	pts[5].x = 0.18; pts[5].y = -0.455;

	// 形参代入
	for (i = 0; i < 6; i++)
	{
		p[i].x = long (pts[i].x * size + posx);
		p[i].y = long (pts[i].y * size + posy);
	}

	// 绘制
	fillpolygon (p, 6);

	pts[0].x = -0.865; pts[0].y = -0.5;
	pts[1].x = -0.5; pts[1].y = -0.865;
	pts[2].x = -0.135; pts[2].y = -0.5;
	pts[3].x = -0.18; pts[3].y = -0.455;
	pts[4].x = -0.5; pts[4].y = -0.78;
	pts[5].x = -0.82; pts[5].y = -0.455;

	// 形参代入
	for (i = 0; i < 6; i++)
	{
		p[i].x = long (pts[i].x * size + posx);
		p[i].y = long (pts[i].y * size + posy);
	}

	// 绘制
	fillpolygon (p, 6);

	// 单位坐标定位
	pts[0].x = 0.5; pts[0].y = -0.865 + 1;
	pts[1].x = 0.865; pts[1].y = -0.5 + 1;
	pts[2].x = 0.82; pts[2].y = -0.455 + 1;
	pts[3].x = 0.455; pts[3].y = -0.82 + 1;

	// 形参代入
	for (i = 0; i < 4; i++)
	{
		p[i].x = long (pts[i].x * size + posx);
		p[i].y = long (pts[i].y * size + posy);
	}

	// 绘制
	fillpolygon (p, 4);

	// 单位坐标定位
	pts[0].x = -0.865; pts[0].y = -0.5 + 1;
	pts[1].x = -0.5; pts[1].y = -0.865 + 1;
	pts[2].x = -0.455; pts[2].y = -0.82 + 1;
	pts[3].x = -0.82; pts[3].y = -0.455 + 1;

	// 形参代入
	for (i = 0; i < 4; i++)
	{
		p[i].x = long (pts[i].x * size + posx);
		p[i].y = long (pts[i].y * size + posy);
	}

	// 绘制
	fillpolygon (p, 4);
}



// 圈圈绘制函数
void game::draw_circle (double size, int posx, int posy)
{
	// 从半径最大开始,往半径最小进行
	// 最大圆
	setfillcolor (color.blockcolor[2]);
	setlinecolor (color.linecolor[1]);
	setlinestyle (PS_SOLID, 2);

	fillcircle (posx, posy, int (size));

	// 光影
	setfillcolor (color.blockcolor[3]);
	setlinecolor (color.blockcolor[3]);
	setlinestyle (PS_SOLID, 1);

	fillpie (int (-0.80 * size + posx), int (-0.80 * size + posy), int (0.80 * size + posx), int (0.80 * size + posy), 0, pi / 2.0);
	fillpie (int (-0.70 * size + posx), int (-0.70 * size + posy), int (0.70 * size + posx), int (0.70 * size + posy), 0, pi / 2.0);

	// 中圆
	setfillcolor (color.blockcolor[2]);
	setlinecolor (color.blockcolor[2]);
	setlinestyle (PS_SOLID, 1);

	fillcircle (posx, posy, int (0.70 * size));

	// 最小圆
	setfillcolor (color.bkcolor[0]);
	setlinecolor (color.linecolor[1]);
	setlinestyle (PS_SOLID, 2);

	fillcircle (posx, posy, int (0.39 * size));
}



// 小格判断函数
void game::check_small (int back_or_not)
{
	int i, j, k, t;
	i = block.nowboxnum;
	j = block.type;
	// 小格判断。若小格三连,则对应大格有归属,则需要进行大格判断
	// 三行分别是包含左上角点的三条线,包含中心点的三条线,包含右下角点的两条线
	if ((box[i][0].type == j && ((box[i][1].type == j && box[i][2].type == j) || (box[i][3].type == j && box[i][6].type == j) || (box[i][4].type == j && box[i][8].type == j)))
		|| (box[i][4].type == j && ((box[i][1].type == j && box[i][7].type == j) || (box[i][3].type == j && box[i][5].type == j) || (box[i][2].type == j && box[i][6].type == j)))
		|| (box[i][8].type == j && ((box[i][2].type == j && box[i][5].type == j) || (box[i][6].type == j && box[i][7].type == j))))
	{
		// 判断成功
		// 非悔棋状态
		if (back_or_not == 0)
		{
			// 闪烁显示
			// 绘制小棋子
			for (k = 0; k < 2; k++)
			{
				// 格子绘制
				setfillcolor (color.bkcolor[1]);
				setlinecolor (color.linecolor[1]);
				setlinestyle (PS_SOLID, 5);
				for (t = 0; t < 9; t++)
				{
					if (box[i][t].type == j)
					{
						fillrectangle (box[i][t].posx, box[i][t].posy, box[i][t].posx + 50, box[i][t].posy + 50);
					}
				}
				FlushBatchDraw ();
				Sleep (200);

				// 棋子绘制
				for (t = 0; t < 9; t++)
				{
					if (box[i][t].type == j)
					{
						if (box[i][t].type == 1) { draw_crosses (25, box[i][t].posx + 25, box[i][t].posy + 25); }
						else if (box[i][t].type == 2) { draw_circle (25, box[i][t].posx + 25, box[i][t].posy + 25); }
					}
				}
				FlushBatchDraw ();
				Sleep (200);
			}
		}

		// 更改小格子参数(属性)
		for (k = 0; k <= 8; k++)
		{
			box[i][k].type = j;
		}

		// 更改大格子参数(属性)
		box[i][9].type = j;

		// 非悔棋状态
		if (back_or_not == 0)
		{
			// 闪烁
			// 绘制大棋子
			for (k = 0; k < 2; k++)
			{
				// 格子绘制
				setfillcolor (color.bkcolor[1]);
				setlinecolor (color.linecolor[1]);
				setlinestyle (PS_SOLID, 5);
				fillrectangle (box[i][0].posx, box[i][0].posy, box[i][8].posx + 50, box[i][8].posy + 50);
				FlushBatchDraw ();
				Sleep (200);

				// 棋子绘制
				if (box[i][9].type == 1) { draw_crosses (75, box[i][4].posx + 25, box[i][4].posy + 25); }
				else if (box[i][9].type == 2) { draw_circle (75, box[i][4].posx + 25, box[i][4].posy + 25); }
				FlushBatchDraw ();
				Sleep (200);
			}
		}

		// 大格判断
		check_big (back_or_not);
	}
	// 小格判断。若小格满且无归属,则对应大格不能为零了,也不能是 1 和 2
	// k = 0 无空位
	k = 0;
	for (j = 0; j < 9; j++)
	{
		if (box[i][j].type == 0)
		{
			// k = 1 有空位,则大格中的小格未满
			k = 1;
			break;
		}
	}
	// 大格参数为 3,即不属于任何一方
	if (k == 0 && box[i][9].type == 0)
	{
		box[i][9].type = 3;
	}
}



// 大格判断函数
void game::check_big (int back_or_not)
{
	int j, k, t;
	j = block.type;

	// 大格判断,若大格三连则立即结束
	// 三行分别是包含左上角点的三条线,包含中心点的三条线,包含右下角点的两条线
	if ((box[0][9].type == j && ((box[1][9].type == j && box[2][9].type == j) || (box[3][9].type == j && box[6][9].type == j) || (box[4][9].type == j && box[8][9].type == j)))
		|| (box[4][9].type == j && ((box[1][9].type == j && box[7][9].type == j) || (box[3][9].type == j && box[5][9].type == j) || (box[2][9].type == j && box[6][9].type == j)))
		|| (box[8][9].type == j && ((box[2][9].type == j && box[5][9].type == j) || (box[6][9].type == j && box[7][9].type == j))))
	{
		// 更改棋盘参数(属性)
		box[9][9].type = j;

		// 非悔棋状态
		if (back_or_not == 0)
		{
			// 闪烁显示
			// 绘制大棋子
			for (k = 0; k < 2; k++)
			{
				// 格子绘制
				setfillcolor (color.bkcolor[1]);
				setlinecolor (color.linecolor[1]);
				setlinestyle (PS_SOLID, 5);

				for (t = 0; t < 9; t++)
				{
					if (box[t][9].type == j)
					{
						fillrectangle (box[t][0].posx, box[t][0].posy, box[t][8].posx + 50, box[t][8].posy + 50);
					}
				}
				FlushBatchDraw ();
				Sleep (200);

				// 棋子绘制
				for (t = 0; t < 9; t++)
				{
					if (box[t][9].type == j)
					{
						if (box[t][9].type == 1) { draw_crosses (75, box[t][4].posx + 25, box[t][4].posy + 25); }
						else if (box[t][9].type == 2) { draw_circle (75, box[t][4].posx + 25, box[t][4].posy + 25); }
					}
				}
				FlushBatchDraw ();
				Sleep (200);
			}

			// 闪烁
			// 绘制超大棋子
			for (k = 0; k < 2; k++)
			{
				// 格子绘制
				setfillcolor (color.bkcolor[1]);
				setlinecolor (color.linecolor[1]);
				setlinestyle (PS_SOLID, 5);
				fillrectangle (box[0][0].posx, box[0][0].posy, box[8][8].posx + 50, box[8][8].posy + 50);
				FlushBatchDraw ();
				Sleep (200);

				// 棋子绘制
				if (box[9][9].type == 1) { draw_crosses (225, box[4][4].posx + 25, box[4][4].posy + 25); }
				else if (box[9][9].type == 2) { draw_circle (225, box[4][4].posx + 25, box[4][4].posy + 25); }
				FlushBatchDraw ();
				Sleep (200);
			}
		}
	}
}



// 人机决策数函数
int game::machine_check ()
{
	int i, j, k, b, c;

	// 定义一个结构体,决策树
	struct Node
	{
		int eat[9]; // 九宫格状态
		int eat_changenum; // 子结点改变了父结点哪个空格状态
		int gamenum; // 估计值
	};
	Node tree[9];

	// 初始化
	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 9; j++)
		{
			tree[i].eat[j] = eat[j];
			tree[i].eat_changenum = i;
		}
		tree[i].eat[i] = block.type;
		tree[i].gamenum = 0;
	}

	b = block.type;
	c = b == 1 ? 2 : 1;

	// 特殊模式和嵌套模式
	if (exit_start == -1 || exit_start == 0)
	{
		for (i = 0; i < 9; i++)
		{
			// 己方绝杀点
			if (// 上水平线
				(tree[i].eat[0] == b && tree[i].eat[1] == b && tree[i].eat_changenum == 2) ||
				(tree[i].eat[0] == b && tree[i].eat[2] == b && tree[i].eat_changenum == 1) ||
				(tree[i].eat[1] == b && tree[i].eat[2] == b && tree[i].eat_changenum == 0) ||
				// 中水平线
				(tree[i].eat[3] == b && tree[i].eat[4] == b && tree[i].eat_changenum == 5) ||
				(tree[i].eat[3] == b && tree[i].eat[5] == b && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == b && tree[i].eat[5] == b && tree[i].eat_changenum == 3) ||
				// 下水平线
				(tree[i].eat[6] == b && tree[i].eat[7] == b && tree[i].eat_changenum == 8) ||
				(tree[i].eat[6] == b && tree[i].eat[8] == b && tree[i].eat_changenum == 7) ||
				(tree[i].eat[7] == b && tree[i].eat[8] == b && tree[i].eat_changenum == 6) ||
				// 左垂直线
				(tree[i].eat[0] == b && tree[i].eat[3] == b && tree[i].eat_changenum == 6) ||
				(tree[i].eat[0] == b && tree[i].eat[6] == b && tree[i].eat_changenum == 3) ||
				(tree[i].eat[3] == b && tree[i].eat[6] == b && tree[i].eat_changenum == 0) ||
				// 中垂直线
				(tree[i].eat[1] == b && tree[i].eat[4] == b && tree[i].eat_changenum == 7) ||
				(tree[i].eat[1] == b && tree[i].eat[7] == b && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == b && tree[i].eat[7] == b && tree[i].eat_changenum == 1) ||
				// 右垂直线
				(tree[i].eat[2] == b && tree[i].eat[5] == b && tree[i].eat_changenum == 8) ||
				(tree[i].eat[2] == b && tree[i].eat[8] == b && tree[i].eat_changenum == 5) ||
				(tree[i].eat[5] == b && tree[i].eat[8] == b && tree[i].eat_changenum == 2) ||
				// 左上右下斜线
				(tree[i].eat[0] == b && tree[i].eat[4] == b && tree[i].eat_changenum == 8) ||
				(tree[i].eat[0] == b && tree[i].eat[8] == b && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == b && tree[i].eat[8] == b && tree[i].eat_changenum == 0) ||
				// 右上左下斜线
				(tree[i].eat[2] == b && tree[i].eat[4] == b && tree[i].eat_changenum == 6) ||
				(tree[i].eat[2] == b && tree[i].eat[6] == b && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == b && tree[i].eat[6] == b && tree[i].eat_changenum == 2))
			{
				tree[i].gamenum += 1000;
			}
			// 敌方绝杀点
			else if (// 上水平线
				(tree[i].eat[0] == c && tree[i].eat[1] == c && tree[i].eat_changenum == 2) ||
				(tree[i].eat[0] == c && tree[i].eat[2] == c && tree[i].eat_changenum == 1) ||
				(tree[i].eat[1] == c && tree[i].eat[2] == c && tree[i].eat_changenum == 0) ||
				// 中水平线
				(tree[i].eat[3] == c && tree[i].eat[4] == c && tree[i].eat_changenum == 5) ||
				(tree[i].eat[3] == c && tree[i].eat[5] == c && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == c && tree[i].eat[5] == c && tree[i].eat_changenum == 3) ||
				// 下水平线
				(tree[i].eat[6] == c && tree[i].eat[7] == c && tree[i].eat_changenum == 8) ||
				(tree[i].eat[6] == c && tree[i].eat[8] == c && tree[i].eat_changenum == 7) ||
				(tree[i].eat[7] == c && tree[i].eat[8] == c && tree[i].eat_changenum == 6) ||
				// 左垂直线
				(tree[i].eat[0] == c && tree[i].eat[3] == c && tree[i].eat_changenum == 6) ||
				(tree[i].eat[0] == c && tree[i].eat[6] == c && tree[i].eat_changenum == 3) ||
				(tree[i].eat[3] == c && tree[i].eat[6] == c && tree[i].eat_changenum == 0) ||
				// 中垂直线
				(tree[i].eat[1] == c && tree[i].eat[4] == c && tree[i].eat_changenum == 7) ||
				(tree[i].eat[1] == c && tree[i].eat[7] == c && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == c && tree[i].eat[7] == c && tree[i].eat_changenum == 1) ||
				// 右垂直线
				(tree[i].eat[2] == c && tree[i].eat[5] == c && tree[i].eat_changenum == 8) ||
				(tree[i].eat[2] == c && tree[i].eat[8] == c && tree[i].eat_changenum == 5) ||
				(tree[i].eat[5] == c && tree[i].eat[8] == c && tree[i].eat_changenum == 2) ||
				// 左上右下斜线
				(tree[i].eat[0] == c && tree[i].eat[4] == c && tree[i].eat_changenum == 8) ||
				(tree[i].eat[0] == c && tree[i].eat[8] == c && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == c && tree[i].eat[8] == c && tree[i].eat_changenum == 0) ||
				// 右上左下斜线
				(tree[i].eat[2] == c && tree[i].eat[4] == c && tree[i].eat_changenum == 6) ||
				(tree[i].eat[2] == c && tree[i].eat[6] == c && tree[i].eat_changenum == 4) ||
				(tree[i].eat[4] == c && tree[i].eat[6] == c && tree[i].eat_changenum == 2))
			{
				tree[i].gamenum += 1000;
			}
			// 中心点
			else if (tree[i].eat_changenum == 4)
			{
				tree[i].gamenum += 10;
			}
			// 对角点
			else if (tree[i].eat[4] == b)
			{
				if (tree[i].eat[0] == c && tree[i].eat_changenum == 8) { tree[i].gamenum += 10; }
				if (tree[i].eat[2] == c && tree[i].eat_changenum == 6) { tree[i].gamenum += 10; }
				if (tree[i].eat[6] == c && tree[i].eat_changenum == 2) { tree[i].gamenum += 10; }
				if (tree[i].eat[8] == c && tree[i].eat_changenum == 0) { tree[i].gamenum += 10; }
				if (tree[i].eat_changenum == 1 && ((tree[i].eat[0] == c && tree[i].eat[8] == c) ||
					(tree[i].eat[2] == c && tree[i].eat[6] == c)))
				{
					tree[i].gamenum += 100;
				}
			}
			// 特殊点
			else if (tree[i].eat_changenum == 2 && tree[i].eat[4] == c && tree[i].eat[8] == c)
			{
				tree[i].gamenum += 100;
			}
			// 点已被占
			if ((ma[0] == -1 && box[tree[i].eat_changenum][9].type != 0) || (ma[0] != -1 && box[ma[0]][tree[i].eat_changenum].type != 0))
			{
				tree[i].gamenum = -10000;
			}
		}
	}
	// 嵌套模式的小格选择
	if (exit_start == 0 && ma[0] != -1)
	{
		for (i = 0; i < 9; i++)
		{
			if (box[tree[i].eat_changenum][9].type != 0)
			{
				tree[i].gamenum -= 100;
			}
			if (// 上水平线
				(box[0][9].type == c && box[1][9].type == c && (tree[i].eat_changenum == 2 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[0][9].type == c && box[2][9].type == c && (tree[i].eat_changenum == 1 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[1][9].type == c && box[2][9].type == c && (tree[i].eat_changenum == 0 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 中水平线
				(box[3][9].type == c && box[4][9].type == c && (tree[i].eat_changenum == 5 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[3][9].type == c && box[5][9].type == c && (tree[i].eat_changenum == 4 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[4][9].type == c && box[5][9].type == c && (tree[i].eat_changenum == 3 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 下水平线
				(box[6][9].type == c && box[7][9].type == c && (tree[i].eat_changenum == 8 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[6][9].type == c && box[8][9].type == c && (tree[i].eat_changenum == 7 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[7][9].type == c && box[8][9].type == c && (tree[i].eat_changenum == 6 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 左垂直线
				(box[0][9].type == c && box[3][9].type == c && (tree[i].eat_changenum == 6 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[0][9].type == c && box[6][9].type == c && (tree[i].eat_changenum == 3 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[3][9].type == c && box[6][9].type == c && (tree[i].eat_changenum == 0 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 中垂直线
				(box[1][9].type == c && box[4][9].type == c && (tree[i].eat_changenum == 7 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[1][9].type == c && box[7][9].type == c && (tree[i].eat_changenum == 4 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[4][9].type == c && box[7][9].type == c && (tree[i].eat_changenum == 1 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 右垂直线
				(box[2][9].type == c && box[5][9].type == c && (tree[i].eat_changenum == 8 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[2][9].type == c && box[8][9].type == c && (tree[i].eat_changenum == 5 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[5][9].type == c && box[8][9].type == c && (tree[i].eat_changenum == 2 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 左上右下斜线
				(box[0][9].type == c && box[4][9].type == c && (tree[i].eat_changenum == 8 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[0][9].type == c && box[8][9].type == c && (tree[i].eat_changenum == 4 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[4][9].type == c && box[8][9].type == c && (tree[i].eat_changenum == 0 || box[tree[i].eat_changenum][9].type != 0)) ||
				// 右上左下斜线
				(box[2][9].type == c && box[4][9].type == c && (tree[i].eat_changenum == 6 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[2][9].type == c && box[6][9].type == c && (tree[i].eat_changenum == 4 || box[tree[i].eat_changenum][9].type != 0)) ||
				(box[4][9].type == c && box[6][9].type == c && (tree[i].eat_changenum == 2 || box[tree[i].eat_changenum][9].type != 0)))
			{
				tree[i].gamenum -= 1000;
			}
			for (j = 0; j < 9; j++)
			{
				if (box[tree[i].eat_changenum][j].type == c)
				{
					tree[i].gamenum -= 100;
				}
			}
		}
	}

	// 给最大值
	k = -0xffffff; j = 0;
	for (i = 0; i < 9; i++)
	{
		if (tree[i].gamenum > k && ((ma[0] == -1 && box[tree[i].eat_changenum][9].type == 0) || (ma[0] != -1 && box[ma[0]][tree[i].eat_changenum].type == 0)))
		{
			k = tree[i].gamenum;
			j = tree[i].eat_changenum;
		}
	}

	// 错误输出,则纠正
	if (ma[0] != -1 && box[ma[0]][j].type != 0)
	{
		for (i = 0; i < 9; i++)
		{
			if (box[i][9].type == 0)
			{
				ma[0] = i;
				break;
			}
		}
		for (j = 0; j < 9; j++)
		{
			if (box[ma[0]][j].type == 0)
			{
				break;
			}
		}
	}

	// 返回决策值
	return j;
}



// 人机函数
void game::machine ()
{
	int i;
	// ai 的任务就是返回两个数
	ma[0] = -1; ma[1] = -1;
	// 大格无空位
	if (box[block.nextboxnum][9].type != 0)
	{
		// 初始化临时九宫格
		for (i = 0; i < 9; i++)
		{
			eat[i] = box[i][9].type;
		}
		// 人机决策数函数
		ma[0] = machine_check ();
	}
	// 大格有空位
	else if (box[block.nextboxnum][9].type == 0)
	{
		// 普通模式被限制
		ma[0] = block.nextboxnum;

		// 特殊模式无限制
		if (block.nextboxnum == 9 && box[block.nowboxnum][9].type == 0)
		{
			// 上一步在哪,则这一步在哪
			ma[0] = block.nowboxnum;
		}
		else if (block.nextboxnum == 9 && box[block.nowboxnum][9].type != 0)
		{
			// 上一步是某个大格的最后一步,则决策下一步下哪个大格
			// 初始化临时九宫格
			for (i = 0; i < 9; i++)
			{
				eat[i] = box[i][9].type;
			}
			// 人机决策数函数
			ma[0] = machine_check ();
		}
	}

	// 小格判断
	for (i = 0; i < 9; i++)
	{
		// 初始化临时九宫格
		eat[i] = box[ma[0]][i].type;
	}
	// 人机决策数函数
	ma[1] = machine_check ();
}



////////////////////////////// 准备进程源文件 //////////////////////////////



// 准备进程主循函数
void game::carry_prepare ()
{
	int i;
	// 鼠标定义
	ExMessage m;
	// 准备进程控制参数初始化
	int	exit_prepare = 0;
	// 绘制界面
	draw_scene_prepare ();
	// 主循开始
	while (exit_prepare == 0)
	{
		if (peekmessage (&m, EM_MOUSE | EM_KEY))
		{
			// 左键单击判断
			if (m.message == WM_LBUTTONDOWN)
			{
				// 判断是否点击了按钮,按钮状态是否为激活
				for (i = 0; i < 10; i++)
				{
					if (m.x > boxm[i].posx1 && m.y > boxm[i].posy1 && m.x < boxm[i].posx2 && m.y < boxm[i].posy2 && boxm[i].type == 0)
					{
						break;
					}
				}

				// 开始游戏按钮
				if (i == 0)
				{
					// 进入选择游戏模式界面
					// 按钮激活状态变更
					boxm[0].type = 1;
					boxm[1].type = 1;
					boxm[2].type = 1;
					boxm[9].type = 1;
					boxm[3].type = 0;
					boxm[4].type = 0;
					boxm[5].type = 0;
					boxm[6].type = 0;
					// 开始进程控制参数为 0,进入普通模式
					exit_start = 0;
				}
				// 主题更换按钮
				else if (i == 1)
				{
					// 进入主题更换界面
					// 按钮激活状态变更
					boxm[0].type = 1;
					boxm[1].type = 1;
					boxm[2].type = 1;
					boxm[9].type = 1;
					boxm[6].type = 0;
					boxm[7].type = 0;
					boxm[8].type = 0;
				}
				// 退出按钮
				else if (i == 2)
				{
					// 总进程控制参数置一,跳过开始进程
					exit_carry = 1;
					// 准备进程控制参数置一,结束主循
					exit_prepare = 1;
				}
				// 选择模式,进入游戏
				else if (i == 3 || i == 4 || i == 5)
				{
					// 普通模式加特殊模式,双人,人机先,人机后共 6 种
					// 开始进程控制参数有 0(普通模式)-1(特殊模式)
					// 游戏模式控制参数有 0(双人)1(人机先)2(人机后)
					mod_start = i - 3;
					// 准备进程控制参数置一,结束主循,进入开始进程
					exit_prepare = 1;
				}
				// 后退按钮
				else if (i == 6)
				{
					// 从主题选择界面返回
					// 按钮激活状态变更
					boxm[0].type = 0;
					boxm[1].type = 0;
					boxm[2].type = 0;
					boxm[9].type = 0;
					boxm[3].type = 1;
					boxm[4].type = 1;
					boxm[5].type = 1;
					boxm[6].type = 1;
					boxm[7].type = 1;
					boxm[8].type = 1;
				}
				// 模式一按钮
				else if (i == 7 && mod_scene == 2)
				{
					// 主题变换函数,颜色结构体变更
					mod_scene_change ();
				}
				// 模式二按钮
				else if (i == 8 && mod_scene == 1)
				{
					// 主题变换函数,颜色结构体变更
					mod_scene_change ();
				}
				// 特殊模式按钮
				else if (i == 9)
				{
					// 进入选择特殊模式界面
					// 按钮激活状态变更
					boxm[0].type = 1;
					boxm[1].type = 1;
					boxm[2].type = 1;
					boxm[9].type = 1;
					boxm[3].type = 0;
					boxm[4].type = 0;
					boxm[5].type = 0;
					boxm[6].type = 0;
					// 开始进程控制参数为 -1,进入特殊模式
					exit_start = -1;
				}
				if (i < 10 && exit_prepare == 0)
				{
					// 点击按钮后,根据按钮激活参数,重新绘制界面
					draw_scene_prepare ();
					FlushBatchDraw ();
				}
			}
		}
	}

}



// 准备进程初始化函数	
void game::initialization_prepare ()
{
	// 按钮设置初始化
	// 按钮数量参数初始化
	num_button = 10;

	// 按钮结构体参数初始化
	boxm[0].posx1 = 200; boxm[0].posy1 = 120; boxm[0].posx2 = 400; boxm[0].posy2 = 180; boxm[0].text = _T ("开始游戏"); boxm[0].type = 0;
	boxm[1].posx1 = 200; boxm[1].posy1 = 220; boxm[1].posx2 = 400; boxm[1].posy2 = 280; boxm[1].text = _T ("主题更换"); boxm[1].type = 0;
	boxm[9].posx1 = 200; boxm[9].posy1 = 320; boxm[9].posx2 = 400; boxm[9].posy2 = 380; boxm[9].text = _T ("特殊模式"); boxm[9].type = 0;
	boxm[2].posx1 = 200; boxm[2].posy1 = 420; boxm[2].posx2 = 400; boxm[2].posy2 = 480; boxm[2].text = _T ("退出"); boxm[2].type = 0;

	boxm[3].posx1 = 200; boxm[3].posy1 = 120; boxm[3].posx2 = 400; boxm[3].posy2 = 180; boxm[3].text = _T ("双人模式"); boxm[3].type = 1;
	boxm[4].posx1 = 200; boxm[4].posy1 = 220; boxm[4].posx2 = 400; boxm[4].posy2 = 280; boxm[4].text = _T ("人机先手"); boxm[4].type = 1;
	boxm[5].posx1 = 200; boxm[5].posy1 = 320; boxm[5].posx2 = 400; boxm[5].posy2 = 380; boxm[5].text = _T ("人机后手"); boxm[5].type = 1;

	boxm[6].posx1 = 200; boxm[6].posy1 = 420; boxm[6].posx2 = 400; boxm[6].posy2 = 480; boxm[6].text = _T ("后退"); boxm[6].type = 1;

	boxm[7].posx1 = 200; boxm[7].posy1 = 120; boxm[7].posx2 = 400; boxm[7].posy2 = 180; boxm[7].text = _T ("白天主题"); boxm[7].type = 1;
	boxm[8].posx1 = 200; boxm[8].posy1 = 220; boxm[8].posx2 = 400; boxm[8].posy2 = 280; boxm[8].text = _T ("夜间主题"); boxm[8].type = 1;
}



// 准备进程绘制函数
void game::draw_scene_prepare ()
{
	// 画布绘制
	setbkcolor (color.bkcolor[0]);
	cleardevice ();
	// 按钮绘制
	draw_button ();
	// 标题绘制
	draw_word (50, 200, 20);
	FlushBatchDraw ();
}



// 标题绘制函数
void game::draw_word (double size, int posx, int posy)
{
	int i, j;
	LPTSTR text;

	// 参数设置,填充透明
	setbkmode (TRANSPARENT);
	settextstyle (50, 20, _T ("Consolas"));
	text = _T ("嵌套井字棋");

	// 背景色的反色
	settextcolor (color.linecolor[1]);
	// 范围绘制,构造阴影
	for (i = posx - 3; i <= posx + 3; i++)
	{
		for (j = posy - 3; j <= posy + 3; j++)
		{
			outtextxy (i, j, text);
		}
	}

	// 背景色
	settextcolor (color.bkcolor[0]);
	// 在阴影中绘制
	outtextxy (posx, posy, text);

	// 恢复填充
	setbkmode (OPAQUE);
	FlushBatchDraw ();
}



////////////////////////////// 开始进程源文件 //////////////////////////////



// 开始进程主循函数
void game::carry_start ()
{
	// 鼠标定义
	ExMessage m;
	int i, j, k, x1, y1;
	// 记录初始化
	record.flag = 0;
	// 操作手参数重置
	block.type = 1;
	// 悔棋参数设置
	back_or_not = 0;
	// 绘制
	draw_scene_start ();
	// 嵌套模式
	while (exit_start == 0)
	{
		if (peekmessage (&m, EM_MOUSE | EM_KEY))
		{
			// 左键单击判断
			if (m.message == WM_LBUTTONDOWN || (mod_start == 1 && block.type == 1) || (mod_start == 2 && block.type == 2))
			{
				// 单击在棋盘范围
				if ((m.x < 475 && m.x > 25 && m.y > 25 && m.y < 475) || (mod_start == 1 && block.type == 1) || (mod_start == 2 && block.type == 2))
				{
					// 人机模式
					if ((mod_start == 1 && block.type == 1) || (mod_start == 2 && block.type == 2))
					{
						k = 0;
						machine ();
						i = ma[0];
						j = ma[1];
					}
					// 双人模式
					else if (m.x < 475 && m.x > 25 && m.y > 25 && m.y < 475)
					{
						// 判断大格内有无可以落子的地方
						// k = 0 无空位
						k = 0;
						for (i = 0; i < 9; i++)
						{
							if (box[block.nextboxnum][i].type == 0)
							{
								// k = 1 有空位,则必须下大格内
								k = 1;
								break;
							}
						}

						// 识别点击了哪个格子
						i = (m.x - 25) / 150 + (m.y - 25) / 150 * 3;
						x1 = m.x; y1 = m.y;
						while (x1 > 175)
						{
							x1 = x1 - 150;
						}
						while (y1 > 175)
						{
							y1 = y1 - 150;
						}
						j = (x1 - 25) / 50 + (y1 - 25) / 50 * 3;
					}

					// 有效点击
					if (((k == 1 && i == block.nextboxnum) || k == 0) && box[i][j].type == 0)
					{
						// 记录参数更新
						record.bigboxnum[record.flag] = i;
						record.smallboxnum[record.flag] = j;
						record.flag += 1;

						// 对小格子参数更新
						box[i][j].type = block.type;

						// 操作手参数更新
						block.nowboxnum = i;
						block.nextboxnum = j;

						// 闪烁显示
						// 绘制小棋子
						i = block.nowboxnum;
						j = block.nextboxnum;
						for (k = 0; k < 2; k++)
						{
							// 格子绘制
							setfillcolor (color.bkcolor[1]);
							setlinecolor (color.linecolor[1]);
							setlinestyle (PS_SOLID, 5);
							fillrectangle (box[i][j].posx, box[i][j].posy, box[i][j].posx + 50, box[i][j].posy + 50);
							FlushBatchDraw ();
							Sleep (200);

							// 棋子绘制
							if (box[i][j].type == 1) { draw_crosses (25, box[i][j].posx + 25, box[i][j].posy + 25); }
							else if (box[i][j].type == 2) { draw_circle (25, box[i][j].posx + 25, box[i][j].posy + 25); }
							FlushBatchDraw ();
							Sleep (200);
						}

						// 判断棋盘形势
						check_small (back_or_not);

						// 判断结束后,操作手参数更新
						block.type = block.type == 1 ? 2 : 1;

						// 绘制
						draw_scene_start ();

						// 判断棋盘是否填满
						k = 0;
						for (i = 0; i <= 8; i++)
						{
							for (j = 0; j <= 8; j++)
							{
								if (box[i][j].type == 0)
								{
									k = 1;
									break;
								}
							}
							if (k == 1)break;
						}

						// 最后一步未触发胜利,且棋盘已满
						if (exit_start == 0 && k == 0)
						{
							// 正常退出,胜者为后手方,返回开始选择函数
							MessageBox (hOut, _T ("圈圈后手胜利"), _T ("来自小豆子的提醒"), MB_OK);
							exit_start = 1;
						}
						// 胜负已分
						else if (box[9][9].type != 0)
						{
							// 正常退出,弹出胜者,返回开始选择函数
							if (block.type == 2)
							{
								MessageBox (hOut, _T ("叉叉十字架胜利"), _T ("来自小豆子的提醒"), MB_OK);
							}
							else
							{
								MessageBox (hOut, _T ("圈圈胜利"), _T ("来自小豆子的提醒"), MB_OK);
							}
							exit_start = 1;
						}
					}
				}
				else
				{
					// 判断是否点击了按钮
					for (i = 0; i < 4; i++)
					{
						if (m.x > boxm[i].posx1 && m.y > boxm[i].posy1 && m.x < boxm[i].posx2 && m.y < boxm[i].posy2 && boxm[i].type == 0)
						{
							break;
						}
					}

					// 重开按钮
					if (i == 0)
					{
						// 开始进程初始化函数,主要是格子参数的初始化
						initialization_start ();
						// 记录初始化
						record.flag = 0;
						// 操作手参数重置
						block.type = 1;
					}
					// 悔棋按钮
					else if (i == 1)
					{
						// 判断能不能悔棋
						if ((mod_start == 0 && record.flag > 0) || (record.flag > 1))
						{
							// 根据模式,判断悔几步,双人一步,人机两步
							if (mod_start == 0) { record.flag -= 1; }
							else { record.flag -= 2; }
							// 重置
							initialization_start ();
							// 从头推导
							// 悔棋参数设置
							back_or_not = 1;
							for (k = 0; k < record.flag; k++)
							{
								// 赋值
								i = record.bigboxnum[k];
								j = record.smallboxnum[k];
								// 对小格子参数更新
								box[i][j].type = block.type;
								// 操作手参数更新
								block.nowboxnum = i;
								block.nextboxnum = j;
								// 判断棋盘形势
								check_small (back_or_not);
								// 判断结束后,操作手参数更新
								block.type = block.type == 1 ? 2 : 1;
								// 悔棋,棋盘必不满
							}
							back_or_not = 0;
						}
					}
					// 主题切换按钮
					else if (i == 2)
					{
						mod_scene_change ();
					}
					// 返回按钮
					else if (i == 3)
					{
						exit_start = 1;
					}
					// 绘制
					draw_scene_start ();
				}
			}
		}
	}
	// 特殊模式
	while (exit_start == -1)
	{
		if (peekmessage (&m, EM_MOUSE | EM_KEY))
		{
			// 左键单击判断
			if (m.message == WM_LBUTTONDOWN || (mod_start == 1 && block.type == 1) || (mod_start == 2 && block.type == 2))
			{
				// 单击在棋盘范围
				if ((m.x < 475 && m.x > 25 && m.y > 25 && m.y < 475) || (mod_start == 1 && block.type == 1) || (mod_start == 2 && block.type == 2))
				{
					// 人机模式
					if ((mod_start == 1 && block.type == 1) || (mod_start == 2 && block.type == 2))
					{
						k = 0;
						machine ();
						i = ma[0];
						j = ma[1];
					}
					// 双人模式
					else if (m.x < 475 && m.x > 25 && m.y > 25 && m.y < 475)
					{
						// 识别点击了哪个格子
						i = (m.x - 25) / 150 + (m.y - 25) / 150 * 3;
						x1 = m.x; y1 = m.y;
						while (x1 > 175)
						{
							x1 = x1 - 150;
						}
						while (y1 > 175)
						{
							y1 = y1 - 150;
						}
						j = (x1 - 25) / 50 + (y1 - 25) / 50 * 3;
					}

					// 有效点击
					if (box[i][j].type == 0)
					{
						// 记录参数更新
						record.bigboxnum[record.flag] = i;
						record.smallboxnum[record.flag] = j;
						record.flag += 1;

						// 对小格子参数更新
						box[i][j].type = block.type;

						// 操作手参数更新
						block.nowboxnum = i;
						block.nextboxnum = j;

						// 闪烁显示
						// 绘制小棋子
						i = block.nowboxnum;
						j = block.nextboxnum;
						for (k = 0; k < 2; k++)
						{
							// 格子绘制
							setfillcolor (color.bkcolor[1]);
							setlinecolor (color.linecolor[1]);
							setlinestyle (PS_SOLID, 5);
							fillrectangle (box[i][j].posx, box[i][j].posy, box[i][j].posx + 50, box[i][j].posy + 50);
							FlushBatchDraw ();
							Sleep (200);

							// 棋子绘制
							if (box[i][j].type == 1) { draw_crosses (25, box[i][j].posx + 25, box[i][j].posy + 25); }
							else if (box[i][j].type == 2) { draw_circle (25, box[i][j].posx + 25, box[i][j].posy + 25); }
							FlushBatchDraw ();
							Sleep (200);
						}

						// 判断棋盘形势
						check_small (back_or_not);

						// 判断结束后,操作手参数更新
						block.type = block.type == 1 ? 2 : 1;

						// 绘制
						// 每次落子范围都是全局,所以这个参数一直为 9
						// 普通模式这个值只有第一次是 9,两个模式最大的区别
						block.nextboxnum = 9;
						draw_scene_start ();

						// 判断棋盘是否填满
						k = 0;
						for (i = 0; i <= 8; i++)
						{
							for (j = 0; j <= 8; j++)
							{
								if (box[i][j].type == 0)
								{
									k = 1;
									break;
								}
							}
							if (k == 1)break;
						}
						// 最后一步未触发胜利,且棋盘已满
						if (exit_start == -1 && k == 0)
						{
							// 正常退出,胜者为后手方,返回开始选择函数
							MessageBox (hOut, _T ("圈圈后手胜利"), _T ("来自小豆子的提醒"), MB_OK);
							exit_start = 1;
						}
						// 胜负已分
						else if (box[9][9].type != 0)
						{

							// 正常退出,弹出胜者,返回开始选择函数
							if (block.type == 2)
							{
								MessageBox (hOut, _T ("叉叉十字架胜利"), _T ("来自小豆子的提醒"), MB_OK);
							}
							else
							{
								MessageBox (hOut, _T ("圈圈胜利"), _T ("来自小豆子的提醒"), MB_OK);
							}
							exit_start = 1;
						}
					}
				}
				else
				{
					// 判断是否点击了按钮
					for (i = 0; i < 4; i++)
					{
						if (m.x > boxm[i].posx1 && m.y > boxm[i].posy1 && m.x < boxm[i].posx2 && m.y < boxm[i].posy2 && boxm[i].type == 0)
						{
							break;
						}
					}

					// 重开按钮
					if (i == 0)
					{
						// 开始模式初始化函数
						initialization_start ();
						// 记录初始化
						record.flag = 0;
						// 操作手参数重置
						block.type = 1;
					}
					// 悔棋按钮
					else if (i == 1)
					{
						// 判断能不能悔棋
						if ((mod_start == 0 && record.flag > 0) || (record.flag > 1))
						{
							// 根据模式,判断悔几步,双人一步,人机两步
							if (mod_start == 0) { record.flag -= 1; }
							else { record.flag -= 2; }
							// 重置
							initialization_start ();
							// 从头推导
							// 悔棋参数设置
							back_or_not = 1;
							for (k = 0; k < record.flag; k++)
							{
								// 赋值
								i = record.bigboxnum[k];
								j = record.smallboxnum[k];
								// 对小格子参数更新
								box[i][j].type = block.type;
								// 操作手参数更新
								block.nowboxnum = i;
								block.nextboxnum = j;
								// 判断棋盘形势
								check_small (back_or_not);
								// 判断结束后,操作手参数更新
								block.type = block.type == 1 ? 2 : 1;
								// 悔棋,棋盘必不满
							}
							back_or_not = 0;
						}
					}
					// 主题切换按钮
					else if (i == 2)
					{
						mod_scene_change ();
					}
					// 返回按钮
					else if (i == 3)
					{
						exit_start = 1;
					}
					// 绘制
					// 同理,这个值一直是 9
					block.nextboxnum = 9;
					draw_scene_start ();
				}
			}
		}
	}
}



// 开始进程初始化函数
void game::initialization_start ()
{
	int i, j;
	// 画布初始化
	setbkcolor (color.bkcolor[0]);
	cleardevice ();
	// 格子初始化,81 个小格子,9 个大格子,来保存 9 个小井字棋状态;9 个小格子,1 个大格子,来保存 1 个大井字棋状态。共 100 个
	for (i = 0; i <= 8; i++)
	{
		for (j = 0; j <= 8; j++)
		{
			// 81 个小格的初始化
			box[i][j].bigboxnum = i;
			box[i][j].smallboxnum = j;
			box[i][j].type = 0;
			box[i][j].posx = i % 3 * 150 + j % 3 * 50 + 25;
			box[i][j].posy = i / 3 * 150 + j / 3 * 50 + 25;
		}
		// 9 个大格的初始化
		box[i][9].type = 0;
	}

	// 第 10 个大格的初始化,为了解决第一次点击,操作手参数不足的问题,第一次点击完就没有效果了
	for (j = 0; j < 9; j++)
	{
		box[9][j].type = 1;
	}

	// 棋盘参数初始化,即超大格参数初始化
	box[9][9].type = 0;

	// 操作手参数初始化,第一次是 9
	block.nowboxnum = 4;
	block.nextboxnum = 9;
	block.type = 1;

	// 按钮设置初始化
	num_button = 4;

	boxm[0].posx1 = 500; boxm[0].posy1 = 120; boxm[0].posx2 = 580; boxm[0].posy2 = 180; boxm[0].text = _T ("重开"); boxm[0].type = 0;
	boxm[1].posx1 = 500; boxm[1].posy1 = 220; boxm[1].posx2 = 580; boxm[1].posy2 = 280; boxm[1].text = _T ("悔棋"); boxm[1].type = 0;
	boxm[2].posx1 = 500; boxm[2].posy1 = 320; boxm[2].posx2 = 580; boxm[2].posy2 = 380; boxm[2].text = _T ("主题"); boxm[2].type = 0;
	boxm[3].posx1 = 500; boxm[3].posy1 = 420; boxm[3].posx2 = 580; boxm[3].posy2 = 480; boxm[3].text = _T ("返回"); boxm[3].type = 0;

}



// 开始进程绘制函数
void game::draw_scene_start ()
{
	int i, j, k;

	// 对下次落子状态的判断
	k = 0;
	for (i = 0; i <= 8; i++)
	{
		if (box[block.nextboxnum][i].type == 0)
		{
			k = 1;
			break;
		}
	}

	// 绘制主背景
	setbkcolor (color.bkcolor[0]);
	cleardevice ();

	// 绘制下次落子范围
	setfillcolor (color.bkcolor[1]);
	setlinecolor (color.linecolor[2]);
	setlinestyle (PS_SOLID, 5);
	// 对应大格内有可以落子的地方,则必须在对应大格落子
	if (k == 1)
	{
		fillrectangle (box[block.nextboxnum][0].posx, box[block.nextboxnum][0].posy, box[block.nextboxnum][0].posx + 150, box[block.nextboxnum][0].posy + 150);
	}
	// 对应大格内无可以落子的地方,则随意落子
	else if (k == 0)
	{
		fillrectangle (box[0][0].posx, box[0][0].posy, box[0][0].posx + 450, box[0][0].posy + 450);
	}

	// 绘制小格子线
	setlinecolor (color.linecolor[0]);
	setlinestyle (PS_SOLID, 5);
	for (i = 0; i < 9; i += 3)
	{
		// 横线
		line (box[i][3].posx, box[i][3].posy, box[i + 2][5].posx + 50, box[i + 2][5].posy);
		line (box[i][6].posx, box[i][6].posy, box[i + 2][8].posx + 50, box[i + 2][8].posy);
		// 竖线
		line (box[i / 3][1].posx, box[i / 3][1].posy, box[i / 3 + 6][7].posx, box[i / 3 + 6][7].posy + 50);
		line (box[i / 3][2].posx, box[i / 3][2].posy, box[i / 3 + 6][8].posx, box[i / 3 + 6][8].posy + 50);
	}

	// 绘制大格子线
	setlinecolor (color.linecolor[1]);
	for (i = 0; i < 9; i += 3)
	{
		// 横线
		line (box[i][0].posx, box[i][0].posy, box[i + 2][2].posx + 50, box[i + 2][2].posy);
		// 竖线
		line (box[i / 3][0].posx, box[i / 3][0].posy, box[i / 3 + 6][6].posx, box[i / 3 + 6][6].posy + 50);
	}
	i = 6;
	// 横线
	line (box[i][0].posx, box[i][0].posy + 150, box[i + 2][2].posx + 50, box[i + 2][2].posy + 150);
	// 竖线
	line (box[i / 3][0].posx + 150, box[i / 3][0].posy, box[i / 3 + 6][6].posx + 150, box[i / 3 + 6][6].posy + 50);

	// 绘制小棋子
	for (i = 0; i <= 8; i++)
	{
		for (j = 0; j <= 8; j++)
		{
			if (box[i][j].type == 1) { draw_crosses (25, box[i][j].posx + 25, box[i][j].posy + 25); }
			else if (box[i][j].type == 2) { draw_circle (25, box[i][j].posx + 25, box[i][j].posy + 25); }
		}
	}

	// 绘制大棋子
	for (i = 0; i <= 8; i++)
	{
		if (box[i][9].type != 0 && box[i][9].type != 3)
		{
			// 格子绘制
			setfillcolor (color.bkcolor[0]);
			setlinecolor (color.linecolor[1]);
			setlinestyle (PS_SOLID, 5);
			fillrectangle (box[i][0].posx, box[i][0].posy, box[i][8].posx + 50, box[i][8].posy + 50);

			// 棋子绘制
			if (box[i][9].type == 1) { draw_crosses (75, box[i][4].posx + 25, box[i][4].posy + 25); }
			else if (box[i][9].type == 2) { draw_circle (75, box[i][4].posx + 25, box[i][4].posy + 25); }
		}

	}

	// 绘制超大棋子
	if (box[9][9].type != 0)
	{
		// 格子绘制
		setfillcolor (color.bkcolor[0]);
		setlinecolor (color.linecolor[1]);
		setlinestyle (PS_SOLID, 5);
		fillrectangle (box[0][0].posx, box[0][0].posy, box[8][8].posx + 50, box[8][8].posy + 50);

		// 棋子绘制
		if (box[9][9].type == 1) { draw_crosses (225, box[4][4].posx + 25, box[4][4].posy + 25); }
		else if (box[9][9].type == 2) { draw_circle (225, box[4][4].posx + 25, box[4][4].posy + 25); }
	}

	// 绘制按钮
	draw_button ();

	FlushBatchDraw ();
}

添加评论