摘要:三子棋三子棋游戲介紹規則游戲設計思路代碼分析文件代碼分析。玩家下棋實現。三子棋是一種民間傳統游戲,又叫九宮棋圈圈叉叉一條龍井字棋等。落子后打印棋盤以顯示。假設平局時判定輸贏的函數返回后面代碼實現時詳細講。
是黑白棋的一種。
三子棋是一種民間傳統游戲,又叫九宮棋、圈圈叉叉、一條龍、井字棋等。
將正方形對角線連起來,相對兩邊依次擺上三個雙方棋子,只要將自己的三個棋子走成一條線,對方就算輸了。但是,有很多時候會出現和棋的情況。
如果兩個人都掌握了技巧,那么一般來說就是平(和)棋。一般來說,第二步下在中間最有利(因為第一步不能夠下在中間),下在角上次之,下在邊上再次之。最大的好處就是隨便找個地方就可以玩這個簡單而有趣的游戲了。
其他輸入 - 重新選擇(循環實現)
在進入游戲后:
將游戲的實現使用到的函數封裝在game.c文件中。
函數實現功能:
如下:
可通過函數中循環控制實現。
制作棋盤分為:
落子后打印棋盤以顯示。
直到某一方勝利或者和棋。
通過行、列、對角線落子相同形式判別勝利。
因為一個程序需要對實現功能的部分進行封裝,所以我們在這里將整個程序分為3個文件:
游戲開始時,要確保4點:
int main(){ int input = 0; do { menu(); printf("請選擇:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("您已退出游戲。/n"); break; default: printf("選擇錯誤,請重新輸入。/n"); break; } } while (input); return 0;}
這里只需要打印一個簡易菜單即可,如果有前端知識可以設計出更好的界面。
void menu(){ printf("**********************************/n"); printf("************ 1.play ************/n"); printf("************ 0.exit ************/n"); printf("**********************************/n");}
實現代碼效果:
3. 玩家輸入其他:
上面展示了玩家輸入0,1,其他時的不同效果。
如輸入其他時,會通過循環一直輸入,直到輸入(0/1)時,進入游戲或者退出游戲。
在進入游戲后,需要通過對不同的函數進行封裝實現,完成我們想要的功能:
第三點需要注意:
因為不知道什么時候分出結果,所以需要在每一次下完棋之后進行判斷是否分出結果。
結果的可能有4種:
void game(){ //三子棋過程 char board[ROW][COL]; //棋盤數組 //初始化棋盤 - board的元素全都給空格 InitBoard(board, ROW, COL); //打印棋盤 DisplayBoard(board, ROW, COL); //下棋 char ret = 0; 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; } } if (ret == "*") { printf("玩家贏/n"); } else if (ret == "#") { printf("電腦贏/n"); } else { printf("平局/n"); }}
這里將不同函數實現的功能一一說明:
InitBoard(board, ROW, COL);
整個棋盤是通過一個二維數組實現的,棋盤初始化即指將二維數組中的所有元素置成空格,因為空格打印在控制臺上是不可見的。
DisplayBoard(board, ROW, COL);
因為棋盤初始化之后全部是空格,是不可見的,所以我們需要打印棋盤的函數對棋盤做一些控制,讓他變成我們希望的樣子。
實現模板:
下棋部分又分為玩家下棋和電腦下棋。
PlayerMove(board, ROW, COL); //玩家下棋ComputerMove(board, ROW, COL); //電腦下棋
二者的邏輯實現不同,所以封裝為不同的函數實現。
當然,在實現完下棋之后需要再次調用棋盤打印函數,一來一回的在界面上出現,增加代碼的趣味性。
ret = IsWin(board, ROW, COL);
這個函數需要有返回值來告訴我們游戲的結果,四種結果上面已經提到過。
1. 玩家贏。 – 假設玩家棋子為 ‘ * ’;
2. 電腦贏。 – 假設電腦棋子為 ‘ # ’;
3. 平局。 – 假設平局時判定輸贏的函數返回 ‘ C ’;
4. 游戲繼續。 – 假設函數返回 ‘ Q ’。
(即棋盤未被填滿且尚未分出勝負)
只需要控制循環即可遍歷整個二維數組中的所有元素,將他們賦值為空格即可。
void InitBoard(char board[ROW][COL], int row, int col){ int i = 0; for (i = 0; i < row; i++) { int j = 0; for (int j = 0; j < col; j++) { board[i][j] = " "; } }}
這里提一下ROW和COL分別表示棋盤的長和寬,在game.h文件里聲明了,后面介紹,這里只需要直到他們的值都是3即可,因為三子棋棋盤就是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"); }}
打印效果:
仔細看可以看的出來第一行:三個空格 + 一個 ‘ | ’ ,
第一行和第二行之間:三根短線 - - - + 一個 ‘ | ’
玩家下棋要注意:
board[x - 1][y - 1];
void PlayerMove(char board[ROW][COL], int row, int col){ int x = 0; int y = 0; while (1) { printf("玩家走:/n"); printf("請輸入坐標:>"); scanf("%d %d", &x, &y); // 2 1 --> 1 0 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"); } }}
因為存在輸入坐標落過子或者非法需要重新輸入的原因,所以這里的循環判定條件為1,直到成功落子才break跳出循環。
這里需要說明,該代碼是基于C語言實現的,電腦落子屬于人工智能及算法范疇,不予討論。
這里電腦落子通過時間軸生成偽隨機數進行坐標落子。
電腦落子不存在坐標非法的情況,因為我們可以通過對其取模進行控制。
但確實也會存在落子處被占用的情況,所以也需要利用循環重新隨機一個數,所以隨機數代碼應該放在循環體里面,這是一個小細節,需要注意。
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; } }}
如果成功找到位置,就將 ’ # "賦給該坐標位置,然后break結束。
判斷輸贏有三種情況:
char IsWin(char board[ROW][COL], int row, int col){ //1.判斷輸贏 //2.判斷平局 //3.游戲繼續 //行 int i = 0; for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != " ") { return board[i][0]; } } //列 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != " ") { return board[0][i]; } } //對角線 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != " ") { return board[0][0]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != " ") { return board[0][2]; } //判斷平局 if (IsFull(board, row, col)) { return "Q"; } //游戲繼續 return "C";}
需要注意一個小細節,判斷行、列、對角線相等時要判斷他們不等于’ ",即不為空格,因為我們初始化的時候把所有元素都初始化為空格了,不然的話直接就判斷結束了,屬于bug代碼。
注意問題:
只需要遍歷二維數組中的每一個元素,如果遇到了一個空格,則返回0,代表棋盤未滿,如果遍歷完所有元素之后都沒有發現空格,則代表棋盤已被下滿,返回1。
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; //滿了}
需要注意的問題是返回值是0或者1,所以定義函數的類型是int類型。
這個文件放的是預編譯命令和聲明函數等等指令。
預處理命令包括:
#pragma once#include #include #include #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 PlayerMove(char board[ROW][COL], int row, int col);//電腦下棋void ComputerMove(char board[ROW][COL], int row, int col);//判斷游戲輸贏//要返回4種不同的狀態//玩家贏 - "*"//電腦贏 - "#"//平局 - "Q"//繼續 - "C"char IsWin(char board[ROW][COL], int row, int col);
因為is_full函數是在game.c文件中被調用并且是在game.c文件中能夠被定義的,所以不需要在game.h文件中聲明。
???以上就是本文全部內容,整個游戲代碼源碼將會放在全文最后ps部分,如果有講的不對或者不充分的地方希望大家可以在評論區留言,如果覺得博主寫的還行可以留下各位的?點贊?+?關注?+?收藏?嗷~
#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void menu(){ printf("**********************************/n"); printf("************ 1.play ************/n"); printf("************ 0.exit ************/n"); printf("**********************************/n");}void game(){ //三子棋過程 char board[ROW][COL]; //棋盤數組 //初始化棋盤 - board的元素全都給空格 InitBoard(board, ROW, COL); //打印棋盤 DisplayBoard(board, ROW, COL); //下棋 char ret = 0; 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; } } if (ret == "*") { printf("玩家贏/n"); } else if
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/121418.html
摘要:簡單介紹了三子棋原理后接下來為大家講解分步目標及代碼如何實現。電腦下棋我們實現了玩家和電腦的下棋后,我們需要編寫一個函數來判斷雙方的輸贏。我們使用函數來實現這一目標。 目錄 1.三子棋原理 2.分塊代碼實現 3.總結 1.首先向大家介紹一下三子棋的原理 首先我們需要有一個棋盤,初始時棋...
摘要:條消息語言入門三子棋語言實現詳細版的博客博客條消息語言入門三子棋語言實現詳細版的博客博客我們將雷盤初始化為統一的符號。 目錄 1.原理簡介 2.分布目標及代碼實現 3.總結 1.原理簡介 ?首先我們需要一個空的雷盤,在其中隨機埋入十枚雷,當我們排這顆雷時,若此位置為雷,則游戲失敗,若不...
摘要:三子棋目錄一問題介紹三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋 目錄 一、問題介紹 ? ? ? ? 三子棋,在民間又叫井字棋。因為人們在游玩時常常不畫棋盤的邊框,正如漢字中的井字,多稱為井字棋。 三子棋的游戲規則十分的簡單: ...
閱讀 3140·2021-09-28 09:36
閱讀 3685·2021-09-08 09:45
閱讀 1793·2021-09-01 10:43
閱讀 3470·2019-08-30 12:44
閱讀 3343·2019-08-29 17:25
閱讀 1369·2019-08-29 11:03
閱讀 1991·2019-08-26 13:36
閱讀 692·2019-08-23 18:24