四子棋 AI 求优化
  • 板块学术版
  • 楼主Coffee_zzz/xin
  • 当前回复17
  • 已保存回复17
  • 发布时间2024/3/7 20:04
  • 上次更新2024/4/22 08:41:09
查看原帖
四子棋 AI 求优化
744687
Coffee_zzz/xin楼主2024/3/7 20:04

rt,现在搜索基本跑不了几轮。主要时间花费有点大。

框架是自己搭的,不是 thuwc 的。

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;

const int N=8,inf=1e9,Limit1=100,Limit2=200,Limit3=100;
int mp[N+2][N+2];

namespace Print{
	void print(){
		system("cls");
		for(int j=1;j<=N+2;j++){
			putchar('*');
			if(j==N+2) putchar('\n');
			else putchar(' ');
		}
		for(int i=1;i<=N;i++){
			putchar('*'),putchar(' ');
			for(int j=1;j<=N;j++){
				if(mp[i][j]==0) putchar('.');
				else if(mp[i][j]==1) putchar('O');
				else if(mp[i][j]==2) putchar('X');
				putchar(' ');
			}
			putchar('*'),putchar('\n');
		}
		putchar('*'),putchar(' ');
		for(int j=1;j<=N;j++) putchar(j+'0'),putchar(' ');
		putchar('*'),putchar('\n');
	}
}

