<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
遊戲思路:
1.建立初始遊戲介面選單
2.建立遊戲內容:
初始化棋盤 列印棋盤 設定兩方棋子
玩家下 電腦下 判斷輸贏
程式碼行數較多,這裡我們 :
建立 game.h 標頭檔案來宣告函數
建立 game.c 原始檔來定義函數
建立 test.c 原始檔來執行遊戲
首先我們來分析,執行程式時,我們要讓電腦顯示出 是進入遊戲還是退出遊戲,建立選單menu
要進行選擇,因此選擇 switch 語句,並且當玩家進入遊戲結束遊戲後,還要再來一把,那麼就要再一次顯示 menu,因此這裡是先進行一次的迴圈,再判斷,選擇 do...while 語句。
為了閱讀方便,我們分開寫,進行函數巢狀呼叫,如下:
void menu() { printf("************************n"); printf("****** 1.play ********n"); printf("****** 0.exit ********n"); printf("************************n"); } void test() { int input; do { printf("請選擇>:n"); menu(); //呼叫建立的選單 scanf("%d",&input); switch (input) { case 1: printf("三子棋n"); break; case 0: printf("退出遊戲n"); break; default: printf("輸入錯誤,請重新輸入>:"); break; } } while (input); } int main() { test(); return 0; }
先建立 game() 函數替代 case1 中 printf("三子棋n");
再來分析,三子棋遊戲有行列,因此我們想到二維陣列三行三列,並且都為空格,在 game 函數中建立棋盤 char board[3][3] = {0}; 並且初始化棋盤,initboard(board,3,3); ,這裡的初始化棋盤函數我們直接在 game 裡呼叫,在.h裡面進行宣告,在 game.c 中進行定義:
game.h void initboard(char board[3][3], int row, int col); //初始化棋盤
game.c void initboard(char board[3][3], int row, int col) //初始化棋盤 { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j=0;j<col;j++) { board[i][j] = ' '; } } }
這裡有一點我們可以優化,若我們要建立五行五列,六行六列時,又要在三個檔案裡面都改動陣列的行列,那能不能一步到位呢?
game.h //這裡我們在.h裡面用宏定義直接進行行列的表達: #define ROW 3 #define COL 3 void initboard(char board[ROW][COL], int row, int col); //初始化棋盤
game.c void initboard(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++) { board[i][j] = ' '; } } }
test.c void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 }
這樣我們只需要改變 宏定義的值,列印的棋盤行列便可以直接改變。
在 game 函數中建立列印棋盤函數
test.c void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 displayboard(board, ROW, COL); //列印棋盤 }
game.h #define ROW 3 #define COL 3 //函數宣告 void initboard(char board[ROW][COL], int row, int col); //初始化棋盤 void displayboard(char board[ROW][COL], int row, int col); //列印棋盤
game.c 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) //看圖可知列印2個豎分割線 因此是 col-1 printf("|"); } printf("n"); //換行列印 //列印分割行 if (i<row-1) //看圖知只列印2行分割線 因此是 row-1 for (j = 0; j < col; j++) //列印三列 { printf("---"); if (j < col - 1) //看圖可知列印2個豎分割線 因此是 col-1 printf("|"); } printf("n"); //不要忘記換行 } }
棋盤如下:
在 game 函數中建立玩家下棋函數
test.c void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 displayboard(board, ROW, COL); //列印棋盤 play_move(board, ROW, COL); //玩家下棋 displayboard(board, ROW, COL); //列印棋盤 走一步列印一次 }
game.h #define ROW 3 #define COL 3 //函數宣告 void initboard(char board[ROW][COL], int row, int col); //初始化棋盤 void displayboard(char board[ROW][COL], int row, int col); //列印棋盤 void play_move(char board[ROW][COL], int row, int col); //玩家下棋
玩家只需看棋盤輸入座標即可:
注:這裡要注意 陣列行列下標都是從0開始,因此賦子時行列必須對應的減去1
game.c void play_move(char board[ROW][COL], int row, int col) //玩家下棋 { int x = 0; int y = 0; printf("玩家下棋>:"); while (1) 需要重複下棋,是迴圈 { scanf("%d %d",&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"); } } }
在 game 函數中建立電腦下棋函數
test.c void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 displayboard(board, ROW, COL); //列印棋盤 play_move(board, ROW, COL); //玩家下棋 displayboard(board, ROW, COL); //列印棋盤 走一步列印一次 computer_move(board, ROW, COL); //電腦下棋 displayboard(board, ROW, COL); //走一步列印一次 } void test() { int input; srand((unsigned int)time(NULL)); //在test函數裡設定亂數,srand需在rand之前使用 do { printf("請選擇>:n"); menu(); scanf("%d",&input); switch (input) { case 1: game(); break; case 0: printf("退出遊戲n"); break; default: printf("輸入錯誤,請重新輸入>:"); break; } } while (input); }
game.h #include <time.h> //設定亂數需要用到時間戳 #include <stdlib.h> //設定亂數需要用到 srand 和rand #define ROW 3 #define COL 3 //函數宣告 void initboard(char board[ROW][COL], int row, int col); //初始化棋盤 void displayboard(char board[ROW][COL], int row, int col); //列印棋盤 void play_move(char board[ROW][COL], int row, int col); //玩家下棋 void computer_move(char board[ROW][COL], int row, int col); //電腦下棋
用亂數設定電腦落子座標
game.c void computer_move(char board[ROW][COL], int row, int col) //電腦下棋 { printf("電腦下棋:n"); while (1) //重複下,因此是迴圈 { int x = rand() % ROW; //0~2 //電腦下棋為隨機 int y = rand() % COL; //0~2 //我們只需要設定亂數和亂數的範圍 if (board[x][y] == ' ') { board[x][y] = '#'; //設定電腦棋子為'#' break; //走一步跳出迴圈,防止死迴圈 } } }
注意:玩家和電腦下棋均為迴圈,因此在呼叫下棋函數是都應重複呼叫,則game函數裡應為:
test.c void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 displayboard(board, ROW, COL); //列印棋盤 while (1) { play_move(board, ROW, COL); //玩家下棋 displayboard(board, ROW, COL); computer_move(board, ROW, COL); displayboard(board, ROW, COL); }
宣告函數,並分析遊戲結果:三行相同 三列相同 對角線相同 玩家贏或電腦贏 或者是下滿棋盤平局。用不同符號表示不同結果:
game.h #include <time.h> #include <stdlib.h> #define ROW 3 #define COL 3 //函數宣告 void initboard(char board[ROW][COL], int row, int col); //初始化棋盤 void displayboard(char board[ROW][COL], int row, int col); //列印棋盤 void play_move(char board[ROW][COL], int row, int col); //玩家下棋 void computer_move(char board[ROW][COL], int row, int col); //電腦下棋 char is_win(char board[ROW][COL], int row, int col); //判斷輸贏 玩家贏'*' 電腦贏'#' 平局'Q' 繼續'C'
test.c void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 displayboard(board, ROW, COL); //列印棋盤 char ret = 0; //建立ret方便函數返回字元 while (1) { play_move(board, ROW, COL); //玩家下棋 displayboard(board, ROW, COL); ret = is_win(board, ROW, COL); //返回字元並判斷 C為繼續 if (ret!='C') { break; } computer_move(board, ROW, COL); displayboard(board, ROW, COL); ret = is_win(board, ROW, COL); //返回字元並判斷 C為繼續 if (ret!='C') { break; } } if (ret == '*') { printf("玩家贏n"); } else if (ret == '#') { printf("電腦贏n"); } else //這裡ret='Q' { printf("平局n"); } }
函數實現:
game.c int is_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; } } } return 1; //沒有空的座標時返回1 } char is_win(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[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //判斷平局 if (1 == is_full(board, row, col)) //當座標沒空子時,且上述條件不成立則等於1 { return 'Q'; //返回'Q' } //繼續 return 'C'; }
這裡平局函數is_full,在函數is_win裡呼叫,直接在game.c檔案裡面, is_win 函數外面定義就行,沒有必要放在test.c裡面單獨呼叫。
test.c和game.c都需要呼叫標頭檔案stdio.h,我們將它放入game.h裡面,並且test.c和game.c都呼叫game.h就可以了
#include <stdio.h> #include <time.h> #include <stdlib.h> #define ROW 3 #define COL 3 //函數宣告 void initboard(char board[ROW][COL], int row, int col); //初始化棋盤 void displayboard(char board[ROW][COL], int row, int col); //列印棋盤 void play_move(char board[ROW][COL], int row, int col); //玩家下棋 void computer_move(char board[ROW][COL], int row, int col); //電腦下棋 char is_win(char board[ROW][COL], int row, int col); //判斷輸贏 玩家贏'*' 電腦贏'#' 平局'Q' 繼續'C'
#include "game.h" //函數實現 void initboard(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++) { board[i][j] = ' '; } } } 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"); } } void play_move(char board[ROW][COL], int row, int col) //玩家下棋 { int x = 0; int y = 0; printf("玩家下棋>:"); while (1) { scanf("%d %d",&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 computer_move(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; } } } int is_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; } } } return 1; } char is_win(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[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //判斷平局 if (1 == is_full(board, row, col)) { return 'Q'; } //繼續 return 'C'; }
#include "game.h" void menu() { printf("************************n"); printf("****** 1.play ********n"); printf("****** 0.exit ********n"); printf("************************n"); } void game() { char board[ROW][COL] = {0}; initboard(board,ROW,COL); //初始化棋盤 displayboard(board, ROW, COL); //列印棋盤 char ret = 0; while (1) { play_move(board, ROW, COL); //玩家下棋 displayboard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret!='C') { break; } computer_move(board, ROW, COL); displayboard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret!='C') { break; } } if (ret == '*') { printf("玩家贏n"); } else if (ret == '#') { printf("電腦贏n"); } else { printf("平局n"); } } void test() { int input; srand((unsigned int)time(NULL)); do { printf("請選擇>:n"); menu(); scanf("%d",&input); switch (input) { case 1: game(); break; case 0: printf("退出遊戲n"); break; default: printf("輸入錯誤,請重新輸入>:"); break; } } while (input); } int main() { test(); return 0; }
遊戲效果如下:
這樣我們簡易的三子棋就寫完啦,中間還有很多可以優化的地方,之後改進了會發布的!!!!
到此這篇關於C語言三子棋一步步實現詳程的文章就介紹到這了,更多相關C語言 三子棋內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45