三子棋具体就不多介绍了,AI棋用O表示,我们的棋用X表示。先手后手自己选。这里主要说一下AI算法。首先AI会对整个棋盘MAP[3][3]进行遍历,每个格子都有一个权值weight[i][j]。权值的第一次计算方法是对每一行i每一列j进行计算,计算基于这一格有几种获胜的路线。例如没有走时,9个格的权值为:
[][][] 3 2 3
[][][] 2 4 2
[][][] 3 2 3
角落有横竖斜三种获胜方法,边有横竖两种方法,中心有横竖两斜4种方法。假如某格有X阻挡,那么权值会相应变化,例如
[][][] 2 1 2
[]X[] 1 0 1
[][][] 2 1 2
由于有中心阻挡,那么角只有横竖两种方法赢,因此权值为2。但该AI还需继续优化。例如以下:
[]X[] 1 0 1
[]0[] 1 0 2
XX0 0 0 0
AI面对这种情况,本来下在第一个格子就赢了,但他会选择权值为2的格子。因此我们可以在现有权值条件的情况下,在附加个权值。假如某一格子的路线上已经有AI的子了,那么该条路线上未落子的所有格子权值再加1,如果有两个已落子的AI格子权值就加2。例如以下情况:
原权值 优化权值
[]X[] 2 0 2 5 0 3
[]0[] 2 0 2 3 0 4
[]X0 2 0 0 3 0 0
第一个格子5是由于斜路线上有两个子,那在原有的基础2上先加1,再加2,所以权值为2+1+2。第2行第3列权值为4,因为横竖两条路线均有1个子,因此权值为2+1+1,其余格子路线上均有1个子,因此权值为2+1。这样落在权值5那个格子上AI就赢了。但是仅仅这些判断是不够的。例如:
初始 优化
X[]X 0 1 0 0 2 0
[]0[] 1 0 1 2 0 2
[][]0 1 2 0 2 4 0
AI会选择权值为4的格子。那此时AI选择权值为2的格子时,你只需要走一步就赢了,AI就输了,因此该AI算法还得继续。
那么AI可以逆向思考一番,AI可以考虑一下当前情况在计算AI权值的同时再计算一次我们的权值。例如上面例子:
AI权值 你的权值 优化AI 优化你
X[]X 0 1 0 0 1 0 0 2 0 0 4 0
[]0[] 1 0 1 1 0 0 2 0 2 2 0 0
[][]0 1 2 0 1 0 0 2 4 0 2 0 0
我们把两个权值相加(另外把AI的权值应该再加1,因为AI判断赢要优先于输或平,假如AI方有权值大的,代表一步能赢的,我方也有这种情况,那相加权值相同,AI既可以选择赢棋那一格,也可以选择堵你将要赢的那一格。但AI判断赢要优先于堵对方赢。例子就不举了):
相加权值 再加1权值
X[]X 0 6 0 0 7 0
[]0[] 4 0 2 5 0 3
[][]0 4 4 0 5 4 0
因此AI判断到这里就会堵你了。
AI算法就介绍到这里,至于三子棋程序,由于过于简单,就不过多介绍了。主要介绍AI思想,Windows系统编译的程序。如果是Linux需要把以下代码改下。接下来我就贴上代码,供参考,如有不懂欢迎留言。
project.h
#pragma once
#define COLUMN 3
#define ROW 3
#define GOON 0
#define WIN -1
#define DEFEAT 1
void init(char(*MAP)[COLUMN]);
int victory(char(*MAP)[COLUMN]);
bool check(char(*MAP)[COLUMN]);
void show(char(*MAP)[COLUMN]);
void check_stemp(char(*MAP)[COLUMN], int *x, int *y);
void ai_auto(char(*MAP)[COLUMN]);
int menu();
int first_hand(char(*MAP)[COLUMN]);
int ai_hand(char(*MAP)[COLUMN]);
void play(char(*MAP)[COLUMN]);
project.c
#include
#include
#include
#include"project.h"
int vis[ROW][COLUMN];
int weight[ROW][COLUMN];
int x, y;
void init(char(*MAP)[COLUMN]) {
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COLUMN; j++) {
MAP[i][j] = ' ';
vis[i][j] = 0;
}
}
int victory(char(*MAP)[COLUMN]) {
for (int i = 0; i < 3; i++) {
if (MAP[i][0] == 'X'&&MAP[i][1] == 'X'&&MAP[i][2] == 'X')
return WIN;
else if (MAP[i][0] == 'O'&&MAP[i][1] == 'O'&&MAP[i][2] == 'O')
return DEFEAT;
if (MAP[0][i] == 'X'&&MAP[1][i] == 'X'&&MAP[2][i] == 'X')
return WIN;
else if (MAP[0][i] == 'O'&&MAP[1][i] == 'O'&&MAP[2][i] == 'O')
return DEFEAT;
}
if (MAP[0][0] == 'X'&&MAP[1][1] == 'X'&&MAP[2][2] == 'X')
return WIN;
else if (MAP[0][0] == 'O'&&MAP[1][1] == 'O'&&MAP[2][2] == 'O')
return DEFEAT;
if (MAP[0][2] == 'X'&&MAP[1][1] == 'X'&&MAP[2][0] == 'X')
return WIN;
else if (MAP[0][2] == 'O'&&MAP[1][1] == 'O'&&MAP[2][0] == 'O')
return DEFEAT;
return GOON;
}
bool check(char(*MAP)[COLUMN]) {
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COLUMN; j++)
if (!vis[i][j])
return false;
return true;
}
void show(char(*MAP)[COLUMN]) {
printf("-------------\n");
for (int i = 0; i < ROW; i++) {
printf("|");
for (int j = 0; j < COLUMN; j++) {
printf(" %c ", MAP[i][j]);
printf("|");
}
printf("\n");
printf("-------------\n");
}
}
void check_stemp(char(*MAP)[COLUMN], int *x, int *y) {
while (*x > 3 || *x <= 0 || *y>3 || *y <= 0 || MAP[*y - 1][*x - 1] != ' ') {
system("cls");
show(MAP);
printf("Input error, please reenter!\n");
scanf("%d%d", x, y);
}
MAP[*y - 1][*x - 1] = 'X';
vis[*y - 1][*x - 1] = 1;
}
void Empowerment(char(*MAP)[COLUMN], int(*weight)[COLUMN], char ai_X, char ai_0, int flag) {
for (int i = 0; i < 3; i++) {
if (MAP[i][0] != ai_X&&MAP[i][1] != ai_X&&MAP[i][2] != ai_X) {
weight[i][0]++;
weight[i][1]++;
weight[i][2]++;
int tmp = 1;
for (int j = 0; j < 3; j++)
if (MAP[i][j] == ai_0) {
weight[i][0] += tmp+flag;
weight[i][1] += tmp+flag;
weight[i][2] += tmp+flag;
tmp += 10;
}
}
if (MAP[0][i] != ai_X&&MAP[1][i] != ai_X&&MAP[2][i] != ai_X) {
weight[0][i]++;
weight[1][i]++;
weight[2][i]++;
int tmp = 1;
for (int j = 0; j < 3; j++)
if (MAP[j][i] == ai_0) {
weight[0][i] += tmp+flag;
weight[1][i] += tmp+flag;
weight[2][i] += tmp+flag;
tmp += 10;
}
}
}
if (MAP[0][0] != ai_X&&MAP[1][1] != ai_X&&MAP[2][2] != ai_X) {
weight[0][0]++;
weight[1][1]++;
weight[2][2]++;
int tmp = 1;
for (int j = 0; j < 3; j++)
if (MAP[j][j] == ai_0) {
weight[0][0] += tmp+flag;
weight[1][1] += tmp+flag;
weight[2][2] += tmp+flag;
tmp += 10;
}
}
if (MAP[0][2] != ai_X&&MAP[1][1] != ai_X&&MAP[2][0] != ai_X) {
weight[0][2]++;
weight[1][1]++;
weight[2][0]++;
int tmp = 1;
for (int j = 0; j < 3; j++)
if (MAP[j][2 - j] == ai_0) {
weight[0][2] += tmp+flag;
weight[1][1] += tmp+flag;
weight[2][0] += tmp+flag;
tmp += 10;
}
}
}
void ai_auto(char(*MAP)[COLUMN]) {
int weight[3][3] = { 0 };
Empowerment(MAP, weight, 'X', 'O', 1);
Empowerment(MAP, weight, 'O', 'X', 0);
int maxn = -1;
int maxm = -1;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
if (vis[i][j])
weight[i][j] = -1;
if (maxn < weight[i][j]) {
maxn = weight[i][j];
maxm = i * 3 + j;
}
}
MAP[maxm / 3][maxm % 3] = 'O';
vis[maxm / 3][maxm % 3] = 1;
}
int menu() {
int tmp;
printf("*************************************************************\n");
printf("* Please enter: * 1:First hand * 2.Back hand * Others:Close *\n");
printf("*************************************************************\n");
scanf("%d", &tmp);
return tmp;
}
int first_hand(char(*MAP)[COLUMN]) {
system("cls");
show(MAP);
printf("Please enter:x y\n");
scanf("%d%d", &x, &y);
check_stemp(MAP, &x, &y);
system("cls");
show(MAP);
if (victory(MAP) == WIN) {
printf("Congratulations on your victory, you are as smart as Qianyouyou.\n");
return 1;
}
else if (check(MAP)) {
printf("Draw.As smart as me.\n");
return 1;
}
system("pause");
return 0;
}
int ai_hand(char(*MAP)[COLUMN]) {
ai_auto(MAP);
system("cls");
show(MAP);
if (victory(MAP) == DEFEAT) {
printf("You lose, you're as stupid as a pig.\n");
return 1;
}
else if (check(MAP)) {
printf("Draw.As smart as me.\n");
return 1;
}
return 0;
}
void play(char(*MAP)[COLUMN]) {
while (!check(MAP) || victory(MAP) == GOON) {
if (first_hand(MAP))
break;
if (ai_hand(MAP))
break;
}
system("pause");
}
main.c
#include
#include
#include"project.h"
char MAP[ROW][COLUMN];
int main() {
char str[2];
do {
init(MAP);
switch (menu()) {
case 1:
first_hand(MAP);
case 2: {
ai_hand(MAP);
play(MAP);
}
default: {
printf("Do you need to start again?(Y/N)");
scanf("%s", str);
}break;
}
} while (str[0] == 'Y' || str[0] == 'y');
printf("Thank you for using!\n");
system("pause");
return 0;
}