mesoncold

分享让我快乐

五子棋

感谢慢羊羊数字拼图游戏,我用那篇文章初步学了 EasyX 后简单地完成了五子棋游戏的初始的骨架。

参考了陈可佳博弈五子棋,看懂了代码,可是 AI 算法的架子骨摆在那里,我也没做实际上的修改,就只能做些锦上添花的工作,比如

  1. 一些关键的变量不采用魔数,而封装成变量——增强可读性、可拓展性
  2. 不使用全局变量,而是全部采用类来封装
  3. 是封装了单选框类、按钮类、棋盘类
  4. 将一些复杂的小任务封装成函数——增强可读性
  5. 将架构设计得方便将来拓展更多的 AI——增强可拓展性

画面如下:

图 1 玩家对玩家

图 2 AI 对 AI

可以看到,有彩色的提示框,分别可以提示上一次落子的位置以及目前鼠标的位置。红黄绿蓝是来自谷歌图标颜色的灵感。

你可以自己下棋,也可以下到一半选择 AI 和你一起下,甚至可以让 AI 自己下棋!

虽然有点慢,陈可佳说用了 4 层,我没改。不过其实 3 层或者 2 层应该也足够用,你可以在

if (layer < 3)

这句修改层数。

最后感谢慢羊羊对我文章格式的指导。

源码如下,有问题加我 QQ: 782429852。

/////////////////////////////////////////////////////////
// 程序名称:五子棋
// 编译环境:VS 2019,EasyX_20210224
// 作    者:安生晓
// 最后修改:2021-5-15
//
#include <easyx.h>
#include <time.h>
#include <conio.h>
#include <iostream>
#include <vector>

// 位置
struct Position 
{
	int x;		// 0 <= x <= 14
	int y;		// 0 <= y <= 14
	int score;  // 分值,用于 AI 估分
	bool operator==(const Position& b) 
	{
		return x == b.x && y == b.y;
	}
};

// 带文字的按钮类
class TextButton 
{
public:
	TextButton(int x, int y, LPCTSTR str, COLORREF background_color = RGB(255, 205, 150)) :x(x), y(y), str(str), background_color(background_color) {};
	static const int left = 5;
	static const int top = 5;
	static const int roundRadius = 5;
	int x;
	int y;
	LPCTSTR str;
	COLORREF background_color;
	bool isIn(int point_x, int point_y);	// 判断点是否在按钮范围内
	void draw();							// 绘制按钮
};


bool TextButton::isIn(int point_x, int point_y) 
{
	if (point_x >= x && point_x <= x + textwidth(str) + 2 * left && point_y >= y && point_y <= y + textheight(str) + 2 * top)
		return true;
	else
		return false;
}

void TextButton::draw() 
{
	auto pstyle = std::make_shared<LINESTYLE>();
	getlinestyle(pstyle.get());
	setlinestyle(PS_SOLID, 1);
	COLORREF tempColor = getfillcolor();
	setfillcolor(background_color);         // 填充颜色设置
	fillroundrect(x, y, x + textwidth(str) + 2 * left, y + textheight(str) + 2 * top, roundRadius, roundRadius);
	setfillcolor(tempColor);
	setlinestyle(pstyle.get());
	outtextxy(x + left, y + top, str);
}

// 单选框类
class Radio 
{
public:
	Radio(int x, int y, int value) :x(x), y(y), value(value) {};
	static const  int radius = 6;
	int x;
	int y;
	int value;
	bool isIn(int point_x, int point_y);	// 判断点是否在单选框范围内
	void draw(int groupValue);				// 绘制单选框
};

bool Radio::isIn(int point_x, int point_y) 
{
	if (point_x >= x - radius && point_x <= x + radius && point_y >= y - radius && point_y <= y + radius)
		return true;
	else
		return false;
}

void Radio::draw(int groupValue) 
{
	auto pstyle = std::make_shared<LINESTYLE>();
	getlinestyle(pstyle.get());
	setlinestyle(PS_SOLID, 1);
	circle(x, y, radius);
	setlinestyle(pstyle.get());

	if (value == groupValue) {
		COLORREF tempColor = getfillcolor();
		setfillcolor(GREEN);
		fillcircle(x, y, radius / 3);
		setfillcolor(tempColor);
	}
}


