AI五子棋——超强改进版本

这篇具有很好参考价值的文章主要介绍了AI五子棋——超强改进版本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

AI五子棋的改进版本来啦~~
我们发现,原版的AI五子棋如果调成4的话,非常之慢!!下面给出原版的链接

AI五子棋(原版本)

因此我对其进行了改进,由于正常人下五子棋不会东下一颗棋,西下一颗棋。
因此我们可以大幅度缩小搜索的范围,只要搜索已经下了的棋子的周围就可以了(2×2或3×3)。
下面的程序会是2×2的4,尽管还是有点慢,但相比原程序快很多。

另外,关于人机强度、人机耗时的修改,我放在原版的链接里了

我们可以做一个对比:让这两个程序同时运行4,会发现:改进后的程序用了1:17下了一步,但是原版的用了3:04(4GB内存,i3cpu情况下)

#include<iostream>
#include<vector>
#include<array>
#include<fstream>
#include<algorithm>
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
int minx=14,miny=14,maxx=0,maxy=0;
void color(int x) {
	switch(x) {
		case  1:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_RED  );
			break;
		case  2:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_BLUE );
			break;
		case  3:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_GREEN);
			break;
		case  4:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_RED  |FOREGROUND_BLUE );
			break;
		case  5:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_RED  |FOREGROUND_GREEN);
			break;
		case  6:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_BLUE |FOREGROUND_GREEN);
			break;
		case  7:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_GREEN|FOREGROUND_BLUE |FOREGROUND_RED);
			break;
		default:
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY |FOREGROUND_GREEN|FOREGROUND_BLUE |FOREGROUND_RED);
			break;
	}
}
class GameTree {
	public:
		class Node {
			public:
				enum State :uint8_t/*节省内存*/ { SPACE, BLACK, WHITE };
			private:
				friend class GameTree;
				static const uint8_t BOARDSIZE = 15;
				int value;//叶节点表示估价函数的结果,MAX节点表示α值,MIN节点表示β值
				int evaluateValue;//估价函数计算的结果,用于优化
				unsigned short depth;//深度
				uint8_t lastX, lastY;//上一次落子的xy坐标
				Node* father;//父亲节点
				std::vector<Node*> children;//子节点
				State **board;//棋盘
				int Evaluate()const { //估价函数
					static const auto EvaluateSome = [](State **board, uint8_t beginX, uint8_t endX, uint8_t beginY, uint8_t endY) {
						static const auto EvaluateList = [](const std::array<State, 5>& v) { //假定自己是白方
							//判断颜色并记录棋子个数
							State lastColor = SPACE;
							uint8_t bitList = 0;//将棋链以二进制形式表示,如01101
							for (State i : v) {
								if (i != lastColor) {
									if (lastColor == SPACE)//遇到的第一个棋子
										lastColor = i;
									else//有不同颜色的棋子
										return 0;
								}
								if (i != SPACE)
									bitList = bitList * 2 + 1;
							}
							int result = 0;
							switch (bitList) {
								case 0://00000
									result = 0;
									break;
								case 1://00001
								case 2://00010
								case 4://00100
								case 8://01000
								case 16://10000
									result = 5;
									break;
								case 3://00011
								case 24://11000
									result = 80;
									break;
								case 6://00110
								case 12://01100
									result = 100;
									break;
								case 10://01010
									result = 80;
									break;
								case 5://00101
								case 20://10100
									result = 60;
									break;
								case 9://01001
								case 18://10010
									result = 20;
									break;
								case 17://10001
									result = 10;
									break;
								case 7://00111
								case 28://11100
									result = 800;
									break;
								case 14://01110
									result = 1000;
									break;
								case 13://01101
								case 26://11010
								case 11://01011
								case 22://10110
									result = 800;
									break;
								case 19://10011
								case 21://10101
								case 25://11001
									result = 600;
									break;
								case 15://01111
								case 30://11110
									result = 10000;
									break;
								case 29://11101
								case 23://10111
									result = 8000;
									break;
								case 27://11011
									result = 6000;
									break;
								case 31://11111
									return lastColor == WHITE ? INT_MAX : INT_MIN;
							}
							return lastColor == WHITE ? result : -result;//对手返回负值,我方返回正值
						};
						int result = 0;
						for (uint8_t i = beginX; i < endX; i++) { //分别从四个方向判断
							for (uint8_t j = beginY; j < endY; j++) {
								if (j + 4 < endY) {
									std::array<State, 5>v;
									for (uint8_t k = 0; k < 5; k++)
										v[k] = board[i][j + k];
									const int t = EvaluateList(v);
									if (t == INT_MAX || t == INT_MIN)//决出胜负直接返回
										return t;
									result += t;
								}
								if (i + 4 < endX) {
									std::array<State, 5>v;
									for (uint8_t k = 0; k < 5; k++)
										v[k] = board[i + k][j];
									const int t = EvaluateList(v);
									if (t == INT_MAX || t == INT_MIN)//决出胜负直接返回
										return t;
									result += t;
								}
								if (i + 4 < endX && j + 4 < endY) {
									std::array<State, 5>v;
									for (uint8_t k = 0; k < 5; k++)
										v[k] = board[i + k][j + k];
									const int t = EvaluateList(v);
									if (t == INT_MAX || t == INT_MIN)//决出胜负直接返回
										return t;
									result += t;
								}
								if (i + 4 < endX && j >= 4) {
									std::array<State, 5>v;
									for (uint8_t k = 0; k < 5; k++)
										v[k] = board[i + k][j - k];
									const int t = EvaluateList(v);
									if (t == INT_MAX || t == INT_MIN)//决出胜负直接返回
										return t;
									result += t;
								}
							}
						}
						return result;
					};
					uint8_t beginX, endX, beginY, endY;
					if (lastX <= 5)
						beginX = 0;
					else
						beginX = lastX - 5;
					endX = lastX + 5;
					if (endX > BOARDSIZE)
						endX = BOARDSIZE;
					if (lastY <= 5)
						beginY = 0;
					else
						beginY = lastY - 5;
					endY = lastY + 5;
					if (endY > BOARDSIZE)
						endY = BOARDSIZE;
					const int t = EvaluateSome(board, beginX, endX, beginY, endY);
					if (t == INT_MAX || t == INT_MIN)//决出胜负直接返回
						return t;
					return  t - EvaluateSome(father->board, beginX, endX, beginY, endY) + father->evaluateValue;
				}

