写在前面
一个基于控制台的五子棋对战程序,融合了人机交互、AI决策与胜负判断逻辑,完整实现了五子棋游戏的核心机制。
系列文章
技术需求
- 控制台界面控制
- 使用Windows API隐藏光标,提升界面整洁度;通过
SetConsoleCursorPosition
精确控制字符输出位置,实现动态光标移动与画面刷新。 - 调用
system("mode")
设置窗口尺寸,优化棋盘布局显示效果,增强可读性与操作体验。
- 数据结构设计
- 定义
coordinate
结构体存储棋子坐标,便于历史落子追踪与AI分析;使用二维数组Map
表示棋盘状态(0为空,1为玩家,2为AI),支持快速查找与更新。 - 通过
Coor1
和Coor2
数组分别记录玩家与AI的落子序列,为后续威胁评估提供数据基础。
- AI智能决策系统
- 实现多层次评分机制:基于连子长度(2、3、4连)赋予不同权重,结合防守与进攻策略,在
Uturn
和Nturn
函数中分别评估己方与对方的潜在威胁。 - 引入
ESET
函数识别“活二”、“活三”等关键棋形,优先抢占战略要地,提升AI实战水平。 - 综合所有评分结果,选取最高分位置作为AI落子点,实现类人类的博弈思维。
- 交互逻辑与输入处理
- 利用
getch()
实现无回显即时按键响应,支持w/a/s/d
方向移动光标,空格确认落子,操作流畅直观。 - 设计菜单系统,区分先手与后手模式,满足不同玩家需求。
- 胜负判定机制
- 每回合结束后遍历所有己方棋子,在八个方向上统计连续同色棋子数量,一旦达到五子即判定胜利并结束程序。
- 判胜逻辑独立封装,确保公平性与及时响应。
- 动态更新与状态管理
- 每次操作后清屏重绘整个棋盘,保持视觉一致性;通过
Flag
标志位协调玩家与AI交替行棋,保证游戏节奏有序进行。 - 所有状态变更实时同步至
Map
数组与坐标列表,确保数据一致性。
主要代码
创作不易,订阅后可查看完整代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<time.h>
#include<conio.h>
#include<windows.h>
#include<ctime>
using namespace std;
struct coordinate{
int X,Y;
}Coor1[626],Coor2[626];
char Getin=' ';
int Map[25][25],Sum1,Sum2;
int Map1[25][25];
void No(){
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible = false;
SetConsoleCursorInfo(handle, &CursorInfo);
}
void _Coordinate_(int x,int y){
HANDLE winHandle;
COORD pos = {x,y};
winHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(winHandle,pos);
}
int Hrong(int x,int y,int n){
if(Map[x][y]==n) return 5;
}
void Nturn(){
int x1[10],y1[10];
for(int i=Sum1-1;i>=0;i--){
int x=Coor2[i].X,y=Coor2[i].Y,Emc=0;
for(int j=0;j<10;j++){x1[j]=x;y1[j]=y;}
while(Map[x1[0]][y1[0]]==2){ x1[0]++;y1[0]++;Emc++;}
if(Emc==2&&Map[x-1][y-1]==0&&Map[x1[0]][y1[0]]==0){Map1[x1[0]][y1[0]]+=5+3*Hrong(x1[0]+1,y1[0]+1,2);}
if(Emc==3&&Map[x1[0]][y1[0]]==0){Map1[x1[0]][y1[0]]+=50+90*Hrong(x1[0]+1,y1[0]+1,2);}
if(Emc==4&&Map[x1[0]][y1[0]]==0){Map1[x1[0]][y1[0]]+=500;}
Emc=0;
while(Map[x1[1]][y1[1]]==2){ x1[1]--;y1[1]++;Emc++;}
if(Emc==2&&Map[x+1][y-1]==0&&Map[x1[1]][y1[1]]==0){Map1[x1[1]][y1[1]]+=5+3*Hrong(x1[1]-1,y1[1]+1,2);}
if(Emc==3&&Map[x1[1]][y1[1]]==0){Map1[x1[1]][y1[1]]+=50+90*Hrong(x1[1]-1,y1[1]+1,2);}
if(Emc==4&&Map[x1[1]][y1[1]]==0){Map1[x1[1]][y1[1]]+=500;}
Emc=0;
……
创作流程
我设计这个五子棋程序时,心中想的不只是实现一个能下棋的程序,而是创造一个有“智慧”的对手。我希望它不仅能响应我的每一步,还能思考、预判,甚至带有一点策略上的压迫感。于是,我从最基础的棋盘搭建开始,一步步构建起这个黑白对弈的世界。
一开始,我决定用字符界面来呈现整个游戏,虽然没有图形化界面那么炫丽,但那种简洁的“╋”、“●”、“○”符号反而让我觉得更有棋盘的质感,像是在纸上对弈一般纯粹。为了让操作更自然,我引入了光标控制系统,让玩家可以用w/a/s/d
在棋盘上自由移动,空格落子,这种即时反馈让交互变得生动起来。
真正让我投入最多精力的是AI的设计。我不想让它成为一个只会随机落子的摆设,所以我构建了一套评分系统。每当轮到AI行动时,它会扫描整个棋盘,分析每一个空位的“价值”——如果这里落子能形成四子连珠,那就给高分;如果能阻止我即将形成的四子,也必须加分。我为不同的棋形设定了不同的权重,比如“活三”比“死三”更重要,“冲四”几乎等同于胜利前兆。这些判断逻辑分散在多个函数中,彼此协作,最终汇总成一张评分地图,AI只需选择分数最高的点落子。
在这个过程中,我也不断调整参数,测试AI的强弱。太强会让人挫败,太弱又失去挑战意义。我反复调试,让AI既有进攻性又不失防守意识,甚至在某些局面下会故意“放水”,制造悬念。我还加入了胜负判定机制,确保一旦五子连珠,游戏立刻结束,不给任何拖延的机会。
最让我满意的是整个程序的节奏感。玩家落子后,AI稍作“思考”便落下回应,画面刷新流畅,没有卡顿。每一次对弈都像是一场真实的较量,我能感受到那个看不见的对手在与我角力。这不仅仅是一段代码的运行,更像是一场心灵的对话——我在布局,它在破解;我在试探,它在反击。
通过这个项目,我体会到编程不仅是逻辑的堆砌,更是思维的延伸。我把自己的博弈理解注入其中,让机器学会了“下棋”。而这盘棋,每一次重开,都是新的故事。
写在后面
我是一只有趣的兔子,感谢你的喜欢!