製作混亂時鐘弈棋AI計畫

分享讨论IT相关的内容
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

Re: 製作混亂時鐘弈棋AI計畫

帖子 ejsoon »

图片

手工生成一局,乙方好像只能走10,甲方應該只能應1。

甲方如果用8吃掉7,這時乙方會很難辦。

乙方第一步如果走6,或許可以共贏。
https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

Re: 製作混亂時鐘弈棋AI計畫

帖子 ejsoon »

這個棋AI難製作的原因是它確實有點深奧。常常一個局面,我都要研究老半天。有時以為已經有結論了,想不到又有新問題。

因此混亂時鐘不太可能一眼就看出答案,即便是像我這樣的「高手」。可能我也是唯一的高手了,這款棋由寡人發明,一直沒能推廣。
https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

Re: 製作混亂時鐘弈棋AI計畫

帖子 ejsoon »

我有一個疑問,如果chatGPT真的那麼厲害,那我把混亂時鐘的規則跟它說明清楚之後,是不是就可以跟它對弈了?

再退一步,如果它一開始還走不對,我就告訴它哪裏走的不好,那它是否真的能學會下棋?
https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

AI如何判定同輸

帖子 ejsoon »

https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

數據結構

帖子 ejsoon »

代码: 全选

struct pieces {
	vector<vector<int>> stick = {{}, {}}; //處於正位
	vector<vector<int>> hand = {{}, {}}; //拿在手上
	vector<int> running = {}; //可以走至少一步
	vector<vector<int>> stop = {{}, {}}; //一步都走不了(卡住)
	vector<vector<int>> stock = {{}, {}}; //不能走且不能被別的棋子行走吃掉
	vector<vector<int>> dead = {{}, {}}; //不能走不能被行走吃掉,也不能被落子吃掉(卡死)
	vector<vector<int>> free = {{}, {}}; //被卡住但能被己方落子吃掉
};

struct position {
	int board[12];
	int lastmove;
	int player;
	int value;
	pieces pieces_data;
	int deep;
	vector<position> children;
};
上次由 ejsoon 在 2023年 3月 3日 13:07,总共编辑 1 次。
https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

棋子屬性判定函數

帖子 ejsoon »

代码: 全选

pieces piecesValue(position pos) {
	pieces new_pieces;
	vector<int> run_pos_sum = {};
	for (int c = 1; c <= 12; c++) {
		// stick, hand, run, stop
		if (c == pos.board[c - 1]) {
			new_pieces.stick[c % 2].push_back(c);
		} else if (vectorIndexOf(pos.board, c) == -1) {
			new_pieces.hand[c % 2].push_back(c);
		} else {
			vector<int> c_run_pos = getRunPos(pos.board, c);
			if (c_run_pos.size() == 0) {
				new_pieces.stop[c % 2].push_back(c);
			} else {
				new_pieces.running.push_back(c);
				run_pos_sum.insert(run_pos_sum.end(),
					c_run_pos.begin(), c_run_pos.end());
			}
		}
	}
	// free
	for (int p = 0; p < new_pieces.stop.size(); p++) {
		vector<int> makefree = vectorMerge(new_pieces.hand[p], new_pieces.free[p]);
		for (int x = 0; x < new_pieces.stop[p].size(); x++) {
			int stopx = new_pieces.stop[p][x];
			int stop_pos = vectorIndexOf(pos.board, stopx);
			if (vectorIndexOf(makefree, stop_pos + 1) > -1) {
				new_pieces.free[p].push_back(stopx);
				new_pieces.stop[p].erase(new_pieces.stop[p].begin() + x);
				makefree = vectorMerge(new_pieces.hand[p], new_pieces.free[p]);
				x = -1;
			}
		}
	}
	// stock
	for (int p = 0; p < new_pieces.stop.size(); p++) {
		vector<int> stop_delete;
		for (int x = 0; x < new_pieces.stop[p].size(); x++) {
			int c = new_pieces.stop[p][x];
			int c_pos = vectorIndexOf(pos.board, c);
			if (vectorIndexOf(run_pos_sum, c_pos) == -1) {
				stop_delete.push_back(x);
				new_pieces.stock[p].push_back(c);
			}
		}
		while (stop_delete.size()) {
			new_pieces.stop[p].erase(new_pieces.stop[p].begin() + stop_delete.back());
			stop_delete.pop_back();
		}
	}
	// dead
	for (int p = 0; p < new_pieces.stock.size(); p++) {
		vector<int> stock_delete;
		for (int x = 0; x < new_pieces.stock[p].size(); x++) {
			int c = new_pieces.stock[p][x];
			int c_pos = vectorIndexOf(pos.board, c);
			// if in other player
			if (c_pos % 2 == p) {
				stock_delete.push_back(x);
				new_pieces.dead[p].push_back(c);
			}
			// if multiple stock 
			else {
				int ms = c_pos + 1;
				int ms_pos = vectorIndexOf(pos.board, ms);
				int ts = ms_pos + 1;
				int ts_pos = vectorIndexOf(pos.board, ts);
				if (vectorIndexOf(new_pieces.stock[p], ms) > -1
					&& (ms_pos + 1 == c || 
					vectorIndexOf(new_pieces.stock[p], ts) > -1
					&& ts_pos + 1 == c)) {
					stock_delete.push_back(x);
					new_pieces.dead[p].push_back(c);
				}
			}
		}
		while (stock_delete.size()) {
			new_pieces.stock[p].erase(new_pieces.stock[p].begin() + stock_delete.back());
			stock_delete.pop_back();
		}
	}
	return new_pieces;
}