			public:
				//非根节点的构造函数
				Node(Node* nf, uint8_t x, uint8_t y) :father(nf), lastX(x), lastY(y), depth(nf->depth + 1), value(0), board(new State* [BOARDSIZE]) {
					father->children.push_back(this);
					for (int i = 0; i < BOARDSIZE; ++i) {
						board[i] = new State[BOARDSIZE];
						memcpy(board[i], father->board[i], BOARDSIZE * sizeof(State));
					}
					board[lastX][lastY] = IsMaxNode() ? BLACK : WHITE;
					evaluateValue = Evaluate();
					for (int i = 0; i < BOARDSIZE; ++i) {
						delete[] board[i];
					}
					delete[] board;
					board = nullptr;
				}
				//根节点的构造函数
				Node(int _depth, uint8_t x, uint8_t y) :father(nullptr), depth(_depth), lastX(x), lastY(y), value(0),evaluateValue(0),board(new State*[BOARDSIZE]) {
					for (int i = 0; i < BOARDSIZE; ++i) {
						board[i] = new State[BOARDSIZE];
						memset(board[i], 0, BOARDSIZE * sizeof(State));
					}
					board[x][y] = IsMaxNode() ? BLACK : WHITE;
				}
				inline int GetEvaluateValue()const {
					return evaluateValue;
				}
				inline bool IsMaxNode()const { //默认计算机后手
					return depth & 1u;//相当于depth%2
				}
				void Search(unsigned short _depth) {
					if (_depth == 0 || this->evaluateValue == INT_MAX || this->evaluateValue == INT_MIN) {
						this->value = this->evaluateValue;
						return;
					}
					bool created = false;//记录是否new出新的Node,如果没有就不用排序了。
					if (!board) { //不是根节点
						board = new State * [BOARDSIZE];
						for (int i = 0; i < BOARDSIZE; ++i) {
							board[i] = new State[BOARDSIZE];
							memcpy(board[i], father->board[i], BOARDSIZE * sizeof(State));
						}
						board[lastX][lastY] = IsMaxNode() ? BLACK : WHITE;
					}
					for (int i = max(minx-2,0); i < min(maxx+2,14); i++) {
						for (int j = max(miny-2,0); j < min(maxy+2,14); j++) {
							if (!board[i][j]) {
								bool flag = false;
								if (_depth >= 2) { //若剩余深度小于2,则下一层肯定没有搜索过
									for (Node* child : this->children) {
										if (child->lastX == i && child->lastY == j) { //已经被搜索过
											flag = true;
											break;
										}
									}
								}
								if (!flag) {
									new Node(this, i, j);
									minx=min(minx,i);
									maxx=max(maxx,i);
									miny=min(miny,j);
									maxy=max(maxy,j);
									created = true;
								}
							}
						}
					}
					if (IsMaxNode()) {
						this->value = INT_MIN;
						if (created) {
							std::sort(this->children.begin(), this->children.end(), [](Node* a, Node* b) {
								return a->GetEvaluateValue() > b->GetEvaluateValue();
							});//按照估价从大到小排序,增加剪枝的概率
						}
					} else {
						this->value = INT_MAX;
						if (created) {
							std::sort(this->children.begin(), this->children.end(), [](Node* a, Node* b) {
								return a->GetEvaluateValue() < b->GetEvaluateValue();
							});//按照估价从小到大排序,增加剪枝的概率
						}
					}
					auto ReleaseMemory = [this] {
						if (father) { //不是根节点
							for (int i = 0; i < BOARDSIZE; ++i) {
								delete[] board[i];
							}
							delete[] board;
							board = nullptr;
						}
					};
					for (Node* child : this->children) {
						child->Search(_depth - 1);
						//α - β 剪枝
						if (IsMaxNode()) {
							if (child->value > this->value) {
								this->value = child->value;
								if (this->father && this->value >= this->father->value && this != this->father->children.front()) {
									ReleaseMemory();
									return;//剪枝
								}
							}
						} else { //MIN节点
							if (child->value < this->value) {
								this->value = child->value;
								if (this->father && this->value <= this->father->value && this != this->father->children.front()) {
									ReleaseMemory();
									return;//剪枝
								}
							}
						}
					}
					ReleaseMemory();
				}
				void DeleteAllButThis() {
					if (!father->board)//父节点不是根节点
						throw std::invalid_argument("this->father必须是根节点!");
					for (Node* n : father->children) {
						if (n != this)
							delete n;
					}
					board = new State * [BOARDSIZE];
					for (int i = 0; i < BOARDSIZE; ++i) {
						board[i] = new State[BOARDSIZE];
						memcpy(board[i], father->board[i], BOARDSIZE * sizeof(State));
						delete[] father->board[i];
					}
					delete[] father->board;
					board[lastX][lastY] = IsMaxNode() ? BLACK : WHITE;
					free(father);//避免调用析构函数
					father = nullptr;
				}
				inline bool IsFull()const {
					return depth == BOARDSIZE * BOARDSIZE;
				}
				inline State GetWinner()const {
					if (this->value == INT_MAX) {
						return Node::WHITE;
					} else if (this->value == INT_MIN) {
						return Node::BLACK;
					}
					return Node::SPACE;
				}
				~Node() {
					if (board) {
						for (int i = 0; i < BOARDSIZE; ++i) {
							delete[] board[i];
						}
						delete[] board;
					}
					for (Node* n : children) {
						delete n;
					}
				}
		};
	private:
		Node* root;
		const unsigned short maxDepth;
	public:
		GameTree(unsigned short _maxDepth) : root(nullptr), maxDepth(_maxDepth) {
			if (_maxDepth < 2)
				throw std::invalid_argument("最大层数必须大于等于2!");
		}
		std::pair<uint8_t, uint8_t>AIGetNextPos(uint8_t x, uint8_t y) {
			if (root) {
				for (Node* node : root->children) { //进入用户选择的分支
					if (node->lastX == x && node->lastY == y) {
						node->DeleteAllButThis();
						root = node;
						break;
					}
				}
			} else { //第一次开局
				root = new Node(1, x, y);
			}
			root->Search(maxDepth);
			if (root->IsFull())
				return std::make_pair(19, 19);
			for (Node* node : root->children) { //选择分值最大的
				if (node->value == root->value) {
					node->DeleteAllButThis();
					root = node;
					break;
				}
			}
			return std::make_pair(root->lastX, root->lastY);
		}
		Node::State GetWinner()const {
			return root->GetWinner();
		}
		void Run() {
			while (1) {
				int x, y;
				do {
					color(7);
					std::cout << "输入x,y坐标";
					color(3);
					std::cin >> y >> x;
					y-=1;
					x-=1;
				} while (x < 0 || y < 0 || x >= 15 || y >= 15 || (root && root->board[x][y] != Node::SPACE));
				minx=min(minx,y);
				maxx=max(maxx,y);
				miny=min(miny,x);
				maxy=max(maxy,x);
				if (root) {
					for (Node* node : root->children) { //进入用户选择的分支
						if (node->lastX == x && node->lastY == y) {
							node->DeleteAllButThis();
							root = node;
							break;
						}
					}
				} else { //第一次开局
					root = new Node(1, x, y);
				}
				system("cls");
				for (int i = 0; i <= 15; i++) {
					for (int j = 0; j <= 15; j++) {
						color(6);
						if (i==0 && j<10)
							cout <<" " <<j <<" ";
						else if (i==0 && j>=10)
							cout <<j <<" ";
						else if (j==0 && i<10)
							cout <<" " <<i <<" ";
						else if (j==0 && i>=10)
							cout <<i <<" ";
						else if (root->board[i-1][j-1] == Node::SPACE) {
							color(5);
							std::cout << "十 ";
						} else if (root->board[i-1][j-1] == Node::BLACK) {
							color(2);
							std::cout << "○ ";
						} else {
							color(7);
							std::cout << "○ ";
						}
					}
					std::cout << '\n';
				}
				root->Search(maxDepth);
				if (root->value == INT_MAX) {
					std::cout << "电脑胜利!";
					break;
				} else if (root->value == INT_MIN) {
					std::cout << "玩家胜利!";
					break;
				} else if (root->IsFull()) { //不能用root->value==0判断平局,因为平局一定为0,但为0不一定平局
					std::cout << "平局!";
					break;
				}
				for (Node* node : root->children) { //选择分值最大的
					if (node->value == root->value) {
						node->DeleteAllButThis();
						root = node;
						break;
					}
				}
				system("cls");
				for (int i = 0; i <= 15; i++) {
					for (int j = 0; j <= 15; j++) {
						color(6);
						if (i==0 && j<10)
							cout <<" " <<j <<" ";
						else if (i==0 && j>=10)
							cout <<j <<" ";
						else if (j==0 && i<10)
							cout <<" " <<i <<" ";
						else if (j==0 && i>=10)
							cout <<i <<" ";
						else if (root->board[i-1][j-1] == Node::SPACE) {
							color(5);
							std::cout << "十 ";
						} else if (root->board[i-1][j-1] == Node::BLACK) {
							color(2);
							std::cout << "○ ";
						} else {
							color(7);
							std::cout << "○ ";
						}
					}
					std::cout << '\n';
				}
				if (root->value == INT_MAX) {
					std::cout << "电脑胜利!";
					break;
				} else if (root->value == INT_MIN) {
					std::cout << "玩家胜利!";
					break;
				} else if (root->IsFull()) { //不能用root->value==0判断平局,因为平局一定为0,但为0不一定平局
					std::cout << "平局!";
					break;
				}
			}
		}
		~GameTree() {
			delete root;
		}
};
int main() {
	cout <<"\n\n\n\n\n\n                           ";
	color(6);
	Sleep(1000);
	cout <<"游";
	Sleep(1000);
	cout <<"戏";
	Sleep(1000);
	cout <<"开";
	Sleep(1000);
	cout <<"始";
	Sleep(1000);
	cout <<"!";
	Sleep(2000);
	system("cls");
	for (int i = 0; i <= 15; i++) {
		for (int j = 0; j <= 15; j++) {
			color(6);
			if (i==0 && j<10)
				cout <<" " <<j <<" ";
			else if (i==0 && j>=10)
				cout <<j <<" ";
			else if (j==0 && i<10)
				cout <<" " <<i <<" ";
			else if (j==0 && i>=10)
				cout <<i <<" ";
			else {
				color(5);
				std::cout << "十 ";
			}
		}
		std::cout << '\n';
	}
	GameTree(4).Run();	//较为智能的模式,可改为3、2(不智能模式),以及5(超级智能模式,但是特别慢) 
	return 0; 
}

