C語言實現(xiàn)井字棋(三子棋)
本文實例為大家分享了C語言實現(xiàn)井字棋的具體代碼,供大家參考,具體內容如下
一、實現(xiàn)思路
1、初始化數(shù)組
三子棋是九宮格的格式,所以用二維數(shù)組接收數(shù)據(jù)。用‘O'代表電腦下的子,‘X'代表玩家下的子。未下子的時候初始化 ' ‘(space)。則二維數(shù)組為“char”類型,大小為char board[3][3]。
2、打印棋盤
打印出井字的棋盤,同時為了將數(shù)據(jù)顯示在每格的中間,用空格隔開(“ %c |”)的格式設置棋盤“|”用來形成豎,接著打印“- - -|”用來形成行。將兩部用for循環(huán)按照邏輯鏈接起來,即可打印出“井”。同時“%c”處初始化為‘ '(space)
3、玩家下子
<1> 玩家下的子用數(shù)組的坐標表示,輸入提示:(請輸入坐標:),輸入格式為(1 1),范圍為1~3。
<2> 玩家下子的時候,如果遇到已經(jīng)下過子的坐標,返回并提示錯誤,重新輸入。
<3> 如果輸入的坐標超過范圍,提示錯誤,重新輸入。
<4> 打印棋盤,將玩家下子的坐標處用'X'替換。
4、電腦下子
<1> 電腦下子,利用范圍為1~3,隨機產(chǎn)生條件下的坐標,如果遇到已經(jīng)下過子的坐標,就重新產(chǎn)生條件下的坐標,這里利用循環(huán)進行調試。
<2> 有一個電腦下子優(yōu)先規(guī)則:
a、電腦下子的第一個是隨機產(chǎn)生,在電腦先手的時候,第二個也是隨機產(chǎn)生。
b、判斷是否有兩個 ‘O”O(jiān)' 在行、列或者斜對角,如果有,就將第三個子下在可以連成一直線的空白處(即三點成線,贏得比賽)。如果有連成線但是沒用空白處,進行 c 步驟。
c、判斷是不是有兩個 ‘X”X' 在行、列或者斜對角練成線,并且第三個空為空白。如果有就將子下在該空白處(即對玩家進行堵截)。如果沒用,進行 d 步驟。
d、在范圍內隨機下子?! ?br />
<3> 打印棋盤,將電腦下子的坐標處用'O'代替。
5、輸贏判斷
當判斷出有行、列或者斜對角出現(xiàn) ‘X' ‘O' 三點成線,輸出判斷(恭喜你,你贏了)(很遺憾,你輸了)并退出游戲,如果遍歷數(shù)組發(fā)現(xiàn)不符合上述要求,而且沒有數(shù)據(jù) ' ‘(space)(即棋盤下滿),輸出(和棋)并退出游戲。
6、邏輯關系
開始游戲——選擇電腦先手——(ComputerGo——PrintfGame——IsWin——PlayGo——PrintfGame——IsWin)(循環(huán)實現(xiàn))
開始游戲——選擇玩家先手——PrintfGame——(PlayGo——PrintfGame——IsWin——ComputerGo——PrintfGame——IsWin)(循環(huán)實現(xiàn))
二、源代碼
1、game.h(頭文件)
#ifndef __game_h__ #define __game_h__ #define ROW 3 //標識符定義行ROW = 3 #define COL 3//標識符定義列COL = 3 void InitGame(char arr[ROW][COL], int row, int col);//初始化 void PrintfGame(char arr[ROW][COL], int row, int col);//打印 void Menu();//菜單 void ComputerGo(char arr[ROW][COL], int row, int col);//電腦走 void PlayGo(char arr[ROW][COL], int row, int col);//玩家走 char IsWin(char arr[ROW][COL], int row, int col);//輸、贏、和局 #endif //__game_h__
2、game.c(函數(shù)定義)
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" //引用自定義頭文件 #include <stdio.h> #include <time.h> #include <stdlib.h> void Menu() { printf("**********************************\n"); printf("********* 1.paly *********\n"); printf("********* 0.exit *********\n"); printf("**********************************\n"); } void InitGame(char arr[ROW][COL],int row, int col)//初始化數(shù)組 { int i = 0; int j = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { arr[i][j] = ' '; // 利用循環(huán)將數(shù)組元素初始化為' '(space) } } } void PrintfGame(char arr[ROW][COL], int row, int col)//打印棋盤 { //利用循環(huán)打印棋盤 int i = 0; int j = 0; for (i = 0; i < ROW; i++)//限定范圍,不超過ROW { if (i < ROW - 1) //打印前兩行 { for (j = 0; j < COL; j++) { if (j < COL - 1) //打印前兩列 { printf(" %c |", arr[i][j]); } else { printf(" %c ",arr[i][j]); //打印第三列 } } printf("\n"); //輸出形式為" %c | %c | %c " for (j = 0; j < COL; j++) { if (j < COL - 1) { printf("---|"); //打印前兩列 } else { printf("---"); //打印第三列 } } printf("\n"); //輸出形式為"---|---|---" } else //打印第三行 { for (j = 0; j < COL; j++) { if (j < COL - 1) { printf(" %c |",arr[i][j]); } else { printf(" %c ",arr[i][j]); } } printf("\n"); //輸出形式為 " %c | %c | %c " } } } void PlayGo(char arr[ROW][COL], int row, int col)//玩家走 { int i = 0; int j = 0; int set = 0; do { printf("\n"); printf("請輸入坐標:>"); scanf("%d %d", &i, &j); printf("\n"); //對輸入的i,j減1,用戶輸入的時候就可以直接以(1 1)為第一個輸入點 i--; j--; if ((i<0) || (i>=row) || (j<0) || (j>=col) || (arr[i][j] != ' ')) {//輸入超出了范圍或者輸入坐標處已經(jīng)有棋子 printf("輸入有誤!\n"); set = 1; } else { arr[i][j] = 'X';//玩家下子 set = 0; } } while (set);//沒有下子成功就循環(huán)到輸入成功 } char IsWin(char arr[ROW][COL], int row, int col)//判斷輸贏 { int i = 0; int j = 0; int count = 0; for (i = 0; i < ROW; i++) { if ((arr[i][0] == arr[i][1]) && (arr[i][1] == arr[i][2]) && (arr[i][0] != ' ')) { return 'X';//產(chǎn)生有行成線,返回'X' } } for (i = 0; i < ROW; i++) { if ((arr[0][i] == arr[1][i]) && (arr[1][i] == arr[2][i]) && (arr[0][i] != ' ')) { return ' ';//產(chǎn)生列成線,返回' ' } } if ((arr[0][0] == arr[1][1]) && (arr[1][1] == arr[2][2]) && (arr[1][1] != ' ') || (arr[2][0] == arr[1][1]) && (arr[1][1] == arr[0][2])&&(arr[1][1]!=' ')) { return 'O';//產(chǎn)生斜對角成線,返回'O' } if ((arr[0][0] != ' ') && (arr[0][1] != ' ') && (arr[0][2] != ' ') && (arr[1][0] != ' ') && (arr[1][1] != ' ') && (arr[1][2] != ' ') && (arr[2][0] != ' ') && (arr[2][1] != ' ') && (arr[2][2] != ' ')) { return 'H';//棋盤已經(jīng)下滿卻還沒有勝負產(chǎn)生,返回'H' } return 0; } void ComputerGo(char arr[ROW][COL], int row, int col)//電腦走 { int i = 0; int j = 0; int flag0 = 0;//flage0 用于限制一旦有一種判斷成功,就不再進行其他判斷 int flag2 = 0;//flage2 用于對電腦即將贏的時候,不同判斷產(chǎn)生后,進入不同的case int flag3 = 0;//flage3 用于對玩家即將贏的時候,不同判斷產(chǎn)生后,進入不同的case //電腦還差一子就贏得比賽的情況 if (flag0 == 0) { for (i = 0; i < ROW; i++)//每行有兩個‘O'‘O'連在一起,就在第三個空格處下子 { if ((arr[i][0] == arr[i][1] && arr[i][0] == 'O'&&arr[i][2] != 'X') || (arr[i][1] == arr[i][2] && arr[i][1] == 'O'&&arr[i][0] != 'X') || (arr[i][0] == arr[i][2] && arr[i][0] == 'O'&&arr[i][1] != 'X')) { flag0 = 1; flag2 = 1; break; } } } if (flag0 == 0) { for (j = 0; j < ROW; j++)//每列有兩個‘O'‘O'連在一起,就在第三個空格處下子 { if ((arr[0][j] == arr[1][j] && arr[0][j] == 'O'&&arr[2][j] != 'X') || (arr[1][j] == arr[2][j] && arr[1][j] == 'O'&&arr[0][j] != 'X') || (arr[0][j] == arr[2][j] && arr[0][j] == 'O'&&arr[1][j] != 'X')) { flag2 = 2; flag0 = 1; break; } } } if ((arr[0][0] == arr[1][1] && arr[0][0] == 'O'&&arr[2][2] != 'X')//第一條斜對角 || (arr[1][1] == arr[2][2] && arr[1][1] == 'O'&&arr[0][0] != 'X') || (arr[0][0] == arr[2][2] && arr[0][0] == 'O'&&arr[1][1] != 'X') &&(flag0 == 0)) { flag2 = 3; flag0 = 1; } if ((arr[0][2] == arr[1][1] && arr[0][2] == 'O'&&arr[2][0] != 'X')//第二條斜對角 || (arr[1][1] == arr[2][0] && arr[1][1] == 'O'&&arr[0][2] != 'X') || (arr[0][2] == arr[2][0] && arr[0][2] == 'O'&&arr[1][1] != 'X') && (flag0 == 0)) { flag2 = 4; flag0 = 1; } switch (flag2) { case 1: do { j = rand() % 3;//固定行不變,改變列,讓棋子進入空白處 if (arr[i][j] == ' ') { arr[i][j] = 'O'; break; } } while (1); break; case 2: do {//rand()%3 產(chǎn)生0 1 2 之間的隨機數(shù) i = rand() % 3;//固定列不變,改變行,讓棋子進入空白處 if (arr[i][j] == ' ') { arr[i][j] = 'O'; break; } } while (1); break; case 3: do {//改變行列,但是限制(行數(shù)=列數(shù)),使其在第一條斜對角空白處下子 i = rand() % 3; j = rand() % 3; if ((i == j) && (arr[i][j] == ' ')) { arr[i][j] = 'O'; break; } } while (1); break; case 4: do {//改變行列,但是限制行數(shù)和列數(shù),使其在第二條斜對角空白處下子 i = rand() % 3; j = rand() % 3; if ((i == j) && (arr[i][j] == ' ') && (i == 1) || (i == j + 2) && (arr[i][j] == ' ') || (j == i + 2) && (arr[i][j] == ' ')) { arr[i][j] = 'O'; break; } } while (1); break; } //玩家還差一子就贏得比賽的時候,電腦進行堵截 if (flag0 == 0) { for (i = 0; i < ROW; i++)//每行有兩個‘X'‘X'連在一起,就在第三個空格處下子 { if ((arr[i][0] == arr[i][1] && arr[i][0] == 'X'&&arr[i][2] != 'O') || (arr[i][1] == arr[i][2] && arr[i][1] == 'X'&&arr[i][0] != 'O') || (arr[i][0] == arr[i][2] && arr[i][0] == 'X'&&arr[i][1] != 'O')) { flag3 = 1; flag0 = 1; break; } } } if (flag0 == 0) { for (j = 0; j < ROW; j++)//每列有兩個‘X'‘X'連在一起,就在第三個空格處下子 { if ((arr[0][j] == arr[1][j] && arr[0][j] == 'X'&&arr[2][j] != 'O') || (arr[1][j] == arr[2][j] && arr[1][j] == 'X'&&arr[0][j] != 'O') || (arr[0][j] == arr[2][j] && arr[0][j] == 'X'&&arr[1][j] != 'O')) { flag3 = 2; flag0 = 1; break; } } } if ((arr[0][0] == arr[1][1] && arr[0][0] == 'X'&&arr[2][2] != 'O')//斜對角 || (arr[1][1] == arr[2][2] && arr[1][1] == 'X'&&arr[0][0] != 'O') || (arr[0][0] == arr[2][2] && arr[0][0] == 'X'&&arr[1][1] != 'O') && (flag0 == 0)) { flag3 = 3; flag0 = 1; } if ((arr[0][2] == arr[1][1] && arr[0][2] == 'X'&&arr[2][0] != 'O')//斜對角 || (arr[1][1] == arr[2][0] && arr[1][1] == 'X'&&arr[0][2] != 'O') || (arr[0][2] == arr[2][0] && arr[0][2] == 'X'&&arr[1][1] != 'O') && (flag0 == 0)) { flag3 = 4; flag0 = 1; } switch (flag3) { case 1: do { j = rand() % 3; if (arr[i][j] == ' ') { arr[i][j] = 'O'; break; } } while (1); break; case 2: do { i = rand() % 3; if (arr[i][j] == ' ') { arr[i][j] = 'O'; break; } } while (1); break; case 3: do { i = rand() % 3; j = rand() % 3; if ((i == j) && (arr[i][j] == ' ')) { arr[i][j] = 'O'; break; } } while (1); break; case 4: do { i = rand() % 3; j = rand() % 3; if ((i == j) && (arr[i][j] == ' ') && (i == 1) || (i == j + 2) && (arr[i][j] == ' ') || (j == i + 2) && (arr[i][j] == ' ')) { arr[i][j] = 'O'; break; } } while (1); break; } //無論是玩家還是電腦,沒有即將三子成線的情況,電腦隨機產(chǎn)生一個棋子 if (flag0 == 0) { do { i = rand() % 3; j = rand() % 3; if (arr[i][j] == ' ') { arr[i][j] = 'O'; break; } } while (1); } }
3、text.c(邏輯及調用)
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" #include <stdio.h> #include <stdlib.h> #include <time.h> void game1(char arr[ROW][COL], int row, int col)//電腦先手 { char i = 0; while (1)//只有玩家贏或者電腦贏或者棋盤滿了才退出循環(huán) { printf("\n"); ComputerGo(arr, row, col);//電腦走 PrintfGame(arr, row, col);//打印棋盤 i = IsWin(arr, row, col);//判斷是否有輸贏 if ((i == 'X') || (i == 'O') || (i == ' ')) {//電腦下子之后,滿足有三子成線,一定是電腦贏 printf("電腦贏!\n"); printf("\n"); break; } else if (i == 'H')//棋盤已滿 { printf("和局!\n"); printf("\n"); break; } PlayGo(arr, row, col);//玩家走 PrintfGame(arr, row, col);//打印棋盤 i = IsWin(arr, row, col);//判斷輸贏 if ((i == 'X') || (i == 'O') || (i == ' ')) {//玩家下子之后,滿足有三子成線,一定是玩家贏 printf("玩家贏!\n"); printf("\n"); break; } else if (i == 'H')//棋盤已滿 { printf("和局!\n"); printf("\n"); break; } } } void game2(char arr[ROW][COL], int row, int col)//玩家先手 { char i = 0; int tmp = 0; while (1) { if (tmp == 0)//玩家下棋之前打印一個空白棋盤,只執(zhí)行一次 { printf("\n"); PrintfGame(arr, row, col); tmp = 1; } PlayGo(arr, row, col); PrintfGame(arr, row, col); printf("\n"); i = IsWin(arr, row, col); if ((i == 'X') || (i == 'O') || (i == ' ')) { printf("玩家贏!\n"); printf("\n"); break; } else if (i == 'H') { printf("和局!\n"); printf("\n"); break; } ComputerGo(arr, row, col); PrintfGame(arr, row, col); i = IsWin(arr, row, col); if ((i == 'X') || (i == 'O') || (i == ' ')) { printf("電腦贏!\n"); printf("\n"); break; } else if (i == 'H') { printf("和局!\n"); printf("\n"); break; } } } //main函數(shù) int main() { int i = 0; int j = 0; int input = 0; int tmp = 0; int row = 3; int col = 3; char arr[3][3]; srand((unsigned int)time(NULL));//隨機數(shù)發(fā)生器,用于產(chǎn)生隨機數(shù)的時候,每次都不一樣 do { Menu();//打印 printf("請選擇:>\n"); scanf("%d", &input); printf("\n"); switch (input) { case 1: InitGame(arr, row, col);//初始化函數(shù) do { printf("請選擇:>\n1.電腦先手 2.玩家先手\n"); scanf("%d", &tmp); switch (tmp) { case 1: game1(arr, row, col);//電腦先手 tmp = 0; break; case 2: game2(arr, row, col);//玩家先手 tmp = 0; break; default: printf("輸入有誤! 請重新輸入:>\n\n"); break; } } while (tmp); break; case 0: printf("游戲退出!\n"); break; default: printf("輸入有誤!\n"); break; } } while (input); system("pause"); return 0; }
三、程序截圖
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
VC中LINK 2001 和 LINK 2009 的錯誤的解決方法
最近將兩個開源C++項目編譯成windows版本的時候遇到很多問題,編譯的時候總是報錯,報的最多的是無法解析的外部符號”,經(jīng)過近3天的折騰總算都通過了,這里是一些總結2020-10-10C++詳解使用floor&ceil&round實現(xiàn)保留小數(shù)點后兩位
這篇文章主要介紹了C++使用floor&ceil&round實現(xiàn)保留小數(shù)點后兩位的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07C++中構造函數(shù)與析構函數(shù)的調用順序詳解
C++ 語言一直被批評太復雜了,很多細節(jié)的地方需要仔細推敲,甚至其構造函數(shù)和析構的調用順序也成為了一個讓人迷惑的問題,在此我做了簡單的總結。這篇文章主要介紹了C++中構造函數(shù)與析構函數(shù)的調用順序,需要的朋友可以參考借鑒。2017-01-01Java?C++題解leetcode1598文件夾操作日志搜集器
這篇文章主要為大家介紹了Java?C++題解leetcode1598文件夾操作日志搜集器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09