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