c++介绍

Dev-C++ 是一套用于开发 C/C++ 程序的自由的集成开发环境(IDE),并以 GPL 作为分发许可,使用 MinGW 及 GDB 作为编译系统与调试系统。Dev-C++ 运行在 Microsoft Windows 下。

Dev-C++ 的优点在于界面简洁友好,安装便捷,支持单文件编译,因此成为了许多入门 OI 选手以及 C++ 语言初学者的首选。在 NOIP 中,提供 Windows 作为比赛系统的省份一般预置 Dev-C++。

Dev-C++ 起源于 Colin Laplace 编写的 Bloodshed Dev-C++。该版本自 2005 年 2 月 22 日停止更新。2006 年,Dev-C++ 主要开发者 Colin Laplace 曾经对此作出了解释:「因忙于现实生活的事务,没有时间继续 Dev-C++ 的开发。」

Orwell Dev-C++ 是 Dev-C++ 的一个衍生版本,由独立程序员 Orwell (Johan Mes) 开发并维护。其对原版 Dev-C++ 进行了错误修正,并更新了编译器版本。一般而言,Dev-C++ 5.x 均为 Orwell Dev-C++。其最后一次更新于 2015 年,版本为 5.11。

Embarcadero Dev-C++1是 Bloodshed Dev-C++ 和 Orwell Dev-C++ 的继任者。2020 年,Embarcadero 赞助并接手了原有的 Dev-C++ 项目,继续开发。Embarcadero Dev-C++ 加入了对高 DPI 的支持,更新了编译器以加入更新版本的 C++ 标准支持,以及暗色模式。

