如何利用最簡(jiǎn)單的C語(yǔ)言實(shí)現(xiàn)AI五子棋
一.如何實(shí)現(xiàn)
1.說(shuō)明:由于本文只是對(duì)初學(xué)C語(yǔ)言的人學(xué)習(xí),所以將不會(huì)涉及任何算法,電腦將采用隨機(jī)下子的方式。(后期會(huì)為大家介紹Alpha-Beta剪枝算法實(shí)現(xiàn)人工智能AI)
2.主要部分:
(1)菜單
(2)打印棋盤(pán)
(3)玩家下子
(4)電腦下子
(5)判斷輸贏
二.實(shí)現(xiàn)代碼及分析
(1)菜單的制作


運(yùn)用do…while循環(huán)調(diào)用菜單,根據(jù)用戶(hù)選擇實(shí)現(xiàn)玩游戲和退出游戲
(2)棋盤(pán)的初始化和打印
棋盤(pán)采用標(biāo)準(zhǔn)的15*15的格子,我們可以宏定義ROW和COL分別為15和15來(lái)表示行和列。

分別封裝兩個(gè)函數(shù)對(duì)棋盤(pán)進(jìn)行初始化和打印
初始化:(這里將棋盤(pán)初始化為空格,可初始化為其他)

打印棋盤(pán):

效果如下:

(3)玩家下子
void PlayerMove(char board[ROW][COL], int row, int col) {
int x, y;
while (1) {
printf("玩家走:\n");
printf("請(qǐng)輸入坐標(biāo):\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (board[x - 1][y - 1] == ' ') {
board[x - 1][y - 1] = 'O';
break;
}
else {
printf("坐標(biāo)被占用,請(qǐng)重新輸入\n");
}
}
else {
printf("坐標(biāo)非法,請(qǐng)重新輸入\n");
}
}
}
玩家下子主要采用的思路是,判斷棋盤(pán)上是否有子,已經(jīng)輸入的坐標(biāo)是否合法。
(4)電腦下子
void ComputerMove(char board[ROW][COL], int row, int col) {
int x, y;
printf("電腦走\(yùn)n");
while (1) {
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ') {
board[x][y] = 'X';
break;
}
}
}
與玩家下子相同,此處采用的隨機(jī)下子,后期可進(jìn)行優(yōu)化(比如:極大極小值算法、Alpha-Beta剪枝算法等)
(5)判斷輸贏
通過(guò)遍歷整個(gè)棋盤(pán),觀察是否有連五子情況出現(xiàn),代碼如下:
char iswin(char board[ROW][COL], int row, int col) {
//行
int ren=0,dian=0,i,j;
for (i = 0;i < row;i++) {
ren = 0;
for (j = 0;j < col;j++) {
if (board[i][j] == 'O')
ren++;
else
ren = 0;
if (ren >= 5)
return 'o';
}
}
for (i = 0;i < row;i++) {
dian = 0;
for (j = 0;j < col;j++) {
if (board[i][j] == 'X')
dian++;
else
dian = 0;
if (dian >= 5)
return 'x';
}
}
//列
ren = dian = 0;
for (i = 0;i < row;i++) {
ren = 0;
for (j = 0;j < col;j++) {
if (board[j][i] == 'O')
ren++;
else
ren = 0;
if (ren >= 5)
return 'o';
}
}
for (i = 0;i < row;i++) {
dian = 0;
for (j = 0;j < col;j++) {
if (board[j][i] == 'X')
dian++;
else
dian = 0;
if (dian >= 5)
return 'x';
}
}
//右下
ren = dian =i=j= 0;
for (int k = 0;k < row;k++) {
i = k;
j = 0;
ren = 0;
while (i < row && j < col) {
if (board[i][j] == 'O') {
ren++;
}
else {
ren = 0;
}
i++;
j++;
if (ren >= 5)
return 'o';
}
}
i = j = 0;
for (int k = 0;k < row;k++) {
i = k;
j = 0;
dian = 0;
while (i < row && j < col) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i++;
j++;
if (dian >= 5)
return 'x';
}
}
//右上
for (int k = row;k >=0;k--) {
j = col;
i = k;
ren = 0;
while (i >=0 && j >=0) {
if (board[i][j] == 'O') {
ren++;
}
else
ren = 0;
i--;
j--;
if (ren >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = col;
dian = 0;
while (i >= 0 && j >= 0) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i--;
j--;
if (dian >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = 0;
dian = 0;
while (i >= 0 && j <col) {
if (board[i][j] == 'O') {
dian++;
}
else
dian = 0;
i--;
j++;
if (dian >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = 0;
dian = 0;
while (i >= 0 && j <col) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i--;
j++;
if (dian >= 5)
return 'x';
}
}
for (int k = 0;k < row;k++) {
i = k;
j = col;
dian = 0;
while (i < row && j >= 0) {
if (board[i][j] == 'O') {
dian++;
}
else
dian = 0;
i++;
j--;
if (dian >= 5)
return 'o';
}
}
for (int k = 0;k <row;k++) {
i = k;
j = col;
dian = 0;
while (i <row && j >= 0) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i++;
j--;
if (dian >= 5)
return 'x';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = 0;
dian = 0;
while (i >= 0 && j <col) {
if (board[i][j] == 'O') {
dian++;
}
else
dian = 0;
i--;
j++;
if (dian >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = 0;
dian = 0;
while (i >= 0 && j <col) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i--;
j++;
if (dian >= 5)
return 'x';
}
}
for (int k = 0;k < row;k++) {
i = k;
j = col;
dian = 0;
while (i < row && j >= 0) {
if (board[i][j] == 'O') {
dian++;
}
else
dian = 0;
i++;
j--;
if (dian >= 5)
return 'o';
}
}
for (int k = 0;k <row;k++) {
i = k;
j = col;
dian = 0;
while (i <row && j >= 0) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i++;
j--;
if (dian >= 5)
return 'x';
}
}
return 'c';
//左
}
三.整個(gè)代碼
(1)test.c文件下代碼:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu() {
printf("**************************\n");
printf("******* 1. play *********\n");
printf("******* 0. exit *********\n");
printf("**************************\n");
}
void game() {
//棋盤(pán)數(shù)組
char board[ROW][COL],ret;
//初始化棋盤(pán)
InitBoard(board, ROW, COL);
//打印棋盤(pán)
PrintBoard(board, ROW, COL);
//下棋
int a;
printf("1.先手 0.后手");
scanf("%d", &a);
if(a==1)
PlayerMove(board, ROW, COL);
else
ComputerMove(board, ROW, COL);
while (1) {
if (a == 0) {
//PlayerMove(board, ROW, COL);
PlayerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret=iswin(board, ROW, COL);
if (ret != 'c') {
break;
}
//ComputerMove(board, ROW, COL);
ComputerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = iswin(board, ROW, COL);
if (ret != 'c') {
break;
}
}
else {
//ComputerMove(board, ROW, COL);
ComputerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = iswin(board, ROW, COL);
if (ret != 'c') {
break;
}
//PlayerMove(board, ROW, COL);
PlayerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = iswin(board, ROW, COL);
if (ret != 'c') {
break;
}
}
}
if (ret == 'o')
printf("玩家贏\n");
else if (ret == 'x')
printf("電腦贏\n");
else
printf("平局\n");
}
int main() {
int input;
srand((unsigned int)time(NULL));
do {
menu();
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯(cuò)誤\n");
break;
}
} while (input);
return 0;
}
(2)game.c下的代碼
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col) {
for (int i = 0;i < row;i++) {
for (int j = 0;j < col;j++) {
board[i][j] = ' ';
}
}
}
void PrintBoard(char board[ROW][COL], int row, int col) {
for (int i = 0;i < row;i++) {
printf(" ");
printf("%2d", i+1);
}
printf("\n");
for (int i = 0;i < row;i++) {
//打印數(shù)據(jù)
printf("%2d", i + 1);
for (int j = 0;j < col;j++) {
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//打印分割行
if (i < row - 1) {
printf(" ");
for (int j = 0;j < col;j++) {
printf("---");
if (j < col-1)
printf("|");
}
printf("\n");
}
}
}
void PlayerMove(char board[ROW][COL], int row, int col) {
int x, y;
while (1) {
printf("玩家走:\n");
printf("請(qǐng)輸入坐標(biāo):\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (board[x - 1][y - 1] == ' ') {
board[x - 1][y - 1] = 'O';
break;
}
else {
printf("坐標(biāo)被占用,請(qǐng)重新輸入\n");
}
}
else {
printf("坐標(biāo)非法,請(qǐng)重新輸入\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col) {
int x, y;
printf("電腦走\(yùn)n");
while (1) {
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ') {
board[x][y] = 'X';
break;
}
}
}
char iswin(char board[ROW][COL], int row, int col) {
//行
int ren=0,dian=0,i,j;
for (i = 0;i < row;i++) {
ren = 0;
for (j = 0;j < col;j++) {
if (board[i][j] == 'O')
ren++;
else
ren = 0;
if (ren >= 5)
return 'o';
}
}
for (i = 0;i < row;i++) {
dian = 0;
for (j = 0;j < col;j++) {
if (board[i][j] == 'X')
dian++;
else
dian = 0;
if (dian >= 5)
return 'x';
}
}
//列
ren = dian = 0;
for (i = 0;i < row;i++) {
ren = 0;
for (j = 0;j < col;j++) {
if (board[j][i] == 'O')
ren++;
else
ren = 0;
if (ren >= 5)
return 'o';
}
}
for (i = 0;i < row;i++) {
dian = 0;
for (j = 0;j < col;j++) {
if (board[j][i] == 'X')
dian++;
else
dian = 0;
if (dian >= 5)
return 'x';
}
}
//右下
ren = dian =i=j= 0;
for (int k = 0;k < row;k++) {
i = k;
j = 0;
ren = 0;
while (i < row && j < col) {
if (board[i][j] == 'O') {
ren++;
}
else {
ren = 0;
}
i++;
j++;
if (ren >= 5)
return 'o';
}
}
i = j = 0;
for (int k = 0;k < row;k++) {
i = k;
j = 0;
dian = 0;
while (i < row && j < col) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i++;
j++;
if (dian >= 5)
return 'x';
}
}
//右上
for (int k = row;k >=0;k--) {
j = col;
i = k;
ren = 0;
while (i >=0 && j >=0) {
if (board[i][j] == 'O') {
ren++;
}
else
ren = 0;
i--;
j--;
if (ren >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = col;
dian = 0;
while (i >= 0 && j >= 0) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i--;
j--;
if (dian >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = 0;
dian = 0;
while (i >= 0 && j <col) {
if (board[i][j] == 'O') {
dian++;
}
else
dian = 0;
i--;
j++;
if (dian >= 5)
return 'o';
}
}
for (int k = row;k >= 0;k--) {
i = k;
j = 0;
dian = 0;
while (i >= 0 && j <col) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i--;
j++;
if (dian >= 5)
return 'x';
}
}
for (int k = 0;k < row;k++) {
i = k;
j = col;
dian = 0;
while (i < row && j >= 0) {
if (board[i][j] == 'O') {
dian++;
}
else
dian = 0;
i++;
j--;
if (dian >= 5)
return 'o';
}
}
for (int k = 0;k <row;k++) {
i = k;
j = col;
dian = 0;
while (i <row && j >= 0) {
if (board[i][j] == 'X') {
dian++;
}
else
dian = 0;
i++;
j--;
if (dian >= 5)
return 'x';
}
}
return 'c';
//左
}
(3)game.h下的代碼
#pragma once #define ROW 15 #define COL 15 #include<stdio.h> #include<stdlib.h> #include<time.h> //初始化棋盤(pán) void InitBoard(char board[ROW][COL], int row, int col); //打印棋盤(pán) void PrintBoard(char board[ROW][COL], int row, int col); //人走 void PlayerMove(char board[ROW][COL], int row, int col); //電腦走 void ComputerMove(char board[ROW][COL], int row, int col); //判斷輸贏 char iswin(char board[ROW][COL], int row, int col);
四.具體效果
1.棋盤(pán)打印以及選擇先后手

2.玩家和電腦下子

3.判斷輸贏

此處我們看到玩家贏了,可是電腦實(shí)在太蠢了,所以還有很多地方需要添加的
歡迎各位大佬對(duì)此代碼進(jìn)行優(yōu)化!
總結(jié)
到此這篇關(guān)于如何利用最簡(jiǎn)單的C語(yǔ)言實(shí)現(xiàn)AI五子棋的文章就介紹到這了,更多相關(guān)C語(yǔ)言實(shí)現(xiàn)AI五子棋內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)掃雷小游戲簡(jiǎn)單版
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)掃雷小游戲簡(jiǎn)單版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
C++?select模型簡(jiǎn)單聊天室的實(shí)現(xiàn)示例
本文主要介紹了C++?select模型簡(jiǎn)單聊天室的實(shí)現(xiàn)示例,使用CMake項(xiàng)目進(jìn)行開(kāi)發(fā),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
C++的動(dòng)態(tài)內(nèi)存管理你真的了解嗎
這篇文章主要為大家詳細(xì)介紹了C++的動(dòng)態(tài)內(nèi)存管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02
C++在成員函數(shù)中使用STL的find_if函數(shù)實(shí)例
這篇文章主要介紹了C++在成員函數(shù)中使用STL的find_if函數(shù)實(shí)例,包括了STL中find_if函數(shù)的具體用法及相關(guān)的完整實(shí)例,非常具有參考借鑒價(jià)值,需要的朋友可以參考下2014-10-10
C++11特性小結(jié)之decltype、類(lèi)內(nèi)初始化、列表初始化返回值
這篇文章主要介紹了C++11特性小結(jié)之decltype、類(lèi)內(nèi)初始化、列表初始化返回值,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
數(shù)據(jù)結(jié)構(gòu)順序表操作示例
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)順序表操作示例,其中有在第I個(gè)元素前插入數(shù)據(jù)x,元素從0開(kāi)始計(jì)數(shù)、刪除第i個(gè)元素,元素從0開(kāi)始計(jì)數(shù)的方法,需要的朋友可以參考下2014-03-03
C語(yǔ)言雙向鏈表實(shí)現(xiàn)根據(jù)使用頻率安排元素位置的功能實(shí)例代碼
這篇文章主要介紹了C語(yǔ)言雙向鏈表實(shí)現(xiàn)根據(jù)使用頻率安排元素位置的功能實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
C++ OpenCV實(shí)現(xiàn)圖像雙三次插值算法詳解
圖像雙三次插值的原理,就是目標(biāo)圖像的每一個(gè)像素都是由原圖上相對(duì)應(yīng)點(diǎn)周?chē)?x4=16個(gè)像素經(jīng)過(guò)加權(quán)之后再相加得到的。本文主要介紹了通過(guò)C++ OpenCV實(shí)現(xiàn)圖像雙三次插值算法,需要的可以參考一下2021-12-12

