三子棋之VS人工智能/人工智障,你能赢吗?
文章目錄
- 一.前言🚀
- 二.游戲邏輯?🚀
- 三.代碼實現🚀
- 1.test.c🚗
- 2.game.h🚓
- 3.game.c🚕
- 四.游戲功能具體分析🚀
- 1.棋盤的初始化🚙
- 2.棋盤的打印🚑
- 3.玩家下棋🚒
- 4.電腦下棋🚍
- 4.1簡單模式🚘
- 4.2困難模式🚖
- 5.判斷棋盤滿沒滿🚅
- 6.判斷游戲輸贏🚃
- 五.總結🚀
一.前言🚀
大家好,首先祝大家五一快樂🎈🎈🎈🎈🎈🎈,當然有很多大學生像作者一樣五一并沒有放假,說多了都是淚啊😭,不過沒事,我們還有周末!廢話不多說了,今天我們一起來研究一下三子棋,雖然在c站三子棋已經爛大街了,但是每個人都有自己與眾不同的地方,值得我們學習。所以我們可以博采眾長,吸收別人優秀的地方,提高自己的水平。
二.游戲邏輯?🚀
我們在寫一個項目的時候,如果這個項目非常復雜,不建議大家上來就干代碼的,因為你有很大的可能會出錯。我們應該仔細思考游戲的邏輯,如何實現這個項目。
1.我們需要一個菜單控制游戲,讓玩家做出選擇
2.游戲最好可以讓玩家一直玩,除非玩家退出游戲
3.三子棋需要一個棋盤,我們打印一個棋盤(通過二維數組)
4.玩家下棋,輸入坐標(也可以電腦先下棋)
5.打印棋盤,觀察坐標,(是否有錯誤)
6.電腦下棋,打印棋盤,這部分我們可以優化一下,讓我們很難贏電腦
7.判斷輸贏,打印棋盤,觀察坐標
三.代碼實現🚀
當我們寫的代碼比較多的時候,建議大家使用模塊化的設計,我們這里分成三個部分:
test.c
主函數部分,對游戲的邏輯進行測試運行
game.h
庫函數頭文件的包含
行列的自定義設置
函數的定義
game.c
游戲邏輯的具體實現
1.test.c🚗
#define _CRT_SECURE_NO_WARNINGS 1#include"game.h" void menu() {printf("**************************************\n");printf("******** 1. play(智能模式) *********\n");printf("******** 2. play(智障模式) *********\n");printf("******** 0. exit(退出游戲) *********\n");printf("**************************************\n");} void game1() { //存儲數據 - 二維數組char board[ROW][COL] = { 0 };//初始化棋盤 - 初始化空格initBoard(board, ROW, COL);//打印棋盤 - 本質是打印數組的內容displayBoard(board, ROW, COL);//下棋char ret = 0;while(1){playerMove(board, ROW, COL);displayBoard(board, ROW, COL);//判斷玩家是否贏得游戲ret = isWin(board, ROW, COL);if(ret != 'c'){break;} computerMove(board, ROW, COL);displayBoard(board, ROW, COL);//判斷電腦是否贏得游戲ret = isWin(board, ROW, COL);if (ret != 'c'){break;}}switch (ret){case 'O':printf("你贏了,也就一般般吧\n");break;case 'X':printf("你竟然輸給了人工智障,哈哈\n");break;case 'p':printf("平局,好好反思一下你自己\n");break;displayBoard(board, ROW, COL);}//效果差不多/*if (ret == 'o'){printf("玩家贏了\n");}else if (ret == 'x'){printf("電腦贏了\n");}else{printf("平局\n");}*/ } void game2() { //存儲數據 - 二維數組char board[ROW][COL] = { 0 };//初始化棋盤 - 初始化空格initBoard(board, ROW, COL);//打印棋盤 - 本質是打印數組的內容displayBoard(board, ROW, COL);//下棋char ret = 0;while (1){ SmartComputerMove(board, ROW, COL);displayBoard(board, ROW, COL);ret = isWin(board, ROW, COL);//判斷電腦是否贏得游戲if (ret != 'c'){break;}playerMove(board, ROW, COL);displayBoard(board, ROW, COL);//判斷玩家是否贏得游戲ret = isWin(board, ROW, COL);if (ret != 'c'){break;}}switch (ret){case 'O':printf("您贏了,就算是阿爾法狗也不是您的對手\n");break;case 'X':printf("你輸了,沒事,等于你已經和大神過過手了\n");break;case 'p':printf("平局,小伙子,你非常有前途\n");break;displayBoard(board, ROW, COL);} }int main() {int input = 0;srand((unsigned int)time(NULL));do{menu();printf("請選擇模式:>");printf("\n人工智障:1 | 人工智能:2 | 退出游戲:0\n");scanf("%d", &input);switch (input){case 1:game1();break;case 2:game2();break;case 0:printf("退出游戲\n");break;default:printf("輸入錯誤,請重新輸入\n");break;}} while (input);return 0; }2.game.h🚓
//防止頭文件被重復包含 #pragma once //頭文件的包含 #include<stdio.h> #include<stdlib.h> #include<time.h> //定義行和列(可以隨意改變) #define ROW 3 #define COL 3 //初始化棋盤 void initBoard(char board[ROW][COL], int row, int col); //打印棋盤的函數 void displayBoard(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); //困難模式 void SmartComputerMove(char board[ROW][COL], int row, int col); //判斷棋盤滿沒滿 int isFull(char board[ROW][COL], int row, int col); //1.玩家贏 - O //2.電腦贏 - X //3.平局 - p //4.游戲繼續 - c //判斷輸贏 char isWin(char board[ROW][COL], int row, int col);3.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 displayBoard(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");if (i < row - 1){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 = 0;int y = 0;printf("玩家走:>\n");while(1){ printf("請輸入下棋坐標:>");scanf("%d %d", &x, &y);if (x > 0 && x <= row && y > 0 && y <= col){//判斷坐標是否被占用if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = 'O';break;}else{printf("坐標已被占用,請重新輸入\n");break;}}else{printf("坐標錯誤,請重新輸入\n");}} }void computerMove(char board[ROW][COL], int row, int col) {int x = 0;int y = 0;printf("電腦走:>\n");while (1){x = rand() % row;y = rand() % col;//不用判斷合法性if(board[x][y] == ' '){board[x][y] = 'X';break;}} } int isFull(char board[ROW][COL], int row, int col) {int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if(board[i][j] == ' '){return 0;//棋盤沒滿} }}return 1;//棋盤滿了 } char isWin(char board[ROW][COL], int row, int col) {//判斷三行for (int i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}//判斷三列for (int j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' '){return board[0][j];}}//判斷對角線if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[0][0];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[0][2];}//判斷平局int ret = isFull(board, row, col);if (ret == 1){return 'p';}return 'c'; }void SmartComputerMove(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;//判斷每一行是否有兩個相連的棋子,如果有,且第三個棋格為空,則落棋for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][0] == 'X' && board[i][2] == ' '){board[i][2] = 'X';}if (board[i][0] == board[i][2] && board[i][0] == 'X' && board[i][1] == ' '){board[i][1] = 'X';}if (board[i][1] == board[i][2] && board[i][1] == 'X' && board[i][0] == ' '){board[i][0] = 'X';}}//判斷每一列是否有兩個相連的棋子,如果有,且第三個棋格為空,則落棋for (j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[0][j] == 'X' && board[2][j] == ' '){board[2][j] = 'X';}if (board[0][j] == board[2][j] && board[0][j] == 'X' && board[1][j] == ' '){board[1][j] = 'X';}if (board[1][j] == board[2][j] && board[1][j] == 'X' && board[0][j] == ' '){board[0][j] = 'X';}}//判斷兩條對角線是否有兩個相連的棋子,如果有,且第三個棋格為空,則落棋{//第一條if (board[0][0] == board[1][1] && board[0][0] == 'X' && board[2][2] == ' '){board[2][2] = 'X';}if (board[0][0] == board[2][2] && board[0][0] == 'X' && board[1][1] == ' '){board[1][1] = 'X';}if (board[1][1] == board[2][2] && board[1][1] == 'X' && board[0][0] == ' '){board[0][0] = 'X';}//第二條if (board[0][2] == board[1][1] && board[0][2] == 'X' && board[2][0] == ' '){board[2][0] = 'X';}if (board[0][2] == board[2][0] && board[0][2] == 'X' && board[1][1] == ' '){board[1][1] = 'X';}if (board[1][1] == board[2][0] && board[1][1] == 'X' && board[0][2] == ' '){board[0][2] = 'X'; }//如果上面都沒落子,說明不符合贏的條件int i = 0;int j = 0;//判斷每一行是否有兩個相連的棋子,如果有,且第三個棋格為空,則堵棋for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][0] == 'O' && board[i][2] == ' '){board[i][2] = 'X';goto end;}if (board[i][0] == board[i][2] && board[i][0] == 'O' && board[i][1] == ' '){board[i][1] = 'X';goto end;}if (board[i][1] == board[i][2] && board[i][1] == 'O' && board[i][0] == ' '){board[i][0] = 'X';goto end;}}//判斷每一列是否有兩個相連的棋子,如果有,且第三個棋格為空,則堵棋for (j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[0][j] == 'O' && board[2][j] == ' '){board[2][j] = 'X';goto end;}if (board[0][j] == board[2][j] && board[0][j] == 'O' && board[1][j] == ' '){board[1][j] = 'X';goto end;}if (board[1][j] == board[2][j] && board[1][j] == 'O' && board[0][j] == ' '){board[0][j] = 'X';goto end;}}//判斷兩條對角線是否有兩個相連的棋子,如果有,且第三個棋格為空,則堵棋{//第一條if (board[0][0] == board[1][1] && board[0][0] == 'O' && board[2][2] == ' '){board[2][2] = 'X';goto end;}if (board[0][0] == board[2][2] && board[0][0] == 'O' && board[1][1] == ' '){board[1][1] = 'X';goto end;}if (board[1][1] == board[2][2] && board[1][1] == 'O' && board[0][0] == ' '){board[0][0] = 'X';goto end;}//第二條if (board[0][2] == board[1][1] && board[0][2] == 'O' && board[2][0] == ' '){board[2][0] = 'X';goto end;}if (board[0][2] == board[2][0] && board[0][2] == 'O' && board[1][1] == ' '){board[1][1] = 'X';goto end;}if (board[1][1] == board[2][0] && board[1][1] == 'O' && board[0][2] == ' '){board[0][2] = 'X';goto end;}//如果上面都沒返回,說明不符合堵棋,下棋的條件else{computerMove(board, ROW, COL);}}}int ret = 0;end://判斷平局ret = isFull(board, row, col);if (ret == 1){return 'p';}return 'c'; }四.游戲功能具體分析🚀
1.棋盤的初始化🚙
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] = ' ';}} }2.棋盤的打印🚑
void displayBoard(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");if (i < row - 1){for(int j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}} }printf("\n");} }3.玩家下棋🚒
void playerMove(char board[ROW][COL], int row, int col) {int x = 0;int y = 0;printf("玩家走:>\n");while(1){ printf("請輸入下棋坐標:>");scanf("%d %d", &x, &y);if (x > 0 && x <= row && y > 0 && y <= col){//判斷坐標是否被占用if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = 'O';break;}else{printf("坐標已被占用,請重新輸入\n");break;}}else{printf("坐標錯誤,請重新輸入\n");}} }4.電腦下棋🚍
4.1簡單模式🚘
void computerMove(char board[ROW][COL], int row, int col) {int x = 0;int y = 0;printf("電腦走:>\n");while (1){x = rand() % row;y = rand() % col;//不用判斷合法性if(board[x][y] == ' '){board[x][y] = 'X';break;}} }4.2困難模式🚖
void SmartComputerMove(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;//判斷每一行是否有兩個相連的棋子,如果有,且第三個棋格為空,則落棋for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][0] == 'X' && board[i][2] == ' '){board[i][2] = 'X';}if (board[i][0] == board[i][2] && board[i][0] == 'X' && board[i][1] == ' '){board[i][1] = 'X';}if (board[i][1] == board[i][2] && board[i][1] == 'X' && board[i][0] == ' '){board[i][0] = 'X';}}//判斷每一列是否有兩個相連的棋子,如果有,且第三個棋格為空,則落棋for (j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[0][j] == 'X' && board[2][j] == ' '){board[2][j] = 'X';}if (board[0][j] == board[2][j] && board[0][j] == 'X' && board[1][j] == ' '){board[1][j] = 'X';}if (board[1][j] == board[2][j] && board[1][j] == 'X' && board[0][j] == ' '){board[0][j] = 'X';}}//判斷兩條對角線是否有兩個相連的棋子,如果有,且第三個棋格為空,則落棋{//第一條if (board[0][0] == board[1][1] && board[0][0] == 'X' && board[2][2] == ' '){board[2][2] = 'X';}if (board[0][0] == board[2][2] && board[0][0] == 'X' && board[1][1] == ' '){board[1][1] = 'X';}if (board[1][1] == board[2][2] && board[1][1] == 'X' && board[0][0] == ' '){board[0][0] = 'X';}//第二條if (board[0][2] == board[1][1] && board[0][2] == 'X' && board[2][0] == ' '){board[2][0] = 'X';}if (board[0][2] == board[2][0] && board[0][2] == 'X' && board[1][1] == ' '){board[1][1] = 'X';}if (board[1][1] == board[2][0] && board[1][1] == 'X' && board[0][2] == ' '){board[0][2] = 'X'; }//如果上面都沒落子,說明不符合贏的條件int i = 0;int j = 0;//判斷每一行是否有兩個相連的棋子,如果有,且第三個棋格為空,則堵棋for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][0] == 'O' && board[i][2] == ' '){board[i][2] = 'X';goto end;//防止多次落子的問題}if (board[i][0] == board[i][2] && board[i][0] == 'O' && board[i][1] == ' '){board[i][1] = 'X';goto end;}if (board[i][1] == board[i][2] && board[i][1] == 'O' && board[i][0] == ' '){board[i][0] = 'X';goto end;}}//判斷每一列是否有兩個相連的棋子,如果有,且第三個棋格為空,則堵棋for (j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[0][j] == 'O' && board[2][j] == ' '){board[2][j] = 'X';goto end;}if (board[0][j] == board[2][j] && board[0][j] == 'O' && board[1][j] == ' '){board[1][j] = 'X';goto end;}if (board[1][j] == board[2][j] && board[1][j] == 'O' && board[0][j] == ' '){board[0][j] = 'X';goto end;}}//判斷兩條對角線是否有兩個相連的棋子,如果有,且第三個棋格為空,則堵棋{//第一條if (board[0][0] == board[1][1] && board[0][0] == 'O' && board[2][2] == ' '){board[2][2] = 'X';goto end;}if (board[0][0] == board[2][2] && board[0][0] == 'O' && board[1][1] == ' '){board[1][1] = 'X';goto end;}if (board[1][1] == board[2][2] && board[1][1] == 'O' && board[0][0] == ' '){board[0][0] = 'X';goto end;}//第二條if (board[0][2] == board[1][1] && board[0][2] == 'O' && board[2][0] == ' '){board[2][0] = 'X';goto end;}if (board[0][2] == board[2][0] && board[0][2] == 'O' && board[1][1] == ' '){board[1][1] = 'X';goto end;}if (board[1][1] == board[2][0] && board[1][1] == 'O' && board[0][2] == ' '){board[0][2] = 'X';goto end;}//如果上面都沒返回,說明不符合堵棋,下棋的條件else{computerMove(board, ROW, COL);}}}int ret = 0;end://判斷平局ret = isFull(board, row, col);if (ret == 1){return 'p';}return 'c'; }5.判斷棋盤滿沒滿🚅
int isFull(char board[ROW][COL], int row, int col) {int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if(board[i][j] == ' '){return 0;//棋盤沒滿} }}return 1;//棋盤滿了 }6.判斷游戲輸贏🚃
char isWin(char board[ROW][COL], int row, int col) {//判斷三行for (int i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}//判斷三列for (int j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' '){return board[0][j];}}//判斷對角線if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[0][0];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[0][2];}//判斷平局int ret = isFull(board, row, col);if (ret == 1){return 'p';}return 'c'; }五.總結🚀
我們可以發現簡單模式下,電腦的下法是非常笨拙的,因為是隨機的坐標。我們可以改一下,比如困難模式,用窮舉的方法,判斷我方是否有兩顆棋子在一條線上,如果有則堵死;并且判斷電腦的棋子是否有兩顆在一條線上,如果有則落子。一定程度上增加了難度,不太容易贏,平局比較多。因為電腦前兩顆棋子是隨機的,所以也就是看運氣。感興趣的小伙伴可以復制過去體驗一下,可能會有BUG,我暫時還沒有發現!!!如果你發現了,請一定聯系我改正。另外,這個程序只適用于三子棋,其實也可以改,不過我懶寫的了,你可以搜一下,等以后閑了再說吧,孩子要好好學習了,不然要掛科了!!!😭😭😭
總結
以上是生活随笔為你收集整理的三子棋之VS人工智能/人工智障,你能赢吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BGP概述及基础配置
- 下一篇: 酒店客房管理系统之系统实施--数据库