以上的 Dev-C++ 分发都被认为是「官方的」。此外,在 2015 年 Orwell Dev-C++ 停止更新后,因为教学需要,一位来自中国的个人开发者 royqh1979 决定继续开发他的 Dev-C++ 个人分支,命名为小熊猫 Dev-C++2,集成了智能提示和高版本的 MinGW64,非常便于国内的个人使用和学习。

小熊猫 Dev-C++ 6.7.5 版本发布后,作者使用 qt5 开发了全新的小熊猫 C++3,可在 windows、linux 和 macos 等系统下原生运行。小熊猫 C++ 的界面与 Dev-C++ 相似,除了提供和 Dev-C++ 相似但更加完善的单文件编译、调试、语法高亮、搜索/替换等功能外,还提供了诸如 暗色主题、代码智能提示、变量/函数重命名、切换/自动识别文件编码 等现代 IDE 常见的基本功能。此外小熊猫 C++ 还具备与 CP Editor 类似的试题集功能,可以自行编写或 从常见的 OJ 竞赛网站上下载试题样例,自动运行和测试程序。

使用教程

常用快捷键

文件部分

  • Ctrl + N: 创建源代码
  • Ctrl + O: 打开文件
  • Ctrl + W: 关闭文件
  • Ctrl + P: 打印文件

