问题 J: Stone Game(模拟)

Stone Game模拟问题

原题地址 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 100;
ll a[100011];
ll b[100011];
ll c[100011];
ll d[100011];
int main()
{
	int t;
	cin>>t;
	int n;
	for(int tim=1; tim<=t; tim++)
	{
		cin>>n;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		memset(d,0,sizeof(d));

		for(int i=1; i<=n; i++)
			cin>>a[i];
		if(n==1)//n为1的情况进行特判一下。 
		{
			if(a[1]%2==1)
				cout<<"Case "<<tim<<": Alice"<<endl;
			else
				cout<<"Case "<<tim<<": Bob"<<endl;
			continue;
		}
		int j;
		for(int i=2; i<=n; i++)//从前往后扫,将各个上升序列用b数组标记一下 
		{
			//cout<<i<<endl;
			//cout<<a[i-1]<<" "<<a[i]<<endl;
			if(a[i]>a[i-1])
			{
				ll p=1;
				b[i-1]=0;
				for( j=i; j<n; j++)
				{
					if(a[j+1]>a[j])
					{
						//cout<<a[j]<<" "<<a[j+1]<<endl;
						b[j]=p;
						p++;
						continue;
					}
					else
					{
						b[j]=p;

						break;
					}
				}
				i=j+1;

			}

		}
		if(a[n]>a[n-1])
			b[n]=b[n-1]+1;
		for(int i=n,k=1; i>=1; i--)
		{
			c[i]=a[k];
			k++;
		}
//		for(int i=1; i<=n; i++)
//			cout<<b[i]<<" ";
//		cout<<endl;
		int j1;
		for(int i=2; i<=n; i++)//从后往前扫,将上升序列用d数组标记一下。 
		{
			if(c[i]>c[i-1])
			{
				ll p=1;
				d[i-1]=0;
				for( j1=i; j1<n; j1++)
				{
					if(c[j1+1]>c[j1])
					{
						d[j1]=p;
						//cout<<d[j]<<endl;
						p++;
						continue;
					}
					else
					{
						d[j1]=p;

						break;
					}
				}
				i=j1+1;
			}
		}
		if(c[n]>c[n-1])
			d[n]=d[n-1]+1;
		ll res=0;

		for(int i=1,k=n; i<=n; i++,k--)//将前后标记进行更新,保留较大的。 
		{
			if(b[i]<d[k])
				b[i]=d[k];
			res+=abs(a[i]-b[i]);//统计与最终状态与初始状态差值求和 
		}
		//cout<<res<<endl;
		if(res%2==1)//操作数为奇数A赢 
			cout<<"Case "<<tim<<": Alice"<<endl;
		else
			cout<<"Case "<<tim<<": Bob"<<endl;
	}

	return 0;
}
//5 1 8 9 4 5 6 3 2 1
//1 2 3 6 5 4 9 8 1 5

 

