C語(yǔ)言實(shí)現(xiàn)井字棋詳解
1.主函數(shù)
這個(gè)代碼很長(zhǎng),我們可以把它全部寫在主函數(shù)里面。但是十分不推薦這么做。以后工作以后,很多時(shí)候我們負(fù)責(zé)的只是一個(gè)板塊,匯總時(shí)只需要主函數(shù)調(diào)用每個(gè)人寫的函數(shù)就能完成復(fù)雜項(xiàng)目。在這里我們先寫主函數(shù)。
#include<stdio.h> #include<time.h> #define ROW 3 #define COL 3 //這是對(duì)于行和列的初始化 int main() { test(); return 0; }
2.menu菜單
菜單十分容易完成
void menu() { printf("輸入1開始游戲"); printf("輸入0開始游戲"); }
3.test函數(shù)
主函數(shù)中引用了test函數(shù),我們現(xiàn)在寫一個(gè)test函數(shù),返回類型void,選擇用do while循環(huán)來(lái)完成大部分函數(shù)
void text() { int input = 0; srand((unsigned int)time(NULL)); do { switch(input) { case 1: game(); break; case 2: printf("退出游戲\n"); break; default: printf("選擇錯(cuò)誤,請(qǐng)重新輸入\n"); break; } }while(input); }
4.game函數(shù)(1)
game函數(shù)內(nèi)部仍然需要引用許多函數(shù),對(duì)于一個(gè)三乘三的棋盤來(lái)說(shuō),有以下的步驟:
數(shù)據(jù)存儲(chǔ)到一個(gè)字符的二維數(shù)組中,玩家下棋是'*',電腦下棋是'#'數(shù)組的內(nèi)容應(yīng)該是全部空格
初始化棋牌
打印棋盤
下棋
4.1數(shù)據(jù)存儲(chǔ)的二維數(shù)組:InitBoard
這個(gè)函數(shù)的作用是把該二維數(shù)組全部初始化成為空格
void InitBoard(char arr[ROW][COL],int row,int col) //這里的大寫的BOW COL是傳入的數(shù)組的值,小寫的bow col是新的行和列 { int i = 0; int j = 0; for(i = 0;i<row;i++) { for(j = 0;j<col;j++) { board[i][j] = ' '; } } }
4.2棋盤的打?。篋isplayBoard
這個(gè)函數(shù)是把棋盤的形狀打印出來(lái)
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 (j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } } printf("\n"); } }
4.3玩家下棋:PlayerMove
先寫玩家下棋:思路是如果玩家輸入的地址原來(lái)為空格,那么就把這個(gè)位置重新定義為 *
void PlayerMove(char board[ROW][COL],int row,int col) { printf("玩家下棋"); int x = 0; int y = 0; while(1) { scanf("%d %d",&x,&y); if(x>=1&&x<=row&&y>=1&&y<=col)//防止輸入非法棋子位置 { if(board[x-1][y-1] == ' ')//注意這里的x-1和y-1,玩家在輸入的時(shí)候輸入的假如是1 2,那么給電腦的值就是0 1,這么做是為了與二維數(shù)組的下標(biāo)對(duì)應(yīng) { board[x-1][y-1] = '*';//注意這里只有一個(gè)等號(hào)!?。∨c上面不同,這里是重新定義而上面是相等的時(shí)候 break; } else { printf("該坐標(biāo)被占用,請(qǐng)重新輸入\n"); } } else { printf("輸入非法,請(qǐng)重新輸入"); } } }
4.4電腦下棋 :ComputerMove
再寫電腦下棋:思路是如果電腦輸入的地址原來(lái)為空格,那么就把這個(gè)位置重新定義為 #,只不過(guò)不同的是電腦輸入的x和y是用rand()%3設(shè)置出來(lái)的隨機(jī)值,所以我們還要在前面的test函數(shù)中放下srand的設(shè)置。
void ComputerMove(char board[ROW][COL],int row,int col) { int x = 0; int y = 0; printf("電腦下棋\n"); while(1) { x = rand()%ROW//此時(shí)ROW為3,即x等于0到2的隨機(jī)值 y = rand()%COL//此時(shí)COL為3,即Y等于0到2的隨機(jī)值 if(board[x][y] == '') { board[x][y] = '#'; break; } } }
4.5輸贏的判斷 ;Win
我們要有判斷輸贏的代碼,并且初始化一個(gè)值讓其接受返回值
玩家贏 - '*'
電腦贏 - '#'
平均 --- 'Q'
繼續(xù) ----'C'
char Win(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++)//看一下橫著的/豎著的3個(gè)符號(hào)是否相等,返回一個(gè)值讓game()中的ret接收 { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1]!='') { return board[i][1]; } } for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i]!=' ') { return board[0][i]; } } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1]!=' ') { return board[1][1]; } if(1 == FULL(board,row,col)) { return 'Q';//如果經(jīng)過(guò)FULL函數(shù)判定棋盤滿了那么返回一個(gè)Q讓ret接收,否則返回C } return 'C'; }
4.6平局的判定 :FULL
因?yàn)橐祷刂?,所以這個(gè)函數(shù)用int類型存放數(shù)據(jù)
int Full(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++) { if(board[i][j] == ' ') { return 0;//返回值為0 } } } return 1;//如果棋盤滿了則返回1 }
5.game函數(shù)
現(xiàn)在可以把所有的函數(shù)引用了
void game() { char board[ROW][COL] = {0}; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); char ret = 0;//初始化ret,ret為前面說(shuō)的那個(gè)返回值 //判斷輸贏的代碼 //玩家贏 - '*' //電腦贏 - '#' //平均 --- 'Q' //繼續(xù) ----'C' while (1) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = Win(board, ROW, COL); if (ret != 'C') { break; } ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = Win(board, ROW, COL); if (ret != 'C') { break; } } if (ret == '*')//到這里才分別判定返回ret的所有值 { printf("恭喜你你贏了!\n"); } else if(ret == '#') { printf("很遺憾你輸了!\n"); } else { printf("平局\n"); } printf("\n"); }
總結(jié)
可以吧game.c和test.c分別當(dāng)做兩個(gè)源文件,test.c中引用game.c,這樣代碼也會(huì)更加清晰。不管有多少函數(shù)需要引用,只需要寫出函數(shù)的本體再引用,這樣一個(gè)龐大的代碼就被我們拆分成了一段一段小代碼,難度也就沒(méi)那么大了。
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Ubuntu配置sublime text 3的c編譯環(huán)境的具體步驟
下面小編就為大家?guī)?lái)一篇Ubuntu配置sublime text 3的c編譯環(huán)境的具體步驟。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03C語(yǔ)言職工管理系統(tǒng)設(shè)計(jì)
這篇文章主要為大家分享了一份C語(yǔ)言職工管理系統(tǒng)設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06使用Visual Studio進(jìn)行動(dòng)態(tài)鏈接庫(kù)開發(fā)流程
這篇文章主要介紹了使用Visual Studio進(jìn)行動(dòng)態(tài)鏈接庫(kù)開發(fā)流程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05C語(yǔ)言高級(jí)教程之變長(zhǎng)數(shù)組詳解
這篇文章主要介紹了C語(yǔ)言中變長(zhǎng)數(shù)組的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr
雖然通過(guò)弱引用指針可以有效的解除循環(huán)引用,但這種方式必須在程序員能預(yù)見會(huì)出現(xiàn)循環(huán)引用的情況下才能使用,也可以是說(shuō)這個(gè)僅僅是一種編譯期的解決方案,如果程序在運(yùn)行過(guò)程中出現(xiàn)了循環(huán)引用,還是會(huì)造成內(nèi)存泄漏的2013-09-09