// 棋盘类
class ChessBoard 
{
public:
	bool	is_black = true;										// 轮到黑子下棋还是白子
	int		who_win = 0;											// 1 为黑子获胜,2 为白子获胜,0 为平局
	std::vector<Position> black_chesses = std::vector<Position>(0);	// 存储已经下过的黑子坐标,方便检查判定
	std::vector<Position> white_chesses = std::vector<Position>(0);	// 存储已经下过的白子坐标,方便检查判定
	int		g_Map[15][15] = {};										// 棋盘,1 为黑子,2 为白子,0 为无子
	COLORREF background_color = RGB(255, 205, 150);					// 棋盘背景色
	int left_padding = 30;											// 棋盘左边距
	int top_padding = 33;											// 棋盘上边距
	int spacing = 40;												// 棋盘格子间距
	Position mouse_position = Position{ -1,-1 };					// 鼠标位置
	// 两个单选框组的选择变量
	int blackRadioGroupValue = 0;
	int whiteRadioGroupValue = 0;
	// 0-玩家		2-人机(决策树算法)
	Radio player_black = Radio(left_padding + 15 * spacing + 20, top_padding + 5 * spacing, 0);
	Radio DT_black = Radio(left_padding + 15 * spacing + 20, top_padding + 5 * spacing + 50, 2);

	Radio player_white = Radio(left_padding + 18 * spacing + 20, top_padding + 5 * spacing, 0);
	Radio DT_white = Radio(left_padding + 18 * spacing + 20, top_padding + 5 * spacing + 50, 2);

	TextButton initButton = TextButton(left_padding + 16 * spacing + 20, top_padding + 5 * spacing + 75, L"重新开始");

	void init();														// 初始化
	void draw();														// 绘制游戏界面
	void drawPromptBox(const Position& p);								// 绘制提示框
	bool checkchess(Position& p, bool is_black, int xdiff, int ydiff);  // 检查是否满足获胜条件
	bool oneWin();														// 判断是否有一方胜利
	void play();														// 开始游戏
	
	// 决策树
	void DT();
	Position findBestPosition(bool is_black, int layer);
	bool hasNeighbour(int x, int y);
	bool firstRandSet();
	int dx[4]{ 1,0,1,1 }; // - | \ / 四个方向
	int dy[4]{ 0,1,1,-1 };
	int Score[3][5] = //评分表
	{
		{ 0, 80, 250, 500, 500 }, // 防守0子
		{ 0, 0,  80,  250, 500 }, // 防守1子
		{ 0, 0,  0,   80,  500 }  // 防守2子
	};
	int MAXxs[361] = {};	//最优x坐标
	int MAXys[361] = {};	//最优y坐标
	int mylength = 0;		//最优解数
};

void ChessBoard::init() 
{
	// 变量初始化
	is_black = true;
	who_win = 0;
	black_chesses = std::vector<Position>(0);
	white_chesses = std::vector<Position>(0);
	for (int i = 0; i < 15; i++)
	{
		for (int j = 0; j < 15; j++)
		{
			g_Map[i][j] = 0;
		}
	}
	// 清空鼠标缓冲区
	FlushMouseMsgBuffer();
}

void ChessBoard::drawPromptBox(const Position& p) 
{
	// 绘制有四种颜色的提示框
	COLORREF linecolor = getlinecolor();
	int half_spacing = spacing / 2;
	int length = spacing / 3;
	int x = p.x * spacing + left_padding;
	int y = p.y * spacing + top_padding;
	setlinestyle(PS_SOLID, 2);
	setlinecolor(RED);
	// 左上角
	line(x - half_spacing, y - half_spacing, x - half_spacing, y - half_spacing + length);	// 横
	line(x - half_spacing, y - half_spacing, x - half_spacing + length, y - half_spacing);	// 竖
	setlinecolor(YELLOW);
	// 右上角
	line(x + half_spacing, y - half_spacing, x + half_spacing, y - half_spacing + length);	// 横
	line(x + half_spacing, y - half_spacing, x + half_spacing - length, y - half_spacing);	// 竖
	setlinecolor(GREEN);
	// 右上角
	line(x - half_spacing, y + half_spacing, x - half_spacing, y + half_spacing - length);	// 横
	line(x - half_spacing, y + half_spacing, x - half_spacing + length, y + half_spacing);	// 竖
	setlinecolor(BLUE);
	// 右下角
	line(x + half_spacing, y + half_spacing, x + half_spacing, y + half_spacing - length);	// 横
	line(x + half_spacing, y + half_spacing, x + half_spacing - length, y + half_spacing);	// 竖
	setlinecolor(linecolor);
}