恭喜你到达第九步! 上一步我们已经完成了一个AI大脑的最核心功能。我们可以用它来对战了。 访问服务器http://183.175.12.27:8001/join_game,会返回一个游戏编号game_id。之后你可以使用这个游戏编号,进行游戏http://183.175.12.27:8001/play_game/{game_id}并查询游戏状态http://183.175.12.27:8001/check_game/{game_id}。 利用这三个功能我们就可以让我们的AI参战了。这个过程应该是这样的,这是一个典型的消息循环。 用join_game加入游戏 用check_game检查游戏状态 a. 如果游戏完成就退出 b. 如果不轮你下,就等一会,否则使用AI确定要落子的位置,并用play_game告知服务器你落子的位置 c. 返回到第2步用check_game检查游戏状态 其中join_game需要登录,需要提交用户名和密码,需要使用第五步使用的加密方法对密码加密,用户名写入user字段,加密后的密码写入password字段。另外需要传入字段data_type,将其设为json,返回字段game_id是加入的游戏编号。 play_game也需要登录,落子的坐标写入coord字段。 check_game不需要登录,返回当前的游戏状态, 会返回以下状态: is_success,error 查询是否成功及错误原因 step 当前是第几步 creator 游戏一方的用户名 creator_name 游戏一方的名字(昵称) creator_stone 游戏一方使用的棋子(x表示黑棋,o表示白棋) opponent 游戏另一方的用户名 opponent_name 游戏另一方的名字(昵称) opponent_stone 游戏另一方使用的棋子(x表示黑棋,o表示白棋) ready 游戏是否就绪,两个玩家都在线时,游戏进入就绪状态 current_turn 当前应当落子的玩家的用户名 current_stone 当前应当落子的玩家的使用的棋子(x表示黑棋,o表示白棋) left_time 剩余时间,为避免玩家过长思考,限制玩家必须在60秒内落子,否则游戏结束 winner 获胜的玩家的用户名,当游戏没有产生赢家时,该值为None board 棋盘的坐标表示 last_step 上一步落子的坐标 win_step 如果一方获胜,这个字段给出连成五子的一条线的棋子坐标 注意不要过于频繁的检查游戏的状态,使用sleep函数等待服务器更新状态,两次检查以5到10秒的间隔为宜。结合上述的各种问题,给出最终可实行代码
07-05
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<conio.h> #include<graphics.h> #include<math.h> #define width 1042 //窗口宽度 #define height 757 //窗口高度 #define pi 3.14159 #define hook_length 30 //钩子的爪长 #define hook_speed 25 //钩子速度 #define gold_count_max 10 //金子数量最大值 #define stone_count_max 7 //石头数量最大值 #define gold_count_min 5 //金子数量最小值 #define small_gold_r 15 //小号金子的大小 #define mid_gold_r 30 #define big_gold_r 100 #define small_gold_value 25 //小号金子的价值 #define mid_gold_value 200 #define big_gold_value 500 #define small_gold_weight 1 //小号金子的重量(重量会影响钩子返回速度) #define mid_gold_weight 5 #define big_gold_weight 15 #define small_stone_r 10 #define mid_stone_r 20 #define big_stone_r 50 #define small_stone_value 10 #define mid_stone_value 30 #define big_stone_value 50 #define small_stone_weight 5 #define mid_stone_weight 10 #define big_stone_weight 15 #define time_limit 90 //每关的限定时间 #define gold_color RGB(253, 189, 0) //金子的颜色 #define stone_color RGB(145,145,145) //石头的颜色 #pragma warning (disable:4996) #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<conio.h> #include<graphics.h> #include<math.h> #include<windows.h> #define width 1042 //窗口宽度 #define height 757 //窗口高度 #define pi 3.14159 #define hook_length 30 //钩子的爪长 #define hook_speed 25 //钩子速度 #define gold_count_max 10 //金子数量最大值 #define stone_count_max 7 //石头数量最大值 #define gold_count_min 5 //金子数量最小值 #define small_gold_r 15 //小号金子的大小 #define mid_gold_r 30 #define big_gold_r 100 #define small_gold_value 25 //小号金子的价值 #define mid_gold_value 200 #define big_gold_value 500 #define small_gold_weight 1 //小号金子的重量 #define mid_gold_weight 5 #define big_gold_weight 15 #define small_stone_r 10 #define mid_stone_r 20 #define big_stone_r 50 #define small_stone_value 10 #define mid_stone_value 30 #define big_stone_value 50 #define small_stone_weight 5 #define mid_stone_weight 10 #define big_stone_weight 15 #define time_limit 90 //每关的限定时间 // 颜色定义 #define gold_color RGB(253, 189, 0) #define stone_color RGB(145, 145, 145) #define title_color RGB(210, 105, 30) #define btn_color RGB(0, 128, 0) #define tips_color RGB(139, 0, 0) #define bg_color RGB(30, 30, 30) #define text_color RGB(255, 255, 255) #define getmouse struct gold { int value; int weight; int x, y; int r; bool is_be_grap = false; }golds[gold_count_max]; struct stone { int value; int weight; int x, y; int r; bool is_be_grap = false; }stones[stone_count_max]; //绘制钩子 void draw_hook(int x, int y, float jiaodu) { setlinecolor(BLACK); line(x, y, x - hook_length * cos(jiaodu), y + hook_length * sin(jiaodu)); line(x, y, x - hook_length * cos(jiaodu + pi / 2), y + hook_length * sin(jiaodu + pi / 2)); } //绘制钩子发射和返回的直线 void draw_hook_launch_or_recovery(int x, int y, float jiaodu, int s) { setlinecolor(BLACK); float j = jiaodu + pi / 4; line(x, y, x - s * cos(j), y + s * sin(j)); } //绘制文字内容 void draw_worlds(int score, int target_score, time_t time0, time_t time1, int pass_count) { settextcolor(GREEN); settextstyle(50, 0, _T("宋体")); TCHAR str1[15]; _stprintf(str1, L"金钱:%d", score); outtextxy(0, 0, str1); TCHAR str2[20]; _stprintf(str2, L"目标金钱:%d", target_score); outtextxy(0, 50, str2); TCHAR str3[8]; long t = time0 + time_limit - time1; _stprintf(str3, L"时间:%ld", t); outtextxy(width - 200, 0, str3); TCHAR str4[8]; _stprintf(str4, L"第%d关", pass_count); outtextxy(width - 150, 50, str4); setlinecolor(RED); line(0, 100, width, 100); } //判断圆与圆之间是否相差10以上的距离 bool circle_meet(int x0, int y0, int r0, int x1, int y1, int r1) { int a = x0 - x1; int b = y0 - y1; if (a * a + b * b + 100 <= (r0 + r1) * (r0 + r1)) return true; return false; } //创造石头和金子的坐标和大小 void creat_gold_and_stone(struct gold* golds, int gold_count, struct stone* stones, int stone_count, int pass_count) { for (int i = 0; i < gold_count; i++) { int j = rand() % 7; switch (j) { case 0:case 1:case 2:case 3: golds[i].value = small_gold_value; golds[i].weight = small_gold_weight; golds[i].r = small_gold_r; break; case 4:case 5: golds[i].value = mid_gold_value; golds[i].weight = mid_gold_weight; golds[i].r = mid_gold_r; break; case 6: golds[i].value = big_gold_value; golds[i].weight = big_gold_weight; golds[i].r = big_gold_r; break; } } for (int i = 0; i < gold_count; i++) { while (1) { int j; golds[i].x = rand() % (width - 2 * golds[i].r + 1) + golds[i].r; golds[i].y = rand() % (height - 2 * golds[i].r - 201) + golds[i].r + 200; for (j = 0; j < i; j++) { if (circle_meet(golds[i].x, golds[i].y, golds[i].r, golds[j].x, golds[j].y, golds[j].r)) break; } if (j == i) break; } } for (int i = 0; i < stone_count; i++) { int j = rand() % 3; switch (j) { case 0: stones[i].value = small_stone_value; stones[i].weight = small_stone_weight; stones[i].r = small_stone_r; break; case 1: stones[i].value = mid_stone_value; stones[i].weight = mid_stone_weight; stones[i].r = mid_gold_r; break; case 2: stones[i].value = big_stone_value; stones[i].weight = big_stone_weight; stones[i].r = big_stone_r; break; } } for (int i = 0; i < stone_count; i++) { while (1) { int j, k; stones[i].x = rand() % (width - 2 * stones[i].r + 1) + stones[i].r; stones[i].y = rand() % (height - 2 * stones[i].r - 201) + stones[i].r + 200; for (j = 0; j < i; j++) { if (circle_meet(stones[i].x, stones[i].y, stones[i].r, stones[j].x, stones[j].y, stones[j].r)) break; } for (k = 0; k < gold_count; k++) { if (circle_meet(stones[i].x, stones[i].y, stones[i].r, golds[k].x, golds[k].y, golds[k].r)) break; } if (j == i && k == gold_count) break; } } } //绘制石头和金子 void draw_gold_and_stone(struct gold* golds, int gold_count, struct stone* stones, int stone_count) { setfillcolor(gold_color); for (int i = 0; i < gold_count; i++) if (!golds[i].is_be_grap) fillcircle(golds[i].x, golds[i].y, golds[i].r); setfillcolor(stone_color); for (int i = 0; i < stone_count; i++) if (!stones[i].is_be_grap) fillcircle(stones[i].x, stones[i].y, stones[i].r); } //判断点是否在圆内 bool is_circle_include_spot(int spot_x, int spot_y, int circle_x, int circle_y, int circle_r) { int x = spot_x - circle_x; int y = spot_y - circle_y; return x * x + y * y <= circle_r * circle_r; } //将钩子的坐标与每个石头和金子进行比较,判断是否抓到石头或金子同时标记被抓住的 int is_hook_grap_object(int x0, int y0, float jiaodu, int s, struct gold* golds, int gold_count, struct stone* stones, int stone_count) { float j = jiaodu + pi / 4; int x1 = x0 - s * cos(j); int y1 = y0 + s * sin(j); int x2 = x1 - hook_length * cos(jiaodu); int y2 = y1 + hook_length * sin(jiaodu); int x3 = x1 - hook_length * cos(jiaodu + pi / 2); int y3 = y1 + hook_length * sin(jiaodu + pi / 2); for (int i = 0; i < gold_count; i++) if (!golds[i].is_be_grap && is_circle_include_spot(x1, y1, golds[i].x, golds[i].y, golds[i].r)) { golds[i].is_be_grap = true; return i; } for (int i = 0; i < stone_count; i++) if (!stones[i].is_be_grap && is_circle_include_spot(x1, y1, stones[i].x, stones[i].y, stones[i].r)) { stones[i].is_be_grap = true; return i + 10; } return -1; } //绘制钩子抓住物体返回的情景 void draw_hook_and_object(int x, int y, float jiaodu, int s, int object) { float j = jiaodu + pi / 4; int x0 = x - s * cos(j); int y0 = y + s * sin(j); if (object < 10) { setfillcolor(gold_color); fillcircle(x0 - golds[object].r * cos(j), y0 + golds[object].r * sin(j), golds[object].r); } else { setfillcolor(stone_color); fillcircle(x0 - stones[object - 10].r * cos(j), y0 + stones[object - 10].r * sin(j), stones[object - 10].r); } setlinecolor(RED); line(x0, y0, x0 - hook_length * cos(jiaodu), y0 + hook_length * sin(jiaodu)); line(x0, y0, x0 - hook_length * cos(jiaodu + pi / 2), y0 + hook_length * sin(jiaodu + pi / 2)); line(x0, y0, x0 - s * cos(j), y0 + s * sin(j)); } int main() { initgraph(width, height); setbkcolor(WHITE); cleardevice(); float jiaodu = -pi / 4; //钩子当前旋转的角度 bool flag = true; bool is_away = false; //钩子是否发射 bool is_grap_object = false; //钩子是否抓住物体 bool is_hook_out = false; //钩子是否出界 bool time_flag = true; //是否超时 int x0 = width / 2, y0 = 100; //钩子坐标 int hook_away_length = 0; //钩子离开时的直线长度 int score = 0; //当前金钱 int target_score = 600; //目标金钱 int pass_count = 1; //当前关卡 int object; //被抓住的物体 srand((unsigned)time(NULL)); //设置随机种子 BeginBatchDraw();//开始批量绘图,提高绘图效率,避免频繁刷新导致的闪烁 while (1) { int gold_count = rand() % 6 + 5;// // 随机生成本轮的金币数量(5-10个) int stone_count = rand() % (10 - pass_count) + pass_count;//随机生成本轮的石头数量,随着关卡推进逐渐增多 time_flag = true; creat_gold_and_stone(golds, gold_count, stones, stone_count, pass_count); //创建金币和石头对象,初始化它们的位置、价值等属性 time_t time0 = time(NULL);//记录当前回合开始的时间 time_t time1 = time(NULL); draw_gold_and_stone(golds, gold_count, stones, stone_count);//绘制初始的金币和石头 while (time_flag)//当前回合的主循环,在时间限制内持续运行 { draw_worlds(score, target_score, time0, time1, pass_count);//绘制游戏界面元素:分数、目标分数、剩余时间、当前关卡 draw_gold_and_stone(golds, gold_count, stones, stone_count);// 绘制金币和石头 draw_hook(x0, y0, jiaodu);// 绘制当前状态的钩子(未发射状态) if (kbhit() && !is_away)// 检测键盘输入,并且钩子不在移动状态时才响应 { char older = getch(); if (older == 's')//如果按下's'键,发射钩子 { is_away = true;// 标记钩子处于移动状态 BeginBatchDraw(); while (!is_grap_object && !is_hook_out)// 钩子向外延伸的过程,直到勾到物体或超出边界 { hook_away_length += hook_speed;// 增加钩子长度,模拟钩子向外移动 draw_worlds(score, target_score, time0, time1, pass_count); // 绘制游戏界面元素 draw_hook_launch_or_recovery(x0, y0, jiaodu, hook_away_length); //绘制正在发射或回收的钩子 draw_gold_and_stone(golds, gold_count, stones, stone_count); // 绘制金币和石头 FlushBatchDraw(); Sleep(100); time1 = time(NULL); if (time1 - time0 > time_limit) { time_flag = false; break; } cleardevice(); //// 检查钩子是否超出屏幕边界 if (x0 - hook_away_length * cos(jiaodu + pi / 4) <= 0 || x0 - hook_away_length * cos(jiaodu + pi / 4) >= width || y0 + hook_away_length * sin(jiaodu + pi / 4) >= height) is_hook_out = true; if ((object = is_hook_grap_object(x0, y0, jiaodu, hook_away_length, golds, gold_count, stones, stone_count)) != -1) is_grap_object = true; } if (is_hook_out)// // 如果钩子超出边界,开始回收钩子 { BeginBatchDraw(); while (is_hook_out)// 钩子回收过程,直到回到初始位置 { hook_away_length -= hook_speed; draw_worlds(score, target_score, time0, time1, pass_count); draw_hook_launch_or_recovery(x0, y0, jiaodu, hook_away_length); draw_gold_and_stone(golds, gold_count, stones, stone_count); FlushBatchDraw(); Sleep(100); time1 = time(NULL); if (time1 - time0 > time_limit) { time_flag = false; break; } cleardevice(); if (hook_away_length <= 0) { hook_away_length = 0; is_away = false; is_hook_out = false; draw_worlds(score, target_score, time0, time1, pass_count); draw_gold_and_stone(golds, gold_count, stones, stone_count); draw_hook(x0, y0, jiaodu); } } } if (is_grap_object) { BeginBatchDraw(); while (is_grap_object) { if (object < 10) hook_away_length -= (hook_speed - golds[object].weight); else hook_away_length -= (hook_speed - stones[object - 10].weight); draw_worlds(score, target_score, time0, time1, pass_count); draw_hook_and_object(x0, y0, jiaodu, hook_away_length, object); draw_gold_and_stone(golds, gold_count, stones, stone_count); FlushBatchDraw(); Sleep(100); time1 = time(NULL); if (time1 - time0 > time_limit) { time_flag = false; break; } cleardevice(); if (hook_away_length <= 0) { hook_away_length = 0; is_away = false; is_hook_out = false; is_grap_object = false; if (object < 10) score += golds[object].value; else score += stones[object - 10].value; draw_worlds(score, target_score, time0, time1, pass_count); draw_gold_and_stone(golds, gold_count, stones, stone_count); draw_hook(x0, y0, jiaodu); } } } } FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); } FlushBatchDraw(); Sleep(100); time1 = time(NULL); if (time1 - time0 > time_limit) { time_flag = false; break; } cleardevice(); if (jiaodu <= -pi / 4)// 控制钩子左右摆动的逻辑,如果钩子摆到最左端(-45度),改变方向向右摆 flag = true; if (jiaodu >= pi * 3 / 4) flag = false; if (flag) jiaodu += pi / 18; else jiaodu -= pi / 18; } if (score < target_score) break; else { target_score += 600; pass_count++; } } EndBatchDraw(); getch(); closegraph(); }给这个黄金矿工做个开始游戏界面
最新发布
09-05
import pygame import sys import numpy as np import time from pygame.locals import QUIT, KEYDOWN, MOUSEBUTTONDOWN import random import threading # 初始化pygame pygame.init() screen = pygame.display.set_mode((670, 670)) screen_color = [238, 154, 73] # 棋盘背景色 line_color = [0, 0, 0] # 棋盘线颜色 over_pos = [] # 已落子位置 white_color = [255, 255, 255] # 白棋(AI) black_color = [0, 0, 0] # 黑棋(玩家) # 游戏状态 game_over = False winner = 0 thinking = False # AI思考标志 # 评分常量 EMPTY = 0 PLAYER = 1 # 玩家 AI = 2 # AI INF = float('inf') # 更精细的棋型评分表 FIVE = 10000000 # 五连 OPEN_FOUR = 100000 # 活四 FOUR = 10000 # 冲四 OPEN_THREE = 1000 # 活三 THREE = 200 # 眠三 OPEN_TWO = 100 # 活二 TWO = 10 # 眠二 BLOCKED = -1 # 被阻挡的位置 # 威胁级别 THREAT_LEVEL = { FIVE: 100, OPEN_FOUR: 90, FOUR: 80, OPEN_THREE: 70, THREE: 40, OPEN_TWO: 20, TWO: 5 } def check_win(over_pos): """检查是否有玩家获胜""" mp = np.zeros([15, 15], dtype=int) for val in over_pos: x = int((val[0][0] - 27) / 44) y = int((val[0][1] - 27) / 44) if val[1] == white_color: mp[x][y] = AI else: mp[x][y] = PLAYER directions = [[1, 0], [0, 1], [1, 1], [1, -1]] # 水平、垂直、对角线、反对角线 for i in range(15): for j in range(15): if mp[i][j] == 0: continue player = mp[i][j] for dx, dy in directions: count = 1 line = [[i, j]] # 正向检查 for k in range(1, 5): x = i + k * dx y = j + k * dy if 0 <= x < 15 and 0 <= y < 15 and mp[x][y] == player: count += 1 line.append([x, y]) else: break # 反向检查 for k in range(1, 5): x = i - k * dx y = j - k * dy if 0 <= x < 15 and 0 <= y < 15 and mp[x][y] == player: count += 1 line.insert(0, [x, y]) else: break if count >= 5: return [player, line] return [0, []] def find_pos(x, y): """将鼠标位置转换为棋盘坐标""" for i in range(27, 670, 44): for j in range(27, 670, 44): if abs(x - i) <= 22 and abs(y - j) <= 22: return i, j return x, y def check_over_pos(x, y, over_pos): """检查位置是否已有棋子""" for val in over_pos: if val[0][0] == x and val[0][1] == y: return False return True def get_line_score(line, player): """计算一行棋型的分数""" score = 0 count = 0 # 连续棋子数 open_ends = 0 # 开放端数量 block_ends = 0 # 封闭端数量 # 检查连续性和开放端 for i in range(len(line)): if line[i] == player: count += 1 elif line[i] == EMPTY: if i > 0 and i < len(line) - 1: open_ends += 1 else: block_ends += 1 else: # 对手棋子 block_ends += 1 break # 根据棋型评分 if count >= 5: return FIVE elif count == 4: if open_ends >= 2: return OPEN_FOUR elif open_ends == 1: return FOUR elif count == 3: if open_ends >= 2: return OPEN_THREE elif open_ends == 1: return THREE elif count == 2: if open_ends >= 2: return OPEN_TWO elif open_ends == 1: return TWO return score def evaluate_position(mp, x, y, player): """评估位置的价值 - 改进版""" if not (0 <= x < 15 and 0 <= y < 15) or mp[x][y] != EMPTY: return 0 opponent = PLAYER if player == AI else AI score = 0 # 检查四个方向: 水平、垂直、两条对角线 directions = [[(0, 1), (0, -1)], # 水平 [(1, 0), (-1, 0)], # 垂直 [(1, 1), (-1, -1)], # 主对角线 [(1, -1), (-1, 1)]] # 反对角线 for dir_pair in directions: # 获取整个方向的棋型 line = [] for dx, dy in [(-1, -1), (0, 0), (1, 1)]: # 扩展为3个点的窗口 for i in range(-4, 5): # 检查9个点的窗口 nx, ny = x + dx * i, y + dy * i if 0 <= nx < 15 and 0 <= ny < 15: line.append(mp[nx][ny]) else: line.append(BLOCKED) # 边界阻挡 # 计算该方向的分数 dir_score = get_line_score(line, player) # 检查对手的威胁 opponent_score = get_line_score(line, opponent) if opponent_score >= OPEN_THREE: # 优先防守对手的威胁 dir_score += opponent_score * 1.5 score += dir_score # 位置加成:中心位置更有价值 center_x, center_y = 7, 7 distance = abs(x - center_x) + abs(y - center_y) center_bonus = max(0, 50 - distance * 5) score += center_bonus return score def evaluate_board(mp): """评估整个棋盘状态""" ai_score = 0 player_score = 0 # 评估AI的分数 for i in range(15): for j in range(15): if mp[i][j] == EMPTY: ai_score += evaluate_position(mp, i, j, AI) # 评估玩家的分数 for i in range(15): for j in range(15): if mp[i][j] == EMPTY: player_score += evaluate_position(mp, i, j, PLAYER) # AI进攻与防守的权重 return ai_score * 1.2 - player_score * 1.1 def get_valid_moves(mp): """获取有效的移动位置 - 改进版""" moves = [] # 只考虑已落子周围的位置,减少搜索空间 if not over_pos: # 若棋盘为空,返回中心位置 return [(27 + 44 * 7, 27 + 44 * 7)] # 找到所有已落子位置 occupied = set() for pos in over_pos: x = int((pos[0][0] - 27) / 44) y = int((pos[0][1] - 27) / 44) occupied.add((x, y)) # 考虑已落子周围的空位 directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]] candidate = set() for (x, y) in occupied: for dx, dy in directions: nx, ny = x + dx, y + dy if 0 <= nx < 15 and 0 <= ny < 15 and (nx, ny) not in occupied: candidate.add((nx, ny)) # 转换为棋盘坐标并评估分数 scored_moves = [] for (x, y) in candidate: # 评估进攻价值 attack_score = evaluate_position(mp, x, y, AI) # 评估防守价值 defense_score = evaluate_position(mp, x, y, PLAYER) # 综合评分:进攻和防守的平衡 total_score = attack_score + defense_score * 0.8 scored_moves.append((total_score, x, y)) # 按分数排序 scored_moves.sort(reverse=True) # 取前12个最佳位置 return [(x * 44 + 27, y * 44 + 27) for (score, x, y) in scored_moves[:12]] def minimax(mp, depth, alpha, beta, is_maximizing, start_time, time_limit=1.0): """带Alpha-Beta剪枝的Minimax算法 - 改进版""" # 检查超时 if time.time() - start_time > time_limit: return None, None res = check_win(over_pos) if res[0] == AI: return INF, None elif res[0] == PLAYER: return -INF, None if depth == 0: return evaluate_board(mp), None valid_moves = get_valid_moves(mp) if not valid_moves: return 0, None best_move = None if is_maximizing: max_score = -INF for move in valid_moves: # 检查超时 if time.time() - start_time > time_limit: return None, None x = int((move[0] - 27) / 44) y = int((move[1] - 27) / 44) if mp[x][y] != EMPTY: continue mp[x][y] = AI over_pos.append([move, white_color]) score, _ = minimax(mp, depth - 1, alpha, beta, False, start_time, time_limit) mp[x][y] = EMPTY over_pos.pop() if score is None: # 超时 return None, None if score > max_score: max_score = score best_move = move alpha = max(alpha, score) if beta <= alpha: break # Beta剪枝 return max_score, best_move else: min_score = INF for move in valid_moves: # 检查超时 if time.time() - start_time > time_limit: return None, None x = int((move[0] - 27) / 44) y = int((move[1] - 27) / 44) if mp[x][y] != EMPTY: continue mp[x][y] = PLAYER over_pos.append([move, black_color]) score, _ = minimax(mp, depth - 1, alpha, beta, True, start_time, time_limit) mp[x][y] = EMPTY over_pos.pop() if score is None: # 超时 return None, None if score < min_score: min_score = score best_move = move beta = min(beta, score) if beta <= alpha: break # Alpha剪枝 return min_score, best_move def ai_move(over_pos): """AI决策函数 - 改进版""" if not over_pos: # 第一步下在中心 return [(27 + 44 * 7, 27 + 44 * 7), white_color] # 创建棋盘状态 mp = np.zeros([15, 15], dtype=int) for val in over_pos: x = int((val[0][0] - 27) / 44) y = int((val[0][1] - 27) / 44) if val[1] == white_color: mp[x][y] = AI else: mp[x][y] = PLAYER # 检查是否有立即获胜的机会 for i in range(15): for j in range(15): if mp[i][j] == EMPTY: # 检查AI是否可以立即获胜 mp[i][j] = AI res = check_win([[(i * 44 + 27, j * 44 + 27), white_color]] + over_pos) mp[i][j] = EMPTY if res[0] == AI: return [(i * 44 + 27, j * 44 + 27), white_color] # 检查玩家威胁 mp[i][j] = PLAYER res = check_win([[(i * 44 + 27, j * 44 + 27), black_color]] + over_pos) mp[i][j] = EMPTY if res[0] == PLAYER: # 必须防守这个位置 return [(i * 44 + 27, j * 44 + 27), white_color] # 使用Minimax搜索最佳移动 depth = 4 # 搜索深度 start_time = time.time() time_limit = 1.0 # 最多思考1秒 # 使用迭代加深搜索 best_move = None best_score = -INF for current_depth in range(1, depth + 1): score, move = minimax(mp, current_depth, -INF, INF, True, start_time, time_limit) # 检查是否超时 if score is None: break if score > best_score: best_score = score best_move = move # 检查剩余时间 if time.time() - start_time > time_limit * 0.8: break if best_move: return [best_move, white_color] else: # 如果找不到最佳移动,选择评分最高的位置 valid_moves = get_valid_moves(mp) if valid_moves: return [valid_moves[0], white_color] return None # 选择游戏模式 game_mode = None while game_mode not in ['P_vs_P', 'P_vs_ai']: print("请选择游戏模式:") print("1. 人与人对战") print("2. 人与 AI 对战") choice = input("输入 1 或 2 选择模式:") if choice == '1': game_mode = 'P_vs_P' elif choice == '2': game_mode = 'P_vs_ai' class Gomoku: def __init__(self, mode): self.mp = [[0] * 15 for _ in range(15)] self.game_mode = mode self.last_draw_time = time.time() self.ai_thinking = False self.ai_move_result = None self.ai_thread = None def draw_board(self): """绘制棋盘和棋子""" screen.fill(screen_color) # 绘制棋盘 for i in range(27, 670, 44): pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 4 if i in [27, 670 - 27] else 2) pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 4 if i in [27, 670 - 27] else 2) pygame.draw.circle(screen, line_color, [27 + 44 * 7, 27 + 44 * 7], 8) # 绘制棋子 for val in over_pos: pygame.draw.circle(screen, val[1], val[0], 20) # 判断胜负 if game_over and winner != 0: for pos in winner_line: x, y = pos[0] * 44 + 27, pos[1] * 44 + 27 pygame.draw.rect(screen, [238, 48, 167], [x - 22, y - 22, 44, 44], 2) # 显示胜利信息 font = pygame.font.SysFont(None, 55) if winner == PLAYER: text = font.render("玩家胜利!", True, (255, 0, 0)) else: text = font.render("AI胜利!", True, (255, 0, 0)) screen.blit(text, (250, 300)) # 显示AI思考状态 if self.ai_thinking: font = pygame.font.SysFont(None, 36) text = font.render("AI思考中...", True, (50, 50, 200)) screen.blit(text, (270, 10)) def handle_ai_turn(self): """处理AI回合""" global over_pos, game_over, winner, winner_line if not self.ai_thinking: self.ai_thinking = True # 创建新线程执行AI计算 self.ai_thread = threading.Thread(target=self.ai_thread_func) self.ai_thread.start() # 检查AI计算是否完成 if self.ai_move_result is not None: over_pos.append(self.ai_move_result) self.ai_move_result = None self.ai_thinking = False # 检查AI是否获胜 res = check_win(over_pos) if res[0] != 0: game_over = True winner = res[0] winner_line = res[1] def ai_thread_func(self): """AI计算线程函数""" self.ai_move_result = ai_move(over_pos) def play(self): global over_pos, game_over, winner, winner_line clock = pygame.time.Clock() while True: # 处理事件队列 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() elif event.key == pygame.K_r: # 重新开始 over_pos = [] game_over = False winner = 0 self.ai_thinking = False self.ai_move_result = None elif event.type == MOUSEBUTTONDOWN and event.button == 1 and not game_over: # 玩家回合 if self.game_mode == 'P_vs_P' or (self.game_mode == 'P_vs_ai' and len(over_pos) % 2 == 0): x, y = pygame.mouse.get_pos() x, y = find_pos(x, y) if check_over_pos(x, y, over_pos): over_pos.append([[x, y], black_color if len(over_pos) % 2 == 0 else white_color]) # 检查玩家是否获胜 res = check_win(over_pos) if res[0] != 0: game_over = True winner = res[0] winner_line = res[1] # 检查是否需要AI回合 if not game_over and self.game_mode == 'P_vs_ai' and len(over_pos) % 2 == 1: self.handle_ai_turn() # 绘制棋盘 self.draw_board() pygame.display.update() # 控制帧率 clock.tick(60) # 全局变量 game_over = False winner = 0 winner_line = [] # 创建游戏实例并开始游戏 game = Gomoku(game_mode) game.play() 帮我完善ai,让他更加聪明,甚至比人还聪明,优化不足的地方,然后输出完整代码给我
08-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值