namespace Judge{
	bool check(int i,int j){
		return 0<i&&i<=N&&0<j&&j<=N;
	}
	bool modify(int y,int k){
		if(y>8||y<1) return 0;
		if(k!=1&&k!=2) return 0;
		int pos=N;
		while(mp[pos][y]!=0&&pos>0) pos--;
		if(pos==0) return 0;
		mp[pos][y]=k;
		return 1;
	}
	int win(){
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=j;k<=j+3;k++){
					if(mp[i][k]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=j;k<=j+3;k++){
					if(mp[i][k]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N;j++){
				bool flag=1;
				for(int k=i;k<=i+3;k++){
					if(mp[k][j]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N;j++){
				bool flag=1;
				for(int k=i;k<=i+3;k++){
					if(mp[k][j]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l++){
					if(mp[k][l]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l++){
					if(mp[k][l]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=4;j<=N;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l--){
					if(mp[k][l]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=4;j<=N;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l--){
					if(mp[k][l]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		bool flag=1;
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N;j++){
				if(mp[i][j]==0){
					flag=0;
					break;
				}
			}
		}
		if(flag) return 3;
		return 0;
	}
}

namespace User{
	int scan(){
		string s;
		getline(cin,s);
		if('1'<=s[0]&&s[0]<='8') return s[0]-'0';
		else return 0;
	}
	void read(){
		while(1){
			int y=scan();
			if(y!=0&&Judge::modify(y,1)) break;
			Print::print();
		}
	}
}

namespace AI{
	int tmp[N+2][N+2];
	int twin(){
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=j;k<=j+3;k++){
					if(tmp[i][k]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=j;k<=j+3;k++){
					if(tmp[i][k]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N;j++){
				bool flag=1;
				for(int k=i;k<=i+3;k++){
					if(tmp[k][j]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N;j++){
				bool flag=1;
				for(int k=i;k<=i+3;k++){
					if(tmp[k][j]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l++){
					if(tmp[k][l]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=1;j<=N-3;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l++){
					if(tmp[k][l]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=4;j<=N;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l--){
					if(tmp[k][l]!=1){
						flag=0;
						break;
					}
				}
				if(flag) return 1;
			}
		}
		
		for(int i=1;i<=N-3;i++){
			for(int j=4;j<=N;j++){
				bool flag=1;
				for(int k=i,l=j;k<=i+3;k++,l--){
					if(tmp[k][l]!=2){
						flag=0;
						break;
					}
				}
				if(flag) return 2;
			}
		}
		bool flag=1;
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N;j++){
				if(tmp[i][j]==0){
					flag=0;
					break;
				}
			}
		}
		if(flag) return 3;
		return 0;
	}
	int random(int now){
		int x=twin();
		if(x==1) return 0;
		else if(x==2) return 2;
		else if(x==3) return 1;
		while(1){
			int pos=N,y=rand()%8+1;
			while(tmp[pos][y]!=0&&pos>0) pos--;
			if(pos==0) continue;
			tmp[pos][y]=now;
			int x=random(now^3);
			tmp[pos][y]=0;
			return x;
		}
	}
	double value(int now){
		double res=0;
		int x=0;
		for(int i=1;i<=Limit3;i++) x=x+random(now);
		res=x/2.0/Limit3;
		return res;
	}
	double search(double alpha,double beta,int cnt,int dep,int now){
		if(cnt==0) return value(now);
		if(dep>=Limit1) return value(now);
		int x=twin();
		if(x==1) return 0;
		else if(x==2) return 1;
		else if(x==3) return 0.5;
		
		pair <int,int> val[N+2];
		int tot=0;
		for(int i=1;i<=N;i++){
			int pos=N,y=i;
			while(tmp[pos][y]!=0&&pos>0) pos--;
			if(pos==0) continue;
			tmp[pos][y]=now;
			++tot;
			val[tot].fi=value(now^3);
			val[tot].se=i;
			tmp[pos][y]=0;
		}
		sort(val+1,val+1+tot);
		if(now==2) reverse(val+1,val+1+tot);
		
		if(now==1){
			for(int i=1;i<=tot;i++){
				int pos=N,y=val[i].se;
				while(tmp[pos][y]!=0&&pos>0) pos--;
				if(pos==0) continue;
				tmp[pos][y]=1;
				beta=min(beta,search(alpha,beta,cnt/pow(2,i),dep+1,now^3));
				tmp[pos][y]=0;
				if(alpha>=beta) break;
			}
			return beta;
		}
		else{
			for(int i=1;i<=tot;i++){
				int pos=N,y=val[i].se;
				while(tmp[pos][y]!=0&&pos>0) pos--;
				if(pos==0) continue;
				tmp[pos][y]=2;
				alpha=max(alpha,search(alpha,beta,cnt/pow(2,i),dep+1,now^3));
				tmp[pos][y]=0;
				if(alpha>=beta) break;
			}
			return alpha;
		}
	}
	int find(){
		for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) tmp[i][j]=mp[i][j];
		int res=0;
		double alpha=-1;
		for(int i=1;i<=N;i++){
			int pos=N,y=i;
			while(tmp[pos][y]!=0&&pos>0) pos--;
			if(pos==0) continue;
			tmp[pos][y]=2;
			double x=search(0,1,Limit1,0,1);
			if(alpha<x) alpha=x,res=i;
			tmp[pos][y]=0;
		}
		return res;
	}
	void solve(){
		int y=find();
		if(!Judge::modify(y,2)){
			puts("Oops, There is an unknown bug here ...");
			exit(0);
		}
	}
}

namespace Main{
	void enter(){
		char c=getchar();
		while(c!='\n') c=getchar();
	}
	int finish(int x){
		if(x==1){
			Print::print();
			puts("User Win!");
			puts("Press Enter to continue.");
			enter();
			return 1;
		}
		else if(x==2){
			Print::print();
			puts("AI Win!");
			puts("Press Enter to continue.");
			enter();
			return 1;
		}
		else if(x==3){
			Print::print();
			puts("Draw!");
			puts("Press Enter to continue.");
			enter();
			return 1;
		}
		else return 0;
	}
	void main(){
		srand(time(0));
		int res;
		while(1){
			system("cls");
			puts("Press Enter to start.");
			enter();
			for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) mp[i][j]=0;
			while(1){
				Print::print();
				User::read();
				res=Judge::win();
				if(finish(res)) break;
				Print::print();
				AI::solve();
				res=Judge::win();
				if(finish(res)) break;
			}
		}
	}
}

signed main(){
	Main::main();
	return 0;
}

/*
1:User 2:AI
*/
2024/3/7 20:04
加载中...