void ChessBoard::draw()
{
	BeginBatchDraw();						// 开始批量绘制,防止闪烁用的
	setlinestyle(PS_SOLID, 2);
	cleardevice();							// 清屏
	// 画背景
	setfillcolor(background_color);         // 填充颜色设置
	solidrectangle(0, 0, 14 * spacing + left_padding * 2, 14 * spacing + top_padding * 2);
	settextcolor(BLACK);
	int number = 0;
	// 坐标(数值)
	TCHAR strnum[15][3] = { _T("1"),_T("2") ,_T("3") ,_T("4"),_T("5") ,_T("6") ,_T("7"),_T("8"),_T("9"),_T("10"), _T("11"),_T("12") ,_T("13") ,_T("14"),_T("15") };
	// 坐标(字母)
	TCHAR strabc[15][3] = { _T("A"),_T("B") ,_T("C") ,_T("D"),_T("E") ,_T("F") ,_T("G"),_T("H"),_T("I"),_T("J"), _T("K"),_T("L") ,_T("M") ,_T("N"),_T("O") };
	// 画坐标
	for (int i = 0; i < 15; i++)
	{
		outtextxy(left_padding + number - 6, top_padding - 23, strnum[i]);
		outtextxy(left_padding - 14, top_padding + number - 6, strabc[i]);
		number += spacing;
	}
	setlinecolor(BLACK);
	for (int x = 0; x < 15; x++)				// 画横线
		line(left_padding, x * spacing + top_padding, 14 * spacing + left_padding, x * spacing + top_padding);
	for (int y = 0; y < 15; y++)				// 画竖线
		line(y * spacing + left_padding, top_padding, y * spacing + left_padding, 14 * spacing + top_padding);
	// 画五颗星位
	for (int i : {3, 7, 11})
	{
		for (int j : {3, 7, 11})
		{
			setfillcolor(BLACK);
			fillcircle(i * spacing + left_padding, j * spacing + top_padding, 4);
		}
	}
	for (int x = 0; x < 15; x++)				// 画棋子
	{
		for (int y = 0; y < 15; y++) {
			if (g_Map[x][y] == 1) {
				setfillcolor(BLACK);
				fillcircle(x * spacing + left_padding, y * spacing + top_padding, 15);
			}
			else if (g_Map[x][y] == 2) {
				setfillcolor(WHITE);
				fillcircle(x * spacing + left_padding, y * spacing + top_padding, 15);
			}
		}
	}
	// 最后一颗棋子绘制提示边框
	if (black_chesses.size() == white_chesses.size()) 
	{
		if (!white_chesses.empty()) 
		{
			drawPromptBox(white_chesses.back());
		}
	}
	else 
	{
		if (!black_chesses.empty()) 
		{
			drawPromptBox(black_chesses.back());
		}
	}
	if (mouse_position.x != -1) 
	{
		drawPromptBox(mouse_position);
	}

	LOGFONT* font = new LOGFONT();
	gettextstyle(font);
	settextstyle(30, 0, L"楷体", 0, 0, 4, false, false, false, 0, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH);
	settextcolor(BLACK);
	outtextxy(15 * spacing + 2 * left_padding, top_padding, L"五子棋");
	settextstyle(font);

	outtextxy(player_black.x + Radio::radius + 5, player_black.y - Radio::radius - 3, L"玩家A");
	outtextxy(player_black.x + Radio::radius + 10 + textwidth(L"五子棋"), player_black.y - Radio::radius - 3, L"玩家B");
	outtextxy(DT_black.x + Radio::radius + 30, DT_black.y - Radio::radius - 3, L"决策树");
	// 绘制黑方单选框
	player_black.draw(blackRadioGroupValue);
	DT_black.draw(blackRadioGroupValue);
	// 绘制白方单选框
	player_white.draw(whiteRadioGroupValue);
	DT_white.draw(whiteRadioGroupValue);
	// 绘制重新开始按钮
	initButton.draw();

	EndBatchDraw(); // 结束批量绘制
}