格式部分

  • Ctrl + /:注释和取消注释
  • Tab: 缩进
  • Shift + Tab: 取消缩进

行操作

  • Ctrl + E: 复制行
  • Ctrl + D: 删除行
  • Ctrl + Shift + Up: 向上移动
  • Ctrl + Shift + Down: 向下移动

跳转部分

  • Ctrl + F: 搜索
  • Ctrl + R: 替换
  • F3: 搜索下一个
  • Shift + F3: 搜索上一个
  • Ctrl + G: 到指定行号
  • Shift + Ctrl + G: 到指定函数
  • Ctrl + [1 ~ 9]: 设置书签
  • Alt + [1 ~ 9]: 跳转书签

显示部分

  • Ctrl + 滚轮:字号放大或缩小
  • Ctrl + F11: 全屏或恢复

运行部分

  • F9: 只编译
  • F10: 只运行
  • F11: 编译并运行
  • F12: 全部重新编译

调试部分

  • F2: 转到断点
  • F4: 设置断点或取消
  • F5: 调试运行
  • F6: 停止
  • F7: 逐步调试

调试流程

  1. 将编译器配置设定为 TDM-GCC 4.9.2 64-bit Debug
  2. F4 设置或取消调试断点
  3. 将光标放置在变量上,按 Alt + A 向调试窗口添加监控变量
  4. F5 启动调试
  5. F7Alt + N 逐步调试
  6. Alt + S 跳至下一个调试断点
  7. F6 停止调试

