C語(yǔ)言數(shù)組應(yīng)用實(shí)現(xiàn)三子棋游戲
三子棋游戲的基本構(gòu)架是數(shù)組的應(yīng)用,但是要實(shí)現(xiàn)游戲還得結(jié)合具有相關(guān)功能的函數(shù),接下來(lái)就介紹三子棋游戲的基本框架及相關(guān)函數(shù):
下面先介紹一下寫(xiě)三子棋代碼的過(guò)程和思路:
1、游戲開(kāi)始要先顯示游戲界面 (菜單函數(shù)) 。
2、要有一個(gè)棋盤(pán)給玩家下棋,所以需要一個(gè)二維數(shù)組,最開(kāi)始顯示給玩家的棋盤(pán)應(yīng)該是空棋盤(pán),所以初始化數(shù)組為空格(棋盤(pán)初始化函數(shù)) ,全為空格的數(shù)組打印出來(lái)是沒(méi)有顯示的,所以我們要畫(huà)一個(gè)棋盤(pán)框并把它打印出來(lái)(打印棋盤(pán)函數(shù)) 。
3、開(kāi)始游戲后,玩家下棋(玩家下棋函數(shù)) ,數(shù)組更改并打印,電腦下棋(電腦下棋函數(shù)) ,數(shù)組更改并打印。
4、游戲是一個(gè)循環(huán)的過(guò)程,所以輸贏(判斷輸贏函數(shù))及平局(判斷平局函數(shù))的判斷也是一個(gè)循環(huán)的過(guò)程,因此判斷輸贏及平局應(yīng)該在下每一顆棋子后就進(jìn)行判斷。
來(lái)看一下游戲效果:
程序運(yùn)行,顯示游戲菜單,選擇1開(kāi)始游戲。
玩家落子為x,電腦落子為0。
這里的棋盤(pán)行和列用宏定義可以方便更改:
#define ROW 3 #define COL 3?
頭文件game.h:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 3 #define COL 3 void setboard(char arr[ROW][COL], int row, int col); void displayboard(char arr[ROW][COL], int row, int col); void playermove(char arr[ROW][COL], int row, int col); void computermove(char arr[ROW][COL], int row, int col); int iswin(char arr[ROW][COL], int row, int col); int isfull(char arr[ROW][COL], int row, int col); void menu();
源文件main.c:
- 按照前面的分析及思路寫(xiě)出框架,完善函數(shù)功能,構(gòu)成體系;
- 人機(jī)對(duì)戰(zhàn)中電腦下棋是隨機(jī)的;
- 需要注意在每次落子后都要判斷輸贏平局;
#define _CRT_SECURE_NO_WARNINGS 1 //三子棋主函數(shù) #include "game.h" int main() { ?srand((unsigned int)time(NULL)); ? //游戲界面 ?int x = 0; ?int ret = 0; ?char n = 0; ?while(1) ?{ ? menu();//菜單 ? scanf("%d", &x); ? printf("\n"); ? if (x == 1) ? { ? ?//設(shè)置棋盤(pán) ? ?char arr[ROW][COL] = { 0 }; ? ?setboard(arr, ROW, COL);//棋盤(pán)初始化為空格 ? ?displayboard(arr, ROW, COL);//打印棋盤(pán) ? ?while (1) ? ?{ ? ? //玩家下棋 ? ? playermove(arr, ROW, COL); ? ? //打印棋盤(pán) ? ? displayboard(arr, ROW, COL); ? ? //判斷平局 ? ? ret = isfull(arr, ROW, COL); ? ? if (ret == 1) ? ? { ? ? ?printf("平局\n"); ? ? ?break; ? ? } ? ? //判斷輸贏 ? ? n = iswin(arr, ROW, COL); ? ? if (n == 'x') ? ? { ? ? ?printf("玩家贏\n"); ? ? ?break; ? ? } ? ? else if (n == '0') ? ? { ? ? ?printf("電腦贏\n"); ? ? ?break; ? ? } ? ? //玩家贏--x ? ? //電腦贏--0 ? ? //平局--P ? ? //繼續(xù)--C ? ?? ? ? //電腦下棋 ? ? computermove(arr, ROW, COL); ? ? //打印棋盤(pán) ? ? displayboard(arr, ROW, COL); ? ? //判斷平局 ? ? ret = isfull(arr, ROW, COL); ? ? if (ret == 1) ? ? { ? ? ?printf("平局\n"); ? ? ?break; ? ? } ? ? //判斷輸贏 ? ? n = iswin(arr, ROW, COL); ? ? if (n == 'x') ? ? { ? ? ?printf("玩家贏\n"); ? ? ?break; ? ? } ? ? else if (n == '0') ? ? { ? ? ?printf("電腦贏\n"); ? ? ?break; ? ? } ? ?} ? }? ?else if (x == 0) ? ?break; ?else ?printf("輸入錯(cuò)誤,請(qǐng)重新輸入!\n"); ? ?} ?system("pause"); ?return 0; }
源文件game.c:
主要的函數(shù)有以下幾個(gè):
(菜單函數(shù)沒(méi)什么可講的)
- 初始化棋盤(pán)
void setboard(char arr[ROW][COL], int row, int col) { ?int i = 0; ?int j = 0; ?for (i = 0; i < ROW; i++)//棋盤(pán)初始化為空格 ?{ ? for (j = 0; j < COL; j++) ? { ? ?arr[i][j] = ' '; ? } ?? ?} }
- 打印棋盤(pán)
這里我加了格子的序號(hào),提高使用感,在大于3小于10的棋盤(pán)中可以更好的找到想要的坐標(biāo),為什么小于10呢,因?yàn)樵谛蛱?hào)由一位數(shù)變?yōu)閮晌粩?shù)時(shí),打印出來(lái)的棋盤(pán)不規(guī)整了,當(dāng)然這個(gè)地方還可以優(yōu)化,目前就只支持行列小于10的棋盤(pán)。
void displayboard(char arr[ROW][COL], int row, int col) { ?int i = 0; ?int j = 0; ? ?for (i = 1; i <= col; i++) ?{ ? printf(" ?%d ?", i); ? if (i < COL ) ? ?printf("|"); ?} ?printf("\n"); ?for (j = 0; j < COL ; j++) ?{ ? if (j == 0) ? { ? ?printf(" ----"); ? } ? else if (j > 0) ? { ? ?printf("-----"); ? } ? if (j < COL - 1) ? ?printf("|"); ?} ?printf("\n"); ? ?for (i = 0; i < ROW; i++) ?{ ? printf("%d ", i + 1); ? for(j = 0; j < COL; j++) ? {? ? ?if (j == 0) ? ?{ ? ? printf(" %c ", arr[i][j]); ? ?} ? ?else ? ?{ ? ? printf(" ?%c ?", arr[i][j]); ? ?} ? ? ? ?if(j < COL - 1) ? ? ? printf("|"); ? } ? printf("\n"); ? if(i < ROW-1) ? {? ? ?for (j = 0; j < COL; j++) ? ?{ ? ? if (j == 0) ? ? { ? ? ?printf(" ----"); ? ? } ? ? else if (j > 0) ? ? { ? ? ?printf("-----"); ? ? } ? ? if (j < COL - 1) ? ? ?printf("|"); ? ?} ? ?printf("\n"); ? } ?} ? }?
- 玩家下棋
這里要注意判斷坐標(biāo)的合法性
void playermove(char arr[ROW][COL], int row, int col) { ?printf("\n\n玩家走:>\n"); ?while (1) ?{ ? printf("請(qǐng)輸入坐標(biāo):>"); ? int x = 0; ? int y = 0; ? scanf("%d%d", &x, &y); ? if (x > 0 && x <= ROW && y > 0 && y <= COL && arr[x-1][y-1] == ' ') ? { ? ?arr[x-1][y-1] = 'x'; ? ?break; ? } ? else if (x > ROW || y > COL) ? { ? ?printf("錯(cuò)誤坐標(biāo),請(qǐng)重新輸入!\n"); ? } ? else if (arr[x-1][y-1] != ' ') ? { ? ?printf("該坐標(biāo)下過(guò)棋了,請(qǐng)重新輸入!\n"); ? } ?? ?} ? }
- 電腦下棋
電腦下棋是隨機(jī)的,利用rand();及srand();產(chǎn)生0-2的隨機(jī)數(shù),注意生成隨機(jī)數(shù)需要引用time.h這個(gè)頭文件,雖然是產(chǎn)生隨機(jī)坐標(biāo)但是要確定電腦找到一個(gè)有空位的棋格才可以停下。
void computermove(char arr[ROW][COL], int row, int col) { ?printf("\n\n電腦走:>\n"); ?int x = 0; ?int y = 0; ?while (1) ?{ ? x = rand() % ROW; ? y = rand() % COL; ? if (arr[x][y] == ' ') ? { ? ?arr[x][y] = '0'; ? ?break; ? } ?} ? }
- 判斷平局
int isfull(char arr[ROW][COL], int row, int col) { ?int x = 0; ?int y = 0; ?for (x = 0; x < row; x++) ?{ ? for (y = 0; y < col; y++) ? { ? ?if (arr[x][y] == ' ') ? ? return 0; ? } ?} ?return 1; }
- 判斷輸贏
只要棋盤(pán)中任意一個(gè)坐標(biāo)的行,列,斜為相同符號(hào),即為勝利,我這里在保證坐標(biāo)合法的前提下對(duì)每一個(gè)坐標(biāo)周圍8個(gè)坐標(biāo)進(jìn)行判斷,這樣可以做到在非3x3的棋盤(pán)中也可以完成三子棋游戲,當(dāng)然這段代碼只是實(shí)現(xiàn)了功能而已,寫(xiě)的非常繁瑣,我也覺(jué)得非3x3里還下三子棋說(shuō)不過(guò)去,之后也可以繼續(xù)擴(kuò)展到五子棋的判斷輸贏,以后再詳細(xì)整改。
int ?iswin(char arr[ROW][COL], int row, int col) { ?int x = 0;? ?int y = 0; ?int count = 0; ? ? ?for (x = 0; x < row; x++) ?{ ? for (y = 0; y < col; y++) ? { ?? ? ?if (arr[x][y] == arr[x][y - 1] && arr[x][y - 1] == arr[x][y + 1] && arr[x][y] != ' '&& arr[x][y-1] != ' '&& arr[x][y+1] != ' ') ? ?{ ? ? return arr[x][y]; ? ?} ? ?else if (arr[x][y] == arr[x - 1][y + 1] && arr[x - 1][y + 1] == arr[x + 1][y - 1] && arr[x][y] != ' '&& arr[x-1][y+1] != ' '&& arr[x+1][y-1] != ' ') ? ?{ ? ? return arr[x][y]; ? ?} ? ?else if(arr[x][y] == arr[x - 1][y] && arr[x - 1][y] == arr[x + 1][y] && arr[x][y] != ' '&& arr[x-1][y] != ' '&& arr[x+1][y] != ' ') ? ?{ ? ? return arr[x][y]; ? ?} ? ?else if (arr[x][y] == arr[x - 1][y - 1] && arr[x - 1][y - 1] == arr[x + 1][y + 1] && arr[x][y] != ' '&& arr[x-1][y-1] != ' '&& arr[x+1][y+1] != ' ') ? ?{ ? ? return arr[x][y]; ? ?} ? } ?} }
以上就是我的代碼,寫(xiě)完以后還有些小遺憾,很多地方?jīng)]有處理好,希望各位能幫我優(yōu)化改進(jìn)。
希望本文對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java C++題解leetcode915分割數(shù)組示例
這篇文章主要為大家介紹了Java C++題解leetcode915分割數(shù)組示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11C++ 中回文數(shù)判斷簡(jiǎn)單實(shí)例
這篇文章主要介紹了C++ 中回文數(shù)判斷簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05C++圖論之Bellman-Ford算法和SPFA算法的實(shí)現(xiàn)
貝爾曼-福特算法(Bellman-Ford)是由理查德·貝爾曼和萊斯特·福特創(chuàng)立的,求解單源最短路徑問(wèn)題的一種算法。SPFA 算法是 Bellman-Ford算法 的隊(duì)列優(yōu)化算法的別稱,通常用于求含負(fù)權(quán)邊的單源最短路徑。本文將詳解兩個(gè)算法的實(shí)現(xiàn),需要的可以參考一下2022-06-06C語(yǔ)言實(shí)現(xiàn)繪制立體餅圖的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何使用C語(yǔ)言實(shí)現(xiàn)繪制立體餅圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03C++中的四個(gè)默認(rèn)成員函數(shù)與運(yùn)算符重載詳解
這篇文章主要給大家介紹了關(guān)于C++中四個(gè)默認(rèn)成員函數(shù)與運(yùn)算符重載的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)跟著小編一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08C++ 重載與重寫(xiě)的區(qū)別與實(shí)現(xiàn)
在面向?qū)ο笳Z(yǔ)言中,經(jīng)常提到重載與重寫(xiě),本文主要介紹了C++ 重載與重寫(xiě)的區(qū)別與實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01