// xdiff 和 ydiff 只在-1,0,1中取。可以用来表示横、竖、左斜、右斜方向
bool ChessBoard::checkchess(Position& p, bool is_black, int xdiff, int ydiff) 
{
	Position temp = Position{};
	// std::cout << "p.x = " << p.x << ", p.y = " << p.y << std::endl;
	for (int i = 1; i < 5; i++)		// 我这是是反方向判断的,如果你觉得不爽可以通过修改+-号修改判断的方向 
	{
		temp.x = p.x - xdiff * i;
		temp.y = p.y - ydiff * i;
		if (is_black) 
		{
			if (find(black_chesses.begin(), black_chesses.end(), temp) == black_chesses.end()) 
			{
				return false;
			}
		}
		else 
		{
			if (find(white_chesses.begin(), white_chesses.end(), temp) == white_chesses.end()) 
			{
				return false;
			}
		}
	}
	return true;
}

bool ChessBoard::oneWin()
{
	for (Position& p : black_chesses) 
	{
		if (checkchess(p, true, 0, 1) || checkchess(p, true, 1, 0) || checkchess(p, true, 1, 1) || checkchess(p, true, -1, 1))
		{
			who_win = 1; return true;
		}
	}
	for (Position& p : white_chesses) 
	{
		if (checkchess(p, false, 0, 1) || checkchess(p, false, 1, 0) || checkchess(p, false, 1, 1) || checkchess(p, false, -1, 1))
		{
			who_win = 2; return true;
		}
	}
	// std::cout << "没有胜利" << std::endl;
	return false;
}

void ChessBoard::play()
{
	MOUSEMSG msg;
	while (black_chesses.size() < 113)		// 游戏主循环
	{
		msg = GetMouseMsg();				// 获取鼠标信息
		if (msg.mkLButton) {				// 检测是否点击单选框或重新开始按钮
			if (player_black.isIn(msg.x, msg.y)) 
			{
				blackRadioGroupValue = player_black.value; continue;
			}
			else if (DT_black.isIn(msg.x, msg.y)) 
			{
				blackRadioGroupValue = DT_black.value; continue;
			}
			else if (player_white.isIn(msg.x, msg.y)) 
			{
				whiteRadioGroupValue = player_white.value; continue;
			}
			else if (DT_white.isIn(msg.x, msg.y)) 
			{
				whiteRadioGroupValue = DT_white.value; continue;
			}
			else if (initButton.isIn(msg.x, msg.y)) 
			{
				init(); continue;
			}
		}
		if (is_black) 
		{
			switch (blackRadioGroupValue)
			{
			case 0:
				if (msg.x >= left_padding && msg.x < 14 * spacing + left_padding && msg.y >= top_padding && msg.y < 14 * spacing + top_padding)
				{
					int x = (msg.x - left_padding + spacing / 2) / spacing;
					int y = (msg.y - top_padding + spacing / 2) / spacing;
					mouse_position.x = x;
					mouse_position.y = y;
					if (msg.mkLButton)
					{
						if (g_Map[x][y] == 0) 
						{
							g_Map[x][y] = 1;
							black_chesses.emplace_back(Position{ x,y });
							is_black = !is_black;
							if (!oneWin());
							else { draw(); return; }
						}
					}
				}
				else 
				{
					mouse_position.x = -1;
					mouse_position.y = -1;
				}
				break;
			case 2:
				if (!firstRandSet()) 
				{
					DT();
				}
				if (!oneWin());
				else { draw(); return; }
				break;
			default:
				is_black = !is_black;
				break;
			}
		}
		else {
			switch (whiteRadioGroupValue)
			{
			case 0:
				if (msg.x >= left_padding && msg.x < 14 * spacing + left_padding && msg.y >= top_padding && msg.y < 14 * spacing + top_padding)
				{
					int x = (msg.x - left_padding + spacing / 2) / spacing;
					int y = (msg.y - top_padding + spacing / 2) / spacing;
					mouse_position.x = x;
					mouse_position.y = y;
					if (msg.mkLButton)
					{
						if (g_Map[x][y] == 0) 
						{
							g_Map[x][y] = 2;
							white_chesses.emplace_back(Position{ x,y });
							is_black = !is_black;
							if (!oneWin());
							else { draw(); return; }
						}
					}
				}
				else 
				{
					mouse_position.x = -1;
					mouse_position.y = -1;
				}
				break;
			case 2:
				if (!firstRandSet()) 
				{
					DT();
				}
				if (!oneWin());
				else { draw(); return; }
				break;
			default:
				is_black = !is_black;
				break;
			}
		}
		draw();
		// Sleep(10);
	}
}

