C语言——五子棋人机对战
#include<stdio.h>
#include<windows.h>#define TRUE 1
#define FALSE 0struct position {int x;int y;int score;
};char chess_board[16][16];
struct position positions[50];
int position_order;void initialize_board(void)
{int i, j;for (i = 0;i < 16;i++) {for (j = 0;j < 16;j++) {chess_board[i][j] = ' ';}}
}
void initial_positions(void)
{positions[0].x = positions[0].y = positions[0].score = 0;for (position_order = 1;position_order < 50;position_order++) {positions[position_order] = positions[0];}position_order = 0;
}
void print_board(void)
{int i, j;/*print letters*/printf(" ");for (j = 0;j < 16;j++) {printf(" %c", 'A' + j);}putchar('\n');/*print chess board*/for (i = 0;i < 33;i++) {if (i % 2 == 1) {printf("%2d", (i + 1) / 2);}else {printf(" ");}for (j = 0;j < 33;j++) {/*The first row*/if (i == 0 && j == 0) {printf("┌ ");}else if (i == 0 && j==32) {printf("┐");}else if (i == 0 && j % 2 == 0) {printf("┬ ");}/*The last row*/if (i == 32 && j == 0) {printf("└ ");}else if (i == 32 && j == 32) {printf("┘");}else if (i == 32 && j % 2 == 0) {printf("┴ ");}/*The other rows*/if (i != 0 && i != 32) {if (i % 2 == 0) {if (j == 0) {printf("├ ");}else if (j == 32) {printf("┤");}else if (j % 2 == 0) {printf("┼ ");}}else if(j % 2 == 0) {printf(" %c", chess_board[(i - 1) / 2][(j + 1) / 2]);}}}putchar('\n');}
}
int is_full(void) {int i, j;for (i = 0;i < 16;i++) {for (j = 0;j < 16;j++) {if (chess_board[i][j] == ' ')return(FALSE);}}return(TRUE);
}
void is_win(int x, int y, char cp)
{int i, num=0;/*row*/for (i = 0;chess_board[y][x + i] == cp;i++, num++);for (i = -1;chess_board[y][x + i] == cp;i--, num++);if (num >= 5) {system("cls");print_board();printf("%c win!", cp);system("pause");}else {num = 0;}for (i = 0;chess_board[y + i][x] == cp;i++, num++);for (i = -1;chess_board[y + i][x] == cp;i--, num++);if (num >= 5){system("cls");print_board();printf("%c win!", cp);system("pause");}else {num = 0;}for (i = 0;chess_board[y + i][x + i] == cp;i++, num++);for (i = -1;chess_board[y + i][x + i] == cp;i--, num++);if (num >= 5) {system("cls");print_board();printf("%c win!", cp);system("pause");}else {num = 0;}for (i = 0;chess_board[y + i][x - i] == cp;i++, num++);for (i = -1;chess_board[y + i][x - i] == cp;i--, num++);if (num >= 5) {system("cls");print_board();printf("%c win!", cp);system("pause");}else {num = 0;}
}
void scan(void)
{char c;int i;do {printf("输入落子行列:");scanf_s("%d%c", &i, &c);if (!(chess_board[i - 1][c - 'A'] == ' '))continue;chess_board[i - 1][c - 'A'] = '*';break;} while (TRUE);is_win(c - 'A', i - 1, '*');
}
贴一张实际效果图:
![](/assets/blank.gif)
(2)感知:
这一步中,将遍历棋盘中所有可落子位置,从横,纵,右斜和左斜四个方向,以棋子状态进行评分,总后将有效位置的总分记录在数组中。
下面先贴出的是评分函数,其接受一个大小为5的字符数组(记录在选定位置周围截取的包含该位置的”一行“棋子状态),一个描述选定位置在该行中的位置的参数x。内部由若干分支构成,对应每种棋子状态,返回对该状态的评分。
void reverse(char row[],int len) //由于一行棋子具有对称性,故x=3,x=4的状态可翻转归结为x=0,x=1的状态
{char temp;int i,j;for (i = 0, j = len - 1;i <= j;i++, j--) {temp = row[i];row[i] = row[j];row[j] = temp;}
}
int score(char row[], int x) //'O'代表白棋,'*'代表黑棋,人执黑,机器执白
{ //每个if分支后的注释,'_'代表空格(即可落子处),'O'为白棋,'*'为黑棋if (x > 2) { //'?'表示已可给分,该位置状态不必获取reverse(row,5); //三者的排布代表截取行的棋子状态
x = 4 - x; //紧接着的return,返回的便是对该位置的评分}switch (x) {case 0: {if (row[1] == 'O' && (row[2] == 'O' || row[2] == ' ') && (row[3] == 'O' || row[3] == ' ') && (row[4] == 'O' || row[4] == ' ')) {if (row[x + 2] == ' ') { //_O_??return(15);}else if (row[x + 3] == ' ') { //_OO_?return(50);}else if (row[x + 4] == ' ') { //_OOO_return(90);}else { //_OOOOreturn(1000);}}else if (row[1] == '*' && (row[2] == '*' || row[2] == ' ') && (row[3] == '*' || row[3] == ' ') && (row[4] == '*' || row[4] == ' ')) {if (row[x + 2] == ' ') { //_*_??return(5);}else if (row[x + 3] == ' ') { //_**_?return(30);}else if (row[x + 4] == ' ') { //_***_return(70);}else { //_****return(500);}}};break;case 1: {if ((row[0] == 'O' || row[0] == ' ') && (row[2] == 'O' || row[2] == ' ') && (row[3] == 'O' || row[3] == ' ') && (row[4] == 'O' || row[4] == ' ')) {if (row[0] == 'O') {if (row[2] == ' ') { //O_ _??return(15);}else if (row[3] == ' ') { //O_O_??return(50);}else if (row[4] == ' ') { //O_OO_return(90);}else { //O_OOOreturn(1000);}}else if (row[2] == ' ') { //_ _ _??return(0);}else if (row[3] == ' ') { //_ _O_?return(15);}else if (row[4] == ' ') { //_ _OO_return(50);}else { //_ _OOOreturn(80);}}else if ((row[0] == '*' || row[0] == ' ') && (row[2] == '*' || row[2] == ' ') && (row[3] == '*' || row[3] == ' ') && (row[4] == '*' || row[4] == ' ')) {if (row[0] == '*') {if (row[2] == ' ') { //*_ _??return(5);}else if (row[3] == ' ') { //*_*_?return(30);}else if (row[4] == ' ') { //*_**_return(70);}else { //*_***return(500);}}else if (row[2] == ' ') { //_ _ _??return(0);}else if (row[3] == ' ') { //_ _*_?return(5);}else if (row[4] == ' ') { //_ _**_return(30);}else { //_ _***return(60);}}}break;case 2: {if ((row[0] == 'O' || row[0] == ' ') && (row[1] == 'O' || row[2] == ' ') && (row[3] == 'O' || row[3] == ' ') && (row[4] == 'O' || row[4] == ' ')) {if (row[1] == 'O') {if (row[3] == 'O') {if (row[0] == 'O') {if (row[4] == 'O') {//OO_OOreturn(1000);}else {return(90); //OO_O_}}else {if (row[4] == 'O') {//_O_OOreturn(90);}else { //_O_O_return(50);}}}else {if (row[0] == 'O') { //OO_ _?return(40);}else { //_O_ _?return(15);}}}else {if (row[3] == 'O') {if (row[4] == 'O') { //_ _ _OOreturn(40);}else { //_ _ _O_return(15);}}}}else if ((row[0] == '*' || row[0] == ' ') && (row[1] == '*' || row[2] == ' ') && (row[3] == '*' || row[3] == ' ') && (row[4] == '*' || row[4] == ' ')) {if (row[1] == '*') {if (row[3] == '*') {if (row[0] == '*') {if (row[4] == '*') {//**_**return(500);}else { //**_*_return(70);}}else {if (row[4] == '*') {//_*_**return(70);}else { //_*_*_return(30);}}}else {if (row[0] == '*') { //**_ _ _return(20);}else { //_*_ _?return(5);}}}else {if (row[3] == '*') { //_ _ _**if (row[4] == '*') {return(20);}else { //_ _ _*_return(5);}}}}}break;}return(0);
}
接下来呢,就是感知中的另一个主要部分,其功能是对某一位置,从四个方向,截取评分函数所需的一行五位置数组。
int sense_row(int x, int y) //横向截取,如下列一排示例中,x,y所代表的位置是第五个O
{ //[OOOOO]OOOO,O[OOOOO]OOO,OO[OOOOO]OO......如此这般依次截取,其余方向类似int sum = 0, i, j;char row[5];for (i = x - 4;i <= x;i++) {if (!(i >= 0 && i + 4 <= 15)) {continue;}else {for (j = 0;j < 5;j++) {row[j] = chess_board[y][i + j];}sum += score(row, x - i);}}return(sum);
}
int sense_col(int x, int y)
{int sum = 0, i, j;char row[5];for (i = y - 4;i <= y;i++) {if (!(i >= 0 && i + 4 <= 15)) {continue;}else {for (j = 0;j < 5;j++) {row[j] = chess_board[i + j][x];}sum += score(row, y - i);}}return(sum);
}
int sense_right_bias(int x, int y)
{int sum = 0, i, j;char row[5];for (i = -4;i <= 0;i++) {if (!(y + i >= 0 && x + i >= 0 && y + i + 4 <= 15 && x + i + 4 <= 15)) {continue;}else {for (j = 0;j < 5;j++) {row[j] = chess_board[y + i + j][x + i + j];}sum += score(row, -i);}}return(sum);
}
int sense_left_bias(int x, int y)
{int sum = 0, i, j;char row[5];for (i = -4;i <= 0;i++) {if (!(y - i <= 15 && x + i >= 0 && y - i - 4 >= 0 && x + i + 4 <= 15)) {continue;}else {for (j = 0;j < 5;j++) {row[j] = chess_board[y - i - j][x + i + j];}sum += score(row, -i);}}return(sum);
}
void sense(void) //将四个方向上的评分综合并记录
{int x, y, sum = 0;initial_positions();for (y = 0;y < 16;y++) {for (x = 0;x < 16;x++) {if (chess_board[y][x] != ' ') {continue;}sum += sense_col(x, y);sum += sense_row(x, y);sum += sense_left_bias(x, y);sum += sense_right_bias(x, y);if (sum != 0) {positions[position_order].score = sum;positions[position_order].x = x;positions[position_order].y = y;position_order++;sum = 0;}}}
}
void think_act(void)
{int max = 0, max_order, i;for (i = 0;i < position_order;i++) {if (positions[i].score > max) {max = positions[i].score;max_order = i;}}chess_board[positions[max_order].y][positions[max_order].x] = 'O';is_win(positions[max_order].x, positions[max_order].y, 'O');
}
void main(void)
{initialize_board();print_board();while (!is_full()) {scan();sense();think_act();system("CLS");print_board();}system("pause");
}
C语言——五子棋人机对战相关推荐
- C语言 AI智能,五子棋 人机对战,人人对战
C语言五子棋,人机对战,人人对战 chunli@Linux:~$ cat main.c # include<stdio.h> # include<string.h> # inc ...
- 五子棋程序设计(C语言、人机对战、禁手)
五子棋程序设计(C语言.人机对战.禁手) 一.程序需求分析 1.1五子棋简介 五子棋是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏. 五子棋有两种玩法.玩法一:双方分别使用黑白两色的棋 ...
- C#实现五子棋人机对战的思路与源码分享
前言 业余闲暇时,基于.netframework使用C#语言开发了一个五子棋人机对战的游戏,在此做些整理和分享,先上图. winform版 UI虽然很简洁,却花了些功夫,图形元素全动态生成,毕竟不是美 ...
- java五子棋人机对战_实现简单的人机对战五子棋(实践)
五子棋人机对战实践项目 总的任务和目标 完成一个人机对战的五子棋项目,基本效果如下: 第一部分 Java绘图原理 1. 基本概念 像素,坐标 2. 组件自定义绘图原理 3. Graphic ...
- 五子棋人机对战_10.带人机对战的五子棋程序
今天我们带来一个带人机对战功能的五子棋程序.程序基于前面文章中的框架搭建,新增人机对战的策略.程序基于规则进行决策,不考虑禁手,玩家执黑子先行.棋盘规模采用15乘15,棋盘规模容易扩展,程序棋力中等, ...
- 人工智能 - 五子棋人机对战
人工智能 - 五子棋人机对战 作者: jig 阅读人次: 6635 文章来源:本站原创 发布时间:2007-7-12 网友评论(8)条 原帖及讨论:http://bbs.bc ...
- c语言五子棋人机对弈算法,使用canvas基于AI算法实现人机对战之五子棋
这是我使用canvas基于AI算法实现的人机对战之五子棋 黑棋是我 下了几局,真心下不过啊!!! 不说了,源码奉上: 人机大战之五子棋 canvas{ display: block; margin:5 ...
- c语言五子棋人机对弈算法_从零开始编写C语言五子棋程序1
从零开始编写C语言五子棋程序 C语言程序是国科大计算机系本科生必修课程,我选修的是武成岗老师的C语言课程.除了课上回答问题,实验课competitive programming的成绩之外,最终的大作业 ...
- C语言五子棋--人机对弈--人人对弈
C语言五子棋: 注:直接可以运行使用的代码,家人们的点赞在哪里 第一次实现可以进行人机对战的五子棋,分享下,难度不大.都是按照模块来写的,封装成了很多个函数,比较细致,新手还是可以看懂的.主要可以实现 ...
最新文章
- DataLoader 与 Dataset
- linux下仅仅有rman备份集的异机不同文件夹恢复
- 138个被撤出EI检索的会议
- Python翻译Excel文件
- 关于MinGW和MSYS
- win7虚拟机详细搭建过程
- 高阶篇:4.2.5)DFMEA建议措施及后续完备
- Spark写入Hudi报分区列乱码问题java.net.URISyntaxException: Illegal character in path at index 46:
- 2008年世界各国最新GDP排名
- Metaverse 元宇宙入门-02-Hardware 硬件与元宇宙
- K8s学习之yum安装
- 区块链/BlockChain+ProofOfWork
- 金刚菩提子开裂自动修复此计算机,教你一招修复开裂的金刚菩提
- IEEE论文搜索方法
- 计算机图形学之纹理的作用
- 章节十二:编程思维:如何debug
- 计算机教师面试专业技能部分,教师招聘考试面试,专业技能测试考什么?全在这了...
- 如何在跳槽前客观地评估自己的身价?
- Windows_XP DLL修改
- MySQL基本语句(燕十八部分)
热门文章
- 实习小白::(转) Cocos2d-x 3.0 开发(八)骨骼动画的动态换肤
- 各平台播放器以及浏览器的navigator.userAgent
- [python]...
- 微信dnf手游服务器上限,DNF手游:服务器跨区规则上线,玩家扎堆进一区,团本互通...
- 曾哥传——番外篇(一)曾哥无敌
- 极速办公(word)插入的表格如何修改文字方向
- @NotNull和@NotBlank的区别
- GPS 凯立德 J08 没声音的问题解决
- 奥兹国的奇妙术士-对话系统收集数据的方法
- Python Day13 面向对象基础【初级】