C語言實(shí)現(xiàn)井字棋詳解
1.主函數(shù)
這個(gè)代碼很長,我們可以把它全部寫在主函數(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)來完成大部分函數(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è)三乘三的棋盤來說,有以下的步驟:
數(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ù)是把棋盤的形狀打印出來
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
先寫玩家下棋:思路是如果玩家輸入的地址原來為空格,那么就把這個(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
再寫電腦下棋:思路是如果電腦輸入的地址原來為空格,那么就把這個(gè)位置重新定義為 #,只不過不同的是電腦輸入的x和y是用rand()%3設(shè)置出來的隨機(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)過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為前面說的那個(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è)龐大的代碼就被我們拆分成了一段一段小代碼,難度也就沒那么大了。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Ubuntu配置sublime text 3的c編譯環(huán)境的具體步驟
下面小編就為大家?guī)硪黄猆buntu配置sublime text 3的c編譯環(huán)境的具體步驟。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
使用Visual Studio進(jìn)行動(dòng)態(tài)鏈接庫開發(fā)流程
這篇文章主要介紹了使用Visual Studio進(jìn)行動(dòng)態(tài)鏈接庫開發(fā)流程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05
淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr
雖然通過弱引用指針可以有效的解除循環(huán)引用,但這種方式必須在程序員能預(yù)見會(huì)出現(xiàn)循環(huán)引用的情況下才能使用,也可以是說這個(gè)僅僅是一種編譯期的解決方案,如果程序在運(yùn)行過程中出現(xiàn)了循環(huán)引用,還是會(huì)造成內(nèi)存泄漏的2013-09-09