扩展

增加编译选项

点击工具 -> 编译选项,然后选择 “代码生成/优化” 选项卡,下面介绍我自己常用的几个编译选项。

开启优化

优化代码运行时间或占用空间。

选择 “代码生成” 子选项卡中的 “优化级别(-Ox)” 选项标签。
ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

更换语言标准
使用新语言特性或试图让代码在旧标准下编译。

选择 “代码生成” 子选项卡中的 “语言标准(-std)” 选项标签。

ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

显示最多警告信息

查错小助手。

选择 “代码警告” 子选项卡中的 “显示最多警告信息(-Wall)” 选项标签。

ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

生成调试信息

当显示 “项目没有调试信息,您想打开项目调试选项并重新生成吗?” 点击后闪退或想使用调试功能时需开启此功能。

选择 “连接器” 子选项卡中的 “产生调试信息” 选项标签。
ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

编译小 trick

点击工具 -> 编译选项,然后选择 “编译器” 选项卡,接下来介绍几个常用 trick。

开大栈

防止 DFS 爆系统栈之类的情况出现。

在 “连接器命令行加入以下命令” 中加入 -Wl,–stack=128000000 命令。

此命令将栈开到了约 128MB 的大小,有需要可以自行增加。
ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

定义宏

方便本地评测使用文件输入输出或作其他用途。

在 “连接器命令行加入以下命令” 中加入 -D[String] 命令。

其中 [String] 改为你需要的宏名。

如图,当开启编译选项后便可将以下代码从 test.in 文件读入数据并在 test.out 文件中输出。

ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

#ifdef LOCAL
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif

代码格式化

点击 Astyle-> 格式化当前文件 或 按 Ctrl+Shift+A 进行代码格式化。

ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

美化

字体

点击工具 -> 编辑器选项,然后选择 “显示” 选项卡。
ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言

主题

点击工具 -> 编辑器选项,然后选择 “语法” 选项卡,可以使用预设主题,也可以自行调整。
ai五子棋,C++专栏,AI &amp; ChatGPT,游戏,c++,算法,开发语言文章来源地址https://www.toymoban.com/news/detail-745755.html

