@toc 算法
工程文件思路:主函數
放到ticktacktoe
(三子棋)中三子棋具體的實現
放到game.c / game.h
中數組
主函數遊戲思路:
三子棋遊戲思路:
一、至少玩一次,能夠玩屢次,do…while循環
二、進入遊戲後先打印菜單提示
三、提示用戶輸入,根據輸入值來肯定後續的遊戲進程(1表明玩遊戲,0表明退出,其餘須要從新選擇
三子棋玩遊戲的思路:markdown
首先咱們要知道三子棋的一些信息:
一、三子棋形狀框架
二、遊戲規則:同一形狀連成直線(三格)即獲勝
因此獲勝的條件:一、橫排同形狀 二、豎排同形狀 三、對角線同形狀
三子棋遊戲實現具體思路:
1.咱們要記錄下棋的結果,就須要對應的二維數組來存儲
2.建立的二維數組要進行初始化,賦值成空格" "
3.打印棋盤,看一下展現的效果ide
遊戲狀態判斷 四種狀態 玩家贏,電腦贏,平局,繼續
4.玩家下棋
5.判斷玩家是否遊戲勝利 判斷遊戲狀態是否繼續
6.電腦下棋(隨機落子的方式)
7.判斷電腦是否遊戲勝利 判斷遊戲狀態是否繼續函數
void menu() { printf("***************************************\n"); printf("*********1 play game ****************\n"); printf("*********0 exit game ****************\n"); printf("***************************************\n"); }
int main() { menu(); int input=0; do { printf("請選擇:\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出遊戲\n"); break; default: printf("選擇錯誤"); break; } } while (input); return 0; }
注:測試
#define ROW 3 //行 #define COL 3 //列
1.大致結構咱們已經完成,接下來咱們設計該遊戲的重中之重,遊戲函數game()
關於該遊戲咱們首先要對棋盤進行初始化將其初始化爲空格,這裏用兩個循環來實現優化
void Init_board(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0;i < ROW;i++) { for(j=0;j<COL;j++) { board[i][j] = ' '; } } }
2.初始化棋盤後,咱們進行打印棋盤設計
void print_board(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0;i < row;i++) { printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]); if(i<row-1) printf("---|---|---\n"); } }
咱們先看這種,這種寫法確實符合咱們的要求,但咱們仔細想一想,若是咱們把開始的ROE ,COL定義成其餘的數字,那麼這種寫法就不能實現,例如5x5,10x10的棋盤,由於上述代碼的printf所寫的,已經將他的形式鎖死了,因此不能實現其餘棋盤,因此這種寫法難以推廣,接下來咱們進行優化3d
void print_board(char board[ROW][COL], int row, int col) { int i = 0,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"); } } }
寫成這樣咱們就能夠打印各類棋盤了
3.當棋盤完成初始化及打印完棋盤後,咱們就能夠進行下棋了
進行下棋時,無疑覺得玩家一步,電腦一步,首先咱們來完成玩家下棋的代碼
void playermove(char board[ROW][COL], int row, int col) { int x = 0, y = 0; printf("玩家走\n"); while (1) { printf("請輸入一個座標"); scanf("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <=col) { if (board[x - 1][y - 1] != ' ') { printf("該座標已被佔用,請從新輸入"); } else { board[x - 1][y - 1] = '*'; break; } } else { printf("座標錯誤,請從新輸入"); } } }
這裏咱們要注意,咱們所寫的程序是面向用戶的,他們不會像咱們同樣知道二維i數組的第一個座標是(0,0),他們會寫成(1,1),
因此咱們這裏寫成 board[x - 1][y - 1]
其次是電腦下棋
void computermove(char board[ROW][COL], int row, int col) { printf("電腦走\n"); while (1) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
這裏咱們的電腦是比較「笨」的,他所下棋的位置是比較隨機的,同時咱們還要注意這裏rand(隨機數) 函數的使用,由於電腦下棋座標是(0,0)到(2,2)(這裏是以二維數組來講),因此rand()%3 便可,這樣隨機數的範圍就是0-2了,同時使用了rand就須要srand配合使用,
寫到這裏咱們將主函數增長srand((unsigned)time(NULL)); 語句
(這裏簡單說下rand 函數隨機數範圍肯定,ranf ()%num,生成隨機數的範圍就是0到num-1)
遊戲已經大體完成 ,接下來實現判斷遊戲輸贏,這裏我用如下進行判斷
井號 表明電腦贏
星號表明人贏
c 表明繼續
f 表明平局
void game() { char ret; char board[ROW][COL]; //初始化棋盤 Init_board(board, ROW, COL ); //打印棋盤 print_board(board, ROW ,COL); while (1) { playermove(board, ROW, COL);//玩家下棋 ret =checkwin(board, ROW, COL); if (ret != 'c') { break; } print_board(board, ROW, COL); computermove(board, ROW, COL);//電腦下棋 ret = checkwin(board, ROW, COL); if (ret != 'c') { break; } print_board(board, ROW, COL); } if (ret == '#') printf("電腦贏了\n"); if (ret == '*') printf("你贏了\n"); if (ret == 'f') printf("雙方平局\n"); print_board(board, ROW, COL); }
上述大致判斷框架完成,接下來就是checkwin() 函數的實現
這個遊戲無疑就是三行,三列,或對角線連成一條線則取得勝利,且每個格子裏不是咱們所初始化的空格
char checkwin(char board[ROW][COL], int row, int col) { int i = 0; //三行 for (i = 0;i < row;i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') { return board[i][0]; } } //三列 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 (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //平局 if (full(board,row,col) == 1) { return 'f'; } //遊戲繼續,沒有贏或平局 return 'c'; }
這裏咱們又寫了一個新的函數full()來判斷棋盤是否填滿
int full(char board[ROW][COL], int row, int col) { int j = 0, i = 0; for (i = 0;i < row;i++) { for (j = 0;j < col;j++) { if (board[i][j] == ' ') return 0; } } return 1; }
到這遊戲實現,具體思路就這樣的
#define _CRT_SECURE_NO_WARNINGS 1 #define ROW 3 #define COL 3 #include<stdio.h> #include <stdlib.h> #include <time.h> //初始化棋盤 void Init_board(char board[ROW][COL], int row, int col); //打印棋盤 void DisplayBoard(char board[ROW][COL], int row, int col); //玩家下棋 void PlayerMove(char board[ROW][COL], int row, int col); //電腦下棋 void ComputerMove(char board[ROW][COL], int row, int col); //檢測輸贏 char IsWin(char board[ROW][COL], int row, int col); //告訴咱們四種遊戲的狀態 //玩家贏 - '*' //電腦贏 - '#' //平局 - 'Q' //繼續 - 'C'
//game.c遊戲實現部分 #include "game.h" //棋盤初始化爲空格的函數 void InitBoard(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++) { board[i][j] = ' '; } } } //打印棋盤的函數 //void DisplayBoard(char board[ROW][COL], int row, int col) //{ // int i = 0; // for (i = 0; i < row; i++) // { // //打印一行的數據 // printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]); // //打印分割行 // if (i < row - 1) // printf("---|---|---\n"); // } //} //這個打印函數寫死了棋盤邊框,只有3*3的棋盤邊框,所以不是很合適 //改進後的棋盤打印函數 void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; 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"); } } } //保存下棋步驟的函數 //玩家走步記錄函數 //這裏要站在玩家角度設計代碼,3*3列棋盤玩家通常會認爲是3行(1,2,3行)*3列(1,2,3列) //實際上在計算機思惟上應該是3行(0,1,2行)*3列(0,1,2列) void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家先走:(行+空格+列)\n"); while (1) { printf("請輸入要下的座標:>"); scanf("%d%d", &x, &y); //判斷x,y座標的合法性 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("該座標被佔用\n"); } } else { printf("座標非法,請從新輸入!\n"); } } } //電腦走步記錄函數 void ComputerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("電腦走:>\n"); while (1) { x = rand() % row;//模3只能產生0,1,2 y = rand() % col;//模3只能產生0,1,2 if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } //棋盤是否下滿的判斷函數 //返回1表示棋盤滿了 //返回0,表示棋盤沒滿 int IsFull(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;//沒滿 } } } return 1;//滿了 } //檢查橫三行,豎三列,對角線是否有三個相同的棋子 char IsWin(char board[ROW][COL], int row, int col) { int i = 0; //橫三行 for (i = 0; i < row; i++) { 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[1][i] != ' ') { //當有三個棋子相同時,返回三個棋子中的一個便可 //設定中,玩家下棋是‘*’,電腦下棋是'#’,玩家贏 返回,'*'電腦贏返回'#' //不用判斷電腦下棋仍是人下棋,直接返回就行 return board[1][i]; } } //兩個對角線 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') return board[1][1]; if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ') return board[1][1]; //判斷是否平局 if (1 == IsFull(board, ROW, COL)) { //當棋盤滿了沒有結果說明平局 return 'Q'; } //判斷完,輸贏,平局,只剩下一種繼續的可能性 return 'C'; }
//ticktacktoe.c遊戲測試及初始化部分 #define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void menu() { printf("**********************\n"); printf("*** 1.play 2.exit ***\n"); printf("**********************\n"); } //遊戲算法實現 void game() { char ret = 0; //採用數組存儲走出的棋盤信息 char board[ROW][COL] = { 0 }; //棋盤初始化爲空格 InitBoard(board,ROW,COL); //打印棋盤邊框 DisplayBoard(board, ROW, COL); //下棋程序,玩家先下,電腦後下 //既然是在棋盤內下棋,那麼形參列表應該有棋盤的相關信息 //調用須要行列信息,棋盤信息 while (1) { //玩家走步記錄函數及打印 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判斷玩家是否贏 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } //電腦走步記錄函數及打印 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判斷電腦是否贏 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } } //經過Iswin輸贏判斷函數的返回值輸出遊戲結果 if (ret == '*') { printf("玩家贏\n"); } else if (ret == '#') { printf("電腦贏\n"); } else { printf("平局\n"); } } void test() { int input = 0; srand((unsigned int)time(NULL));//用時間戳控制生成隨機值 do { menu(); printf("請選擇:>"); scanf("%d", &input); switch (input) { case 0: printf("退出遊戲\n"); break; case 1: printf("遊戲開始\n"); game(); break; default: printf("選擇錯誤,請從新選擇!\n"); break; } } while (input); } int main() { test(); return 0; }