bool ChessBoard::firstRandSet()
{	// 第一步随便下
	if (black_chesses.empty() && white_chesses.empty())
	{
		srand(0);
		int x = rand() % 15;
		int y = rand() % 15;
		g_Map[x][y] = is_black ? 1 : 2;
		if (is_black) 
		{
			black_chesses.emplace_back(Position{ x,y });
		}
		else
		{
			white_chesses.emplace_back(Position{ x,y });
		}
		is_black = !is_black;
		return true;
	}
	return false;
}

// DT
void ChessBoard::DT() 
{
	Position best = findBestPosition(is_black, 0);	// 寻找最佳位置
	if (best.x == -1) { return; }
	g_Map[best.x][best.y] = is_black ? 1 : 2;		// 下在最佳位置
	if (is_black) 
	{
		black_chesses.emplace_back(best);
	}
	else
	{
		white_chesses.emplace_back(best);
	}
	is_black = !is_black;
}

bool ChessBoard::hasNeighbour(int x, int y) 
{
	for (int i = 0; i < 4; i++)
	{
		if (g_Map[x + dx[i]][y + dy[i]] != 0 || g_Map[x - dx[i]][y - dy[i]] != 0)
			return true;
	}
	return false;
}

Position ChessBoard::findBestPosition(bool is_black, int layer) // layer 层数,0/1/2/3一共四层
{
	if (layer == 0)	mylength = 0;
	int MAXnumber = INT_MIN;    //最佳分数
	for (int i = 0; i < 15; i++) 
	{
		for (int j = 0; j < 15; j++) 
		{
			if (g_Map[i][j] == 0) 
			{
				//遍历每一个空位置
				int length;        //当前方向长度
				int emeny;         //当前方向敌子
				int nowi = 0;      //现在遍历到的y坐标
				int nowj = 0;      //现在遍历到的x坐标
				int thescore = 0;  //这个位置的初始分数
				if (!hasNeighbour(i, j))
					continue;		//如果周围没有棋子,就不用递归了
				// 自己
				g_Map[i][j] = is_black ? 1 : 2;// 尝试下在这里
				// 4条直线,每条直线有上下两个方向,所以一共是八个方向
				for (int k = 0; k < 4; k++)
				{
					length = 0;
					emeny = 0;
					// 直线的一个方向
					nowi = i;
					nowj = j;
					while (nowi <= 14 && nowj <= 14 && nowi >= 0 && nowj >= 0 && g_Map[nowi][nowj] == (is_black ? 1 : 2))
					{
						length++;
						nowj += dy[k];
						nowi += dx[k];
					}
					if (nowi < 0 || nowj < 0 || nowi > 14 || nowj > 14 || g_Map[nowi][nowj] == (is_black ? 2 : 1))
					{
						emeny++;
					}
					// 直线的另一个方向
					nowi = i;
					nowj = j;
					while (nowi <= 14 && nowj <= 14 && nowi >= 0 && nowj >= 0 && g_Map[nowi][nowj] == (is_black ? 1 : 2))
					{
						length++;
						nowj -= dy[k];
						nowi -= dx[k];
					}
					if (nowi < 0 || nowj < 0 || nowi > 14 || nowj > 14 || g_Map[nowi][nowj] == (is_black ? 2 : 1))
					{
						emeny++;
					}
					length -= 2;//判断长度
					if (length > 4)
					{
						length = 4;
					}
					if (Score[emeny][length] == 500)
					{
						//己方胜利,结束递归
						g_Map[i][j] = 0;
						return{ i,j,Score[emeny][length] };
					}
					thescore += Score[emeny][length];
					length = 0;
					emeny = 0;
				}
				//敌人(原理同上)
				g_Map[i][j] = is_black ? 2 : 1;
				for (int k = 0; k < 4; k++)
				{
					length = 0;
					emeny = 0;
					nowi = i;
					nowj = j;
					while (nowi <= 14 && nowj <= 14 && nowi >= 0 && nowj >= 0 && g_Map[nowi][nowj] == (is_black ? 2 : 1))
					{
						length++;
						nowj += dy[k];
						nowi += dx[k];
					}
					if (nowi < 0 || nowj < 0 || nowi > 14 || nowj > 14 || g_Map[nowi][nowj] == (is_black ? 1 : 2))
					{
						emeny++;
					}
					nowi = i;
					nowj = j;
					while (nowi <= 14 && nowj <= 14 && nowi >= 0 && nowj >= 0 && g_Map[nowi][nowj] == (is_black ? 2 : 1))
					{
						length++;
						nowj -= dy[k];
						nowi -= dx[k];
					}
					if (nowi < 0 || nowj < 0 || nowi > 14 || nowj > 14 || g_Map[nowi][nowj] == (is_black ? 1 : 2))
					{
						emeny++;
					}
					length -= 2;
					if (length > 4)
					{
						length = 4;
					}
					if (Score[emeny][length] == 500)
					{
						g_Map[i][j] = 0;
						return{ i,j,Score[emeny][length] };
					}
					thescore += Score[emeny][length];
					length = 0;
					emeny = 0;
				}
				g_Map[i][j] = 0;
				// 如果已经比最高分数小,就没必要递归了
				if (thescore >= MAXnumber)
				{
					if (layer < 3)
					{
						// 只能找4层,否则时间太长
						g_Map[i][j] = is_black ? 1 : 2;
						// 递归寻找对方分数
						int nowScore = thescore - findBestPosition(is_black, layer + 1).score;// 递归求出这个位置的分值
						g_Map[i][j] = 0;
						if (nowScore > MAXnumber)
						{
							// 比最高分值大
							MAXnumber = nowScore;
							if (layer == 0)
							{
								// 第一层
								mylength = 0;	// 清空数组
							}
						}
						if (layer == 0)
						{
							// 第一层
							if (nowScore >= MAXnumber)
							{
								// 把当前位置加入数组
								MAXxs[mylength] = i;
								MAXys[mylength] = j;
								mylength++;
							}
						}
					}
					else 
					{
						// 如果递归到了最后一层
						if (thescore > MAXnumber)
						{
							// 直接更新
							MAXnumber = thescore;
						}
					}
				}
			}
		}
	}
	if (layer == 0)
	{
		if (mylength != 0) 
		{
			// 第一层,在最优解列表里随机找一个落子位置
			int mynum = rand() % mylength;
			return { MAXxs[mynum],MAXys[mynum],MAXnumber };
		}
		else 
		{
			// 输了,找不到最优解,搜索能否随机落子
			for (int i = 0; i < 15; i++)
			{
				for (int j = 0; j < 15; j++)
				{
					if (g_Map[i][j] == 0) {
						MAXxs[mylength] = i;
						MAXxs[mylength] = j;
						mylength++;
					}
				}
			}
			int mynum = rand() % mylength;	// 不会出现 mylength = 0 的情况,因为只要棋盘满了就会自动退出。
			return { MAXxs[mynum],MAXys[mynum],MAXnumber };
		}
	}
	// 其他层(之所以返回 x = -2, y = -2 是因为其他层不需要返回位置)
	return { -2,-2,MAXnumber };
}

int main()
{
	HWND wnd = initgraph(800, 620);		// 创建绘图窗口
	SetWindowText(wnd, L"五子棋");		//设置窗口的标题
	setbkcolor(WHITE);
	setbkmode(TRANSPARENT);				// 设置透明文字输出背景
	ChessBoard chessBoard;
	do
	{
		chessBoard.init();				// 初始化
		chessBoard.play();				// 开始游戏
	} while (MessageBox(
		wnd,
		chessBoard.who_win == 1 ? L"恭喜黑方胜利!\n重来一局吗?" : (chessBoard.who_win == 2 ? L"恭喜白方胜利!\n重来一局吗?" : L"居然是平局,太妙了\n重来一局吗?"),
		chessBoard.who_win == 1 ? L"黑子胜利" : (chessBoard.who_win == 2 ? L"白子胜利" : L"平局"),
		MB_YESNO | MB_ICONQUESTION) == IDYES);
	closegraph();	// 关闭绘图窗口(但不会关闭控制台,也就是说你如果用cout输出,这一步之后是可以看得到的控制台)
	return 0;
}

添加评论