參考了B站UP主 位元鵬哥 的教程視頻,加入了自己的學習筆記和理解,
鏈接:https://www.bilibili.com/video/BV1oi4y1g7CF?t=464&p=17
文章目錄
- 游戲測驗
- 游戲框架
- 創建工程
- 頭檔案
- 游戲選單
- 選單執行
- 游戲執行
- 執行三子棋
- 初始化棋盤
- 列印棋盤
- 玩家輸入
- 電腦輸入
- 勝負判斷
- 平局演算法
- 完整程式
- 寫在后面
游戲測驗
??先把游戲測驗搬上來吧,看看我的成果,哇咔咔咔,我真棒,嘿嘿嘿,
****************************************
*****1.開始游戲 0.退出游戲*****
****************************************
系統提示:請選擇:>>>6
電腦:FBI warning 非法輸入,非法輸入,請您自覺點,
電腦:乖,咱重新輸入!!!
****************************************
*****1.開始游戲 0.退出游戲*****
****************************************
系統提示:請選擇:>>>1
| |
---|---|---
| |
---|---|---
| |
系統提示:請輸入您要下的坐標:>>>2 2
| |
---|---|---
| * |
---|---|---
| |
電腦:我走過啦!!!到你啦!!!
| |
---|---|---
| * |
---|---|---
| | #
系統提示:請輸入您要下的坐標:>>>3 3
電腦:這我下過了,你個憨憨,
系統提示:請輸入您要下的坐標:>>>1 1
* | |
---|---|---
| * |
---|---|---
| | #
電腦:我走過啦!!!到你啦!!!
* | |
---|---|---
| * |
---|---|---
| # | #
系統提示:請輸入您要下的坐標:>>>6 6
電腦:FBI warning 非法輸入,非法輸入!!!請您自覺點,
電腦:乖,咱重新輸入!!!
系統提示:請輸入您要下的坐標:>>>1 3
* | | *
---|---|---
| * |
---|---|---
| # | #
電腦:我走過啦!!!到你啦!!!
* | | *
---|---|---
| * | #
---|---|---
| # | #
系統提示:請輸入您要下的坐標:>>>2 1
* | | *
---|---|---
* | * | #
---|---|---
| # | #
電腦:我走過啦!!!到你啦!!!
* | | *
---|---|---
* | * | #
---|---|---
# | # | #
你輸了!!!你真笨!!!你是個憨憨吧!
****************************************
*****1.開始游戲 0.退出游戲*****
****************************************
系統提示:請選擇:>>>1
| |
---|---|---
| |
---|---|---
| |
系統提示:請輸入您要下的坐標:>>>1 1
* | |
---|---|---
| |
---|---|---
| |
電腦:我走過啦!!!到你啦!!!
* | |
---|---|---
| # |
---|---|---
| |
系統提示:請輸入您要下的坐標:>>>1 2
* | * |
---|---|---
| # |
---|---|---
| |
電腦:我走過啦!!!到你啦!!!
* | * | #
---|---|---
| # |
---|---|---
| |
系統提示:請輸入您要下的坐標:>>>3 1
* | * | #
---|---|---
| # |
---|---|---
* | |
電腦:我走過啦!!!到你啦!!!
* | * | #
---|---|---
| # |
---|---|---
* | | #
系統提示:請輸入您要下的坐標:>>>2 1
* | * | #
---|---|---
* | # |
---|---|---
* | | #
恭喜你贏啦!!!(不過我是隨機下的,我的演算法沒有任何技術含量(狗頭狗頭狗頭))
****************************************
*****1.開始游戲 0.退出游戲*****
****************************************
系統提示:請選擇:>>>1
| |
---|---|---
| |
---|---|---
| |
系統提示:請輸入您要下的坐標:>>>1 1
* | |
---|---|---
| |
---|---|---
| |
電腦:我走過啦!!!到你啦!!!
* | # |
---|---|---
| |
---|---|---
| |
系統提示:請輸入您要下的坐標:>>>2 1
* | # |
---|---|---
* | |
---|---|---
| |
電腦:我走過啦!!!到你啦!!!
* | # |
---|---|---
* | |
---|---|---
# | |
系統提示:請輸入您要下的坐標:>>>3 3
* | # |
---|---|---
* | |
---|---|---
# | | *
電腦:我走過啦!!!到你啦!!!
* | # |
---|---|---
* | # |
---|---|---
# | | *
系統提示:請輸入您要下的坐標:>>>3 2
* | # |
---|---|---
* | # |
---|---|---
# | * | *
電腦:我走過啦!!!到你啦!!!
* | # |
---|---|---
* | # | #
---|---|---
# | * | *
系統提示:請輸入您要下的坐標:>>>1 3
* | # | *
---|---|---
* | # | #
---|---|---
# | * | *
平局!!!你真笨!!!略略略!
****************************************
*****1.開始游戲 0.退出游戲*****
****************************************
系統提示:請選擇:>>>0
破游戲,俺不玩了
J:\code\三子棋\Debug\三子棋.exe (行程 24452)已退出,代碼為 0,
按任意鍵關閉此視窗. . .
游戲框架
在做游戲之前需要建立一個游戲實作基本框架,那么三子棋游戲的框架機制是怎樣的呢?
- 游戲選單
- 系統列印游戲選單
- 玩家選擇是否開始游戲
- 開始游戲進入游戲內容
- 退出游戲,游戲結束
- 游戲內容
- 初始化列印棋盤
- 玩家選擇落子坐標
- 判斷玩家輸入坐標的合法性
- 坐標是否溢位
- 原有坐標位置是否已有棋子
- 列印落子后的棋盤
- 判斷輸贏
- 判斷玩家輸入坐標的合法性
- 電腦選擇落子坐標
- 坐標值偽亂數輸入的方法
- 列印落子后的棋盤
- 判斷輸贏
- 游戲規則
- 勝利:率先使得三行||三列||對角線相同棋滿為勝
- 平局:棋盤已滿但沒有雙方棋子均沒有滿足上述條件判為平局
創建工程
??創建一個新的工程,新建工程檔案,工程檔案包括以下三個:
??頭檔案 game.h ?功能函式C檔案 function.c?游戲執行C檔案 game.c
頭檔案
??頭檔案包括了宏定義,庫函式的參考以及功能函式的宣告,
??下面是頭檔案game.h的代碼,
//宏定義
#define _CRT_SECURE_NO_WARNINGS 1//vs中scanf函式的老毛病,懂得都懂
#define ROW 3//宏定義行數為3
#define COL 3//宏定義列數為3
//參考庫函式
#include<stdio.h>//這個庫函式里包含格式化輸入輸出
#include<stdlib.h>//這個庫函式里包含偽亂數的生成
//函式宣告
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);//電腦輸入函式的宣告
char Win(char board[ROW][COL], int row, int col);//勝負判斷功能函式的宣告
char Full(char board[ROW][COL], int row, int col);//棋盤已滿,判斷平局功能函式的宣告
游戲選單
??emmm,游戲選單沒什么好說的,下一個,
//游戲選單
void menu(void)
{
printf("****************************************\n");
printf("*****1.開始游戲 0.退出游戲*****\n");
printf("****************************************\n");
}
選單執行
??完成上一步之后,就立刻執行選單了,要求用戶選擇,
??輸入1是執行game函式
??輸入0是退出游戲
??其他輸入,呃…警告處分,拉出去斬了,
void test(void)
{
int input = 0;
do
{
menu();//執行游戲選單
printf("\n");//換個行,好看點(狗頭)
printf("系統提示:請選擇:>>>");//系統提示
scanf("%d", &input);//讀取用戶輸入,存放到input里
printf("\n");
switch (input)//switch,懂得都懂,不解釋了
{
case 1:
game();//跳轉執行game函式功能
break;
case 0:
printf("破游戲,俺不玩了\n");
break;
default:
printf("電腦:FBI warning 非法輸入,非法輸入!!!請您自覺點,\n\n");
printf("電腦:乖,咱重新輸入!!!\n\n");
break;
}
} while (input);
}
游戲執行
??上一步玩家輸入1后就呼叫game函式啦,所以在他呼叫之前就要寫好game函式哦,意思是game函式放到呼叫之前,當然你如果提前宣告了,也不要緊,(就比如,emmm,我宣告了我有女朋友,但是還沒有找到,編譯器你不要給我報錯)
??下面分析整個游戲執行程序:
游戲開始執行——>初始化棋盤InitBoard(棋盤里所有的值都是0)——>列印棋盤DisplayBoard(列印簡陋的棋盤框框)——>玩家下棋PlayerMove——>列印棋盤DisplayBoard(列印玩家下玩后的棋盤)——>判斷玩家是否勝利Win(每次都要判斷,有點浪費了,后期可優化)——>電腦下棋ComputerMove(電腦自動下棋,采用的是偽亂數,后期可優化)——>列印棋盤DisplayBoard(列印電腦下棋后的棋盤)——>判斷電腦是否勝利Win(同樣每次都要判斷)——>列印勝負情況(根據上面的回傳值列印游戲勝負情況,回傳*玩家勝利,回傳#電腦勝利,回傳Q平局,回傳C程式繼續進行,)
void game(void)
{
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 = Win(board, ROW, COL);//執行win函式,把回傳值賦值到ret中
//根據回傳值判斷是否要繼續
if (ret != 'C')
{
break;
}
//電腦下棋
ComputerMove(board, ROW, COL);//執行電腦下棋函式
DisplayBoard(board, ROW, COL);//列印電腦下棋后的棋盤結果
//判斷電腦是否勝利
ret = Win(board, ROW, COL);//執行win函式,把回傳值賦值到ret中
//根據回傳值判斷是否要繼續
if (ret != 'C')
{
break;
}
}
//根據回傳值的不同,列印相應的游戲結果,
if (ret == '*')
{
printf("恭喜你贏啦!!!(不過我是隨機下的,我的演算法沒有任何技術含量(狗頭狗頭狗頭)\n");
printf("\n");
}
else if (ret == '#')
{
printf("你輸了!!!你真笨!!!你是個憨憨吧!\n");
printf("\n");
}
else
{
printf("平局!!!你真笨!!!略略略!\n");
printf("\n");
}
}
執行三子棋
int main(void)//參考主函式,程式的入口
{
test();//執行游戲
return 0;
}
??上面用到的所有函式都要在function.c中寫好,下面把寫好的函式放這里吧,演算法原理我寫在注釋里了,
初始化棋盤
#include"game.h"//參考頭檔案
//初始化棋盤
void InitBoard(char board[ROW][COL], int row, int col)//定義InitBoard初始化棋盤函式
{
for (int i = 0; i < row; i++)//for回圈,不解釋,懂得都懂
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';//陣列中每個元素都用空格代替
}
}
}
列印棋盤
//列印棋盤
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)//定義了i變數
{
//列印行,外層回圈執行一次換一行
for (int j = 0; j < col; j++)//定義了j變數
{
if (j < col - 1)//棋盤特殊要求,因為棋盤最右邊沒有|
{
printf(" %c |", board[i][j]);
}
else
printf(" %c ", board[i][j]);//列印最后一列
}
printf("\n");
//列印列,外層回圈執行一次換一行
if (i < row - 1)//控制最后一行, 列印行中不需要這個特殊結構
{
for (int k = 0; k < col; k++)//定義了k變數
{
if (k < col - 1)
{
printf("---|");//同上
}
else
{
printf("---");
}
}
}
printf("\n");
}
}
玩家輸入
//玩家輸入
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("系統提示:請輸入您要下的坐標:>>>");
scanf("%d%d", &x, &y);//獲取玩家坐標
printf("\n");
//判斷xy是否合法,一個是是否溢位,一個是是否被占用
if (x > 0 && x < row + 1 && y>0 && y < col + 1)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';//如果是空格就替換成*
break;
}
else
{
printf("電腦:這我下過了,你個憨憨\n");//占用判斷
printf("\n");
}
}
else
{
printf("電腦:FBI warning 非法輸入,非法輸入!!!請您自覺點,\n\n");//非法輸入
printf("電腦:乖,咱重新輸入!!!\n\n");
}
}
}
電腦輸入
//電腦輸入
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦:我走過啦!!!到你啦!!!\n\n");
while (1)
{
x = rand() % row;//庫函式中的偽亂數,需要參考頭檔案
y = rand() % col;//同上
if (board[x][y] == ' ')
{
board[x][y] = '#';//如果是空格就替換成#
break;
}
}
}
勝負判斷
//判斷勝負
char 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
{
return board[1][1];
}
//判斷是否平局
if (1 == Full(board, ROW, COL))//平局判斷,函式在下面,已在頭檔案中宣告,位置就無所謂了
{
return 'Q';
}
return 'C';
}
平局演算法
//平局演算法函式
char Full(char board[ROW][COL], int row, int col)//棋盤滿了還沒達到上面的條件,就算平局啦!
{
for (int i = 0; i < row; i++)
{
for (int 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>
//函式宣告
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);
char Win(char board[ROW][COL], int row, int col);
char Full(char board[ROW][COL], int row, int col);
#include"game.h"
//初始化棋盤
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//列印棋盤
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (j < col - 1)
{
printf(" %c |", board[i][j]);
}
else
printf(" %c ", board[i][j]);
}
printf("\n");
if (i < row - 1)
{
for (int k = 0; k < col; k++)
{
if (k < col - 1)
{
printf("---|");
}
else
{
printf("---");
}
}
}
printf("\n");
}
}
//玩家輸入
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("系統提示:請輸入您要下的坐標:>>>");
scanf("%d%d", &x, &y);
printf("\n");
//判斷xy是否合法,一個是是否溢位,一個是是否被占用
if (x > 0 && x < row + 1 && y>0 && y < col + 1)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("電腦:這我下過了,你個憨憨,\n");
printf("\n");
}
}
else
{
printf("電腦:FBI warning 非法輸入,非法輸入!!!請您自覺點,\n\n電腦:乖,咱重新輸入!!!\n\n");
}
}
}
//電腦輸入
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦:我走過啦!!!到你啦!!!\n\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判斷勝負
char 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
{
return board[1][1];
}
//判斷是否平局
if (1 == Full(board, ROW, COL))
{
return 'Q';
}
return 'C';
}
//平局演算法函式
char Full(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
#include"game.h"
//游戲選單
void menu(void)
{
printf("****************************************\n");
printf("*****1.開始游戲 0.退出游戲*****\n");
printf("****************************************\n");
}
void game(void)
{
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 = Win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//電腦下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判斷電腦是否勝利
ret = Win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("恭喜你贏啦!!!(不過我是隨機下的,我的演算法沒有任何技術含量(狗頭狗頭狗頭))\n");
printf("\n");
}
else if (ret == '#')
{
printf("你輸了!!!你真笨!!!你是個憨憨吧!\n");
printf("\n");
}
else
{
printf("平局!!!你真笨!!!略略略!\n");
printf("\n");
}
}
void test(void)
{
int input = 0;
do
{
menu();
printf("\n");
printf("系統提示:請選擇:>>>");
scanf("%d", &input);
printf("\n");
switch (input)
{
case 1:
game();
break;
case 0:
printf("破游戲,俺不玩了,\n");
break;
default:
printf("電腦:FBI warning 非法輸入,非法輸入,請您自覺點,\n\n電腦:乖,咱重新輸入!!!\n");
break;
}
} while (input);
}
int main(void)
{
test();
return 0;
}
寫在后面
??上面的C語言小程式實作了三子棋,但是還有好多可以優化的地方,比如外觀,電腦演算法,還有可不可以實作四子棋、五子棋、多子棋呢,所以這個程式可優化的地方還有很多,
?(偽亂數不隨機哇,有沒有什么好的演算法呢emmmm,我現在還不知道,明天找看,還有實作多子棋功能,emmmm加油哇↖(ω)↗)
??下一篇,C語言實作多子棋以及演算法的優化,
??以上程式或者表述如果有錯誤,還請各位大佬批評指正哈,非常感謝,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/256443.html
標籤:其他
