如何利用最簡單的C語言實現(xiàn)AI五子棋
一.如何實現(xiàn)
1.說明:由于本文只是對初學(xué)C語言的人學(xué)習(xí),所以將不會涉及任何算法,電腦將采用隨機下子的方式。(后期會為大家介紹Alpha-Beta剪枝算法實現(xiàn)人工智能AI)
2.主要部分:
(1)菜單
(2)打印棋盤
(3)玩家下子
(4)電腦下子
(5)判斷輸贏
二.實現(xiàn)代碼及分析
(1)菜單的制作
運用do…while循環(huán)調(diào)用菜單,根據(jù)用戶選擇實現(xiàn)玩游戲和退出游戲
(2)棋盤的初始化和打印
棋盤采用標準的15*15的格子,我們可以宏定義ROW和COL分別為15和15來表示行和列。
分別封裝兩個函數(shù)對棋盤進行初始化和打印
初始化:(這里將棋盤初始化為空格,可初始化為其他)
打印棋盤:
效果如下:
(3)玩家下子
void PlayerMove(char board[ROW][COL], int row, int col) { int x, y; while (1) { printf("玩家走:\n"); printf("請輸入坐標:\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("坐標被占用,請重新輸入\n"); } } else { printf("坐標非法,請重新輸入\n"); } } }
玩家下子主要采用的思路是,判斷棋盤上是否有子,已經(jīng)輸入的坐標是否合法。
(4)電腦下子
void ComputerMove(char board[ROW][COL], int row, int col) { int x, y; printf("電腦走\n"); while (1) { x = rand() % row; y = rand() % col; if (board[x][y] == ' ') { board[x][y] = 'X'; break; } } }
與玩家下子相同,此處采用的隨機下子,后期可進行優(yōu)化(比如:極大極小值算法、Alpha-Beta剪枝算法等)
(5)判斷輸贏
通過遍歷整個棋盤,觀察是否有連五子情況出現(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'; //左 }
三.整個代碼
(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() { //棋盤數(shù)組 char board[ROW][COL],ret; //初始化棋盤 InitBoard(board, ROW, COL); //打印棋盤 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("選擇錯誤\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("請輸入坐標:\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("坐標被占用,請重新輸入\n"); } } else { printf("坐標非法,請重新輸入\n"); } } } void ComputerMove(char board[ROW][COL], int row, int col) { int x, y; printf("電腦走\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> //初始化棋盤 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盤 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.棋盤打印以及選擇先后手
2.玩家和電腦下子
3.判斷輸贏
此處我們看到玩家贏了,可是電腦實在太蠢了,所以還有很多地方需要添加的
歡迎各位大佬對此代碼進行優(yōu)化!
總結(jié)
到此這篇關(guān)于如何利用最簡單的C語言實現(xiàn)AI五子棋的文章就介紹到這了,更多相關(guān)C語言實現(xiàn)AI五子棋內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++在成員函數(shù)中使用STL的find_if函數(shù)實例
這篇文章主要介紹了C++在成員函數(shù)中使用STL的find_if函數(shù)實例,包括了STL中find_if函數(shù)的具體用法及相關(guān)的完整實例,非常具有參考借鑒價值,需要的朋友可以參考下2014-10-10C++11特性小結(jié)之decltype、類內(nèi)初始化、列表初始化返回值
這篇文章主要介紹了C++11特性小結(jié)之decltype、類內(nèi)初始化、列表初始化返回值,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05數(shù)據(jù)結(jié)構(gòu)順序表操作示例
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)順序表操作示例,其中有在第I個元素前插入數(shù)據(jù)x,元素從0開始計數(shù)、刪除第i個元素,元素從0開始計數(shù)的方法,需要的朋友可以參考下2014-03-03C語言雙向鏈表實現(xiàn)根據(jù)使用頻率安排元素位置的功能實例代碼
這篇文章主要介紹了C語言雙向鏈表實現(xiàn)根據(jù)使用頻率安排元素位置的功能實例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03