C語言新手初階教程之三子棋實現
三子棋
大傢小時候應該都玩過三子棋吧,學習瞭這麼久的C語言,我們其實已經具備瞭做三子棋這種小型項目的能力,今天我會盡量沉浸式的教大傢實現三子棋,如果看完這篇博客還是不會的可以去我最後附上的gitee倉庫鏈接中尋找。但我還是希望大傢能自己完成,在三子棋中體現自己的風格。
創建項目環境
首先,第一步,打開我們的vs編譯器,新建一個三子棋項目
在這個新建的項目中創建三個文件
1.test.c
2.game.c
3.game.h
我們把函數聲明和頭文件的引入放在game.h這個頭文件中
將一些自定義函數定義放在game.c中
將主函數的編寫放在test.c中
現在直接上頭文件的內容,一會一步一步的教大傢實現頭文件中的接口和引用頭文件的原因
頭文件內容
#ifndef __GAME_H__ #define __GAME_H__ #include<stdio.h> #include<stdlib.h> #include<time.h> #include<Windows.h> #define H 3 #define L 3 void menu(); void game(); void board(char arr[H][L],int x,int y); void printfboard(char arr[H][L], int x,int y); void play(char arr[H][L], int x, int y); void computerplay(char arr[H][L], int x, int y); char win(char arr[H][L],int x,int y); #endif
#ifndef #define #endif是為瞭防止頭文件重復引入,其實在大傢自己創建頭文件時自帶的 #pramga once 同樣也可以達到目的
編寫main函數(test.c)
寫test.c第一步引用頭文件game.h即 #include"game.h" 玩遊戲一定要有一個菜單,所以我們需要打印寫一個菜單,這個菜單函數的實現就在test.c中進行即可 但我們先需要在頭文件中聲明void menu(); 接下來實現菜單 void menu(){ printf("*******************\n"); printf("***1.play 0.exit***\n"); printf("*******************\n"); } 我們使用瞭printf函數,我們這個時候需要引用帶有標準輸入輸出流的頭文件stdio.h 然後我們在game.h中加上#include<stdio.h>
像這種選擇1,開始遊戲,選擇退出程序的模式,我們可以直接用switch來實現 遊戲肯定不止一把,隻要用戶不選擇0,就讓用戶一直玩,所以我們這樣編寫主函數 int main() { int input; do{ menu(); again: printf("請輸入:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出遊戲\n"); break; default: printf("輸入錯誤,請重新輸入\n"); goto again; } } while (input); return 0; } 為瞭防止用戶輸入錯誤,直接退出瞭程序,我們利用goto的特性來實現
接下來我們組裝一下,text.c就完成瞭
#include"game.h" void menu() { printf("*********************\n"); printf("**1.play 0.exit*****\n"); printf("*********************\n"); } int main() { int input; do{ menu(); again: printf("請輸入:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出遊戲\n"); break; default: printf("輸入錯誤,請重新輸入\n"); goto again; } } while (input); return 0; }
實現每一個接口函數
這一個過程可能有點復雜,大傢可能需要多多上手實驗
game函數是相當於game.c的main函數,我們需要一步一步去構建
1.board
在下三子棋之前我們應該知道用什麼來承載棋子,三行三列的棋子,正好對應瞭二維數組的行和列 我們就用二維數組來進行 在game函數中我們可以加入 int arr[3][3]; 但是在實際設計程序中,不建議大傢使用數字,可能會出現錯誤,而且直接定義三行三列 之後我們想改造三子棋為五子棋會很麻煩,這個時候我們可以用常量來代替 所以我們應該在頭文件中加入這兩行代碼,H代表行,L代表列 #define H 3 #define L 3
void game(){ char arr[H][L]; board(arr,H,L); } board函數是用來實現初始化棋盤的,沒有下子的位置都將其初始化為空,即空格 void board(char arr[H][L], int x, int y) { int i, j; for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { arr[i][j] = ' '; } } }
2.printfboard
初始化之後,我們需要打印棋盤這個printfboard函數是用來打印棋盤的,這一步比較重要,也比較困難,這個需要大傢多動手嘗試,先給大傢看看我們理想的棋盤效果
從圖中我們可以看到,我們用|和-作為分割符
void printfboard(char arr[H][L], int x, int y) { for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { printf(" %c ", arr[i][j]); if (j < y - 1) printf("|"); } printf("\n"); if (i < x - 1) { for (int j = 0; j < y; j++) { printf("---"); if (j < y - 1) printf("|"); } printf("\n"); } } }
接下來講game函數改造為 void game(){ char arr[H][L]; board(arr,H,L); printfboard(arr,H,L); }
這個函數的實現並不簡單,希望大傢多多嘗試
3.play
接下來我們開始下棋瞭,我們先人為固定,我們下的是‘*’,電腦下的是‘#’
首先,用戶並不知道數組下標是從零開始的,我們需要設計從1開始
其次,我們需要提醒用戶的錯誤下棋,比如下在已有棋子的地方和下在棋盤以外
最後,我們需要提醒用戶正確的下棋方法,防止出現程序錯誤
void play(char arr[H][L], int x,int y) { int i, j; again: printf("(提示,以x y的形式輸入,x代表行,y代表列)請輸入你要下棋的位置:"); scanf("%d %d", &i, &j); if (i >= 1 && i <= 3 && j >= 1 && j <= 3) { if (arr[i - 1][j - 1] != ' ') { printf("該位置以有棋子,請重新輸入"); goto again; } else { arr[i-1][j-1] = '*'; printfboard(arr, x, y);//下完棋打印棋盤 } } else { printf("輸入錯誤,請重新輸入"); goto again; } }
4.computerplay
玩傢下完之後,需要電腦來下棋,電腦下棋就需要隨機數rand來進行
首先我們在頭文件中引用 #include<time.h> #include<stdlib.h>
computerplay的要點與play一致 void computerplay(char arr[H][L], int x, int y) { int i, j; srand((unsigned)time(NULL));//作為隨機數的生成起點 again: i = rand()%x; //這樣i和j都隻能是0 1 2符合數組下標規則 j = rand() % y; if (arr[i][j] == ' ') { arr[i][j] = '#'; printfboard(arr, H, L); } else goto again; }
電腦和人在還沒有結束之前需要一直下,而且電腦有時候下的很快,我們需要用Sleep休息一下 void game() { char arr[H][L] = { 0 }; board(arr, H, L); printfboard(arr, H, L); while (1) { play(arr, H, L); printf("電腦正在下棋請稍等\n"); Sleep(1000); computerplay(arr, H, L); } }
5.win
接下來便是整個三子棋的最後一步,判斷輸贏
我們先想一想輸贏的條件,連成一條線就是贏,沒有位置就是平局 平局的條件比較好判斷,但判斷贏我們找不到好的方法就隻能一一列舉 但是我們可以想一些有用的思路,我們從行和列交叉一次判讀 如果相等且不為空格直接返回 當棋盤滿瞭,返回! char win(char arr[H][L], int x, int y) { int i, j; int flag = 0; for (i = 0; i < x; i++) { //行 for (j = 0; j < y - 2; j++) { if (arr[i][j] == arr[i][j + 1] && arr[i][j + 1] == arr[i][j + 2] && arr[i][j] != ' ') return arr[i][j]; } } for (j = 0; j < y; j++) { //列 for (i = 0; i < x - 2; i++) { if (arr[i][j] == arr[i + 1][j] && arr[i + 1][j] == arr[i + 2][j] && arr[i][j] != ' ') return arr[i][j]; } } for (i = 0; i < x - 2; i++) { //對角線 for (j = 0; j < y - 2; j++) { if (arr[i][j] == arr[i + 1][j + 1] && arr[i + 1][j + 1] == arr[i + 2][j + 2] && arr[i][j] != ' ') return arr[i][j]; } for (i = 0; i < x; i++) {//對角線 for (j = y - 1; j > 1; j--) { if (arr[i][j] == arr[i + 1][j - 1] && arr[i + 1][j - 1] == arr[i + 2][j - 2] && arr[i][j] != ' ') return arr[i][j]; } } } for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { if (arr[i][j] == ' ') flag = 1; } } if (flag == 1) return ' '; else return '!'; }
再將game進行改造
void game() { char arr[H][L] = { 0 }; char ret; board(arr, H, L); printfboard(arr, H, L); while (1) { play(arr, H, L); ret = win(arr, H, L); if (ret != ' ') break; printf("電腦正在下棋請稍等\n"); Sleep(1000); computerplay(arr, H, L); ret = win(arr, H, L); if (ret != ' ') break; } if (ret == '*') printf("恭喜你獲勝瞭\n"); else if (ret == '#') printf("很遺憾你輸瞭\n"); else printf("勢均力敵,再接再厲\n"); }
然後將game.c拼裝在一起就完事瞭
#include"game.h" void board(char arr[H][L], int x, int y) { int i, j; for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { arr[i][j] = ' '; } } } void printfboard(char arr[H][L], int x, int y) { for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { printf(" %c ", arr[i][j]); if (j < y - 1) printf("|"); } printf("\n"); if (i < x - 1) { for (int j = 0; j < y; j++) { printf("---"); if (j < y - 1) printf("|"); } printf("\n"); } } } void play(char arr[H][L], int x,int y) { int i, j; again: printf("(提示,以x y的形式輸入,x代表行,y代表列)請輸入你要下棋的位置:"); scanf("%d %d", &i, &j); if (i >= 1 && i <= 3 && j >= 1 && j <= 3) { if (arr[i - 1][j - 1] != ' ') { printf("該位置以有棋子,請重新輸入"); goto again; } else { arr[i-1][j-1] = '*'; printfboard(arr, x, y); } } else { printf("輸入錯誤,請重新輸入"); goto again; } } void computerplay(char arr[H][L], int x, int y) { int i, j; srand((unsigned)time(NULL));//作為隨機數的生成起點 again: i = rand()%x; //這樣i和j都隻能是0 1 2符合數組下標規則 j = rand() % y; if (arr[i][j] == ' ') { arr[i][j] = '#'; printfboard(arr, H, L); } else goto again; } char win(char arr[H][L], int x, int y) { int i, j; int flag = 0; for (i = 0; i < x; i++) { for (j = 0; j < y - 2; j++) { if (arr[i][j] == arr[i][j + 1] && arr[i][j + 1] == arr[i][j + 2] && arr[i][j] != ' ') return arr[i][j]; } } for (j = 0; j < y; j++) { for (i = 0; i < x - 2; i++) { if (arr[i][j] == arr[i + 1][j] && arr[i + 1][j] == arr[i + 2][j] && arr[i][j] != ' ') return arr[i][j]; } } for (i = 0; i < x - 2; i++) { for (j = 0; j < y - 2; j++) { if (arr[i][j] == arr[i + 1][j + 1] && arr[i + 1][j + 1] == arr[i + 2][j + 2] && arr[i][j] != ' ') return arr[i][j]; } for (i = 0; i < x; i++) { for (j = y - 1; j > 1; j--) { if (arr[i][j] == arr[i + 1][j - 1] && arr[i + 1][j - 1] == arr[i + 2][j - 2] && arr[i][j] != ' ') return arr[i][j]; } } } for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { if (arr[i][j] == ' ') flag = 1; } } if (flag == 1) return ' '; else return '!'; } void game() { char arr[H][L] = { 0 }; char ret; board(arr, H, L); printfboard(arr, H, L); while (1) { play(arr, H, L); ret = win(arr, H, L); if (ret != ' ') break; printf("電腦正在下棋請稍等\n"); Sleep(1000); computerplay(arr, H, L); ret = win(arr, H, L); if (ret != ' ') break; } if (ret == '*') printf("恭喜你獲勝瞭\n"); else if (ret == '#') printf("很遺憾你輸瞭\n"); else printf("勢均力敵,再接再厲\n"); }
這是拼裝後的結果
如果想和室友對戰的小夥伴,將computerplay改的和play差不多就行如果想玩五子棋也隻需要對修改H L的常量值,以及判定條件,目前可能依然隻能用列舉來判定
學到這,如果你依然不會,沒關系,直接去我的碼雲上找代碼,當然我希望小夥伴們都能寫出屬於自己的三子棋,這個三子棋也並不完美,電腦下棋肯定是呆呆的,可以嘗試一下ai下棋
總結
到此這篇關於C語言新手初階教程之三子棋實現的文章就介紹到這瞭,更多相關C語言實現三子棋內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!