vector<int> getRunPos(int (&board)[12], int c) {
	vector<int> running;
	int c_pos = vectorIndexOf(board, c);
	int next_pos = (c_pos + c) % 12;
	while (board[next_pos] != next_pos + 1) {
		if (next_pos == c_pos || c == next_pos + 1) {
			running.push_back(next_pos);
			break;
		} else {
			running.push_back(next_pos);
		}
		next_pos = (next_pos + c) % 12;
	}
	return running;
}

int vectorIndexOf(vector<int> v, int i) {
	int vindex = find(v.begin(), v.end(), i) - v.begin();
	if (vindex == v.size()) return -1;
	return vindex;
}

int vectorIndexOf(int (&v)[12], int i) {
	int vindex = find(v, v + 12, i) - v;
	if (vindex == 12) return -1;
	return vindex;
}

上次由 ejsoon 在 2023年 3月 3日 13:06,总共编辑 1 次。
https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

根據棋子屬性判定輸贏

帖子 ejsoon »

4己贏
3共贏
2同輸
1己輸
0無果

代码: 全选

int ifEnd(position pos) {
	int me = pos.player;
	int you = 1 - me;
	pieces pd = pos.pieces_data;
	int my_num = pd.stick[me].size();
	int your_num = pd.stick[you].size();
	int my_handle = pd.hand[me].size() + pd.free[me].size();
	int your_handle = pd.hand[you].size() + pd.free[you].size();
	int my_dead = pd.dead[me].size();
	int your_dead = pd.dead[you].size();
	// two win
	if (my_num + my_handle == 6 && your_num + your_handle == 6
			&& my_num - your_num <= 0
			&& my_num - your_num >= -1) {
		return 3;
	}
	// I win
	if (my_num == 6 && your_num < 6
			|| my_num + my_handle == 6 && your_dead > 0
			|| my_num + my_handle == 6 && your_num + your_handle <= 6
			&& my_num - your_num > 0) {
		return 4;
	}
	// I lose
	if (my_num < 5 && your_num == 6
			|| your_num + your_handle == 6 && my_dead > 0
			|| my_num + my_handle <= 6 && your_num + your_handle == 6
			&& your_num - my_num > 1) {
		return 1;
	}
	// two lose
	if (my_dead > 0 && your_dead > 0) {
		return 2;
	}
	return 0;
}
上次由 ejsoon 在 2023年 3月 3日 13:06,总共编辑 2 次。
https://ejsoon.win/
天蒼人頡:發掘好玩事物
头像
BobMaster
锋芒初露
锋芒初露
帖子: 1187
注册时间: 2020年 12月 7日 08:05
来自: 神秘的东方
我的状态: 🎯
为圈友点赞: 338 次
被赞次数: 178 次
联系:

Re: 製作混亂時鐘弈棋AI計畫

帖子 BobMaster »

离题
代码是可以高亮的,高亮码可参考:https://prismjs.com/#supported-languages
[code=cpp]c++代码[/code]

代码: 全选

#include <iostream>

int main(char **args, int argc) {
    std::cout << "Hello World!" << std::endl;
    return 0;
}
BobMaster 的这篇帖子被以下圈友点了赞:
ejsoon
人生如音乐,欢乐且自由
头像
ejsoon
圈圈精英
圈圈精英
帖子: 2179
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 96 次
被赞次数: 92 次
联系:

混亂時鐘弈棋AI計畫:成功!

帖子 ejsoon »

在calcitem的大力幫助下,這個ai程式基本做好了,能把初始局面的所有可能著法都算完並評分。

當我拿第五頁的用例去算之後,發現我之前的結論是錯誤的!乙方的第二回合不能用5吃掉10!否則會輸!

正確應法只能是用2吃掉10或用10吃掉2,誰能想的到呢!只有電腦能算出來!
ejsoon 的这篇帖子被以下圈友点了赞:
BobMaster
https://ejsoon.win/
天蒼人頡:發掘好玩事物
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 3 访客