三子棋具體就不多介紹了,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<stdio.h>
#include<stdlib.h>
#include<string.h>
#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<stdio.h>
#include<stdlib.h>
#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;
}