到了这里,关于AI五子棋——超强改进版本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于博弈树的开源五子棋AI教程[6 置换表]

    置换表是记忆化搜索技术的应用,置换表保存了某一盘面的搜索结果。当博弈树搜索遇到相同的局面时可以调用这些信息来减少重复搜索。那么如何设计一个置换表的节点就显得比较重要,本文在经典的置换表节点增加一个显示当前玩家的字段,这一字段补足了zobrist hash单向

    2024年01月17日
    浏览(40)
  • 基于博弈树的开源五子棋AI教程[7 多线程搜索]

    多线程加快搜索速度这一认知是经受住实践考验的。博弈树搜索的并行搜索方式有很多种,例如叶子并行,根并行,树分裂等算法。笔者给出一种实现起来比较简单的根并行算法。 在是实现时需要注意两点,第一,怎么安全的剪枝;第二,如何进行线程间的通信。对于AB剪枝

    2024年02月01日
    浏览(44)
  • 五子棋游戏禁手算法的改进

    五子棋游戏禁手算法的改进 五子棋最新的禁手规则: 1.黑棋禁手判负、白棋无禁手。黑棋禁手有“三三”(包括“四三三”)、“四四”(包括“四四三”)和“长连”。黑棋只能以“四三”取胜。 2.黑方五连与禁手同时形成,判黑方胜。 3.黑方禁手形成时,白方应立即

    2024年02月10日
    浏览(33)
  • 13 c++版本的五子棋

    呵呵 这大概是 大学里面的 c++ 五子棋了吧  有一些 面向对象的理解, 但是不多  这里 具体的实现 就不赘述, 仅仅是 发一下代码 以及 具体的使用  然后 貌似 放在 win10 上面执行 还有一些问题, 渲染的, 应该很好调整          这个在 win10 上面执行 貌似 渲染是存在问题的, 需

    2024年04月27日
    浏览(30)
  • C++项目:网络版本在线五子棋对战

    目录 1.项目介绍 2.开发环境 3.核心技术 4. 环境搭建 5.websocketpp 5.1原理解析 5.2报文格式  5.3websocketpp常用接口介绍 5.4websocket服务器 6.JsonCpp使用 6.1Json数据格式 6.2JsonCpp介绍 7.MySQL API 7.1MySQL API介绍 7.2MySQL API使用 7.3实现增删改查操作 8.项目结构设计 8.1项目模块划分说明 8.2业务处

    2024年02月10日
    浏览(49)
  • python五子棋代码最简单的,python五子棋代码能复制

    本篇文章给大家谈谈python五子棋代码红方蓝方,以及python五子棋代码最简单的,希望对各位有所帮助,不要忘了收藏本站喔。 开端 画棋盘 首先肯定是要画出棋盘来,用  pygame  画出一个 19 × 19 或 15 × 15 的棋盘并不是什么难事,这在之前的文章中已经多次用到,就不赘述了

    2024年03月13日
    浏览(46)
  • python五子棋代码最简单的,python五子棋代码手机版

    大家好,本文将围绕python五子棋代码最简单的展开说明,python五子棋代码手机版是一个很多人都想弄明白的事情,想搞清楚python五子棋代码画棋盘需要先了解以下几个事情。 【实例简介】 【实例截图】 【核心代码】 \\\"\\\"\\\"五子棋之人机对战\\\"\\\"\\\" import sys import random import pygame from

    2024年01月19日
    浏览(43)
  • 中秋时节赏明月,五子棋戏月饼趣 — Flutter中秋限定版五子棋

    前言 当中秋时节来临,我们都期待着与亲人朋友共度这个美好的节日。这个时候,除了传统的赏月和品尝美味的月饼,我还有一个特别的建议——尝试一款有趣的Flutter五子棋游戏!这款五子棋游戏以中秋为主题,游戏的棋子也可爱地模仿了月饼和玉兔的形状,让我们在这个

    2024年02月06日
    浏览(57)
  • 五子棋游戏

    一。画出棋盘x和y  横和竖个15条线,画出中央的小点 二,创建列表,计算出x和y的当前坐标的位置,且存储二维列表的值,画出圆形白色棋子 三.黑白棋子交替出现 四,提示已经被其他棋子占领了,不能重复占领 五。创建检测五子相连的函数  def  check 六.,实现水平向左和

    2024年02月05日
    浏览(41)
  • 鸿蒙小案例-五子棋

    刚开始以为挺简单的,越写越…emo 因为代码有点多,所以这里就简单讲下逻辑,文末贴上代码 逻辑只是我个人想的,不代表只有这一种实现方式,有其他想法可以在下面留言 另外功能做的比较简单,有一些没实现,但是基本功能都有,大家可以自行优化 组件就比较简单,采

    2024年02月21日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包