前言
三子棋,我相信這是一個相對普及的游戲,每個同學在無聊時候都會隨便拿個廢卷子和同桌比劃比劃,所以針對這個小游戲,綜合利用C語言中的回圈陳述句,條件陳述句,陣列,函式呼叫,等知識對它進行一個初級的撰寫,(同上一期的掃雷游戲,兩游戲的知識點基本一致)并且在每條代碼后面都配備了注釋,并且會在文章中對每一句代碼進行決議,盡量讓每一位初學者都能看懂,都能自己動手寫出來,有疑問或錯誤的地方歡迎下方留言,(由于有一部分代碼需要單獨拿出來決議所以代碼拆分有些亂,最后給大家匯總了三個檔案的代碼)

文章目錄
- 前言
- 一、創建檔案
- 二、撰寫
- 三、成果展示
- 總結
準備作業(初級三子棋)
(所需的知識點)
針對C語言中的回圈陳述句,條件陳述句,陣列,函式呼叫等知識點的綜合應用,寫出一個三子棋游戲
1.利用while for do while陳述句
2.利用switch if 陳述句
3.利用二維陣列
4.亂數的利用
5.函式的呼叫
6.函式的宣告,宏的定義及使用
提示:該游戲依舊采用多檔案的方式進行書寫,各檔案分工明確,代碼簡約
一、創建檔案(與掃雷一致)

第一步創建兩個.c 檔案,text 檔案用于測驗,game 檔案用于創建游戲所需函式

第二步創建一個.h頭檔案,將前兩個檔案中所需要的頭檔案,宏以及函式宣告放到此檔案中,以此來使.c檔案更加整潔
二、撰寫
所需頭檔案,宏,函式宣告(game.h)
整體代碼如下(示例):
#include <stdio.h>
#include <stdlib.h>
#include <time.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 Playmove(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);
1.在測驗檔案(text.c)中引入主函式
整體代碼如下(示例):
void main()//入口主函式(程式起點)
{
srand((unsigned int)time(NULL));
int input = 0;//定義由用戶輸入的變數
do
{
menu();//呼叫選單函式,程式運行后,讓玩家看到選單
printf("請玩家依據選單選擇\n");//提示語(提示玩家輸入變數)
scanf("%d", &input);//scanf函式捕獲用戶輸入的input變數數值
switch (input)//switch 根據用戶輸入的數值 0/1去執行不同的陳述句
{
case 1://當用戶輸入的是1
game();//呼叫game函式去實作游戲
break;
case 0://當用戶輸入的是0
printf("Exit\n");//列印Exit退出游戲
break;
default://用戶數入的不是 0/1重新回到回圈,做下一次的重新輸入
printf("輸入的資料無法識別\n");//提示用戶輸入的資料有誤
break;
}
} while (input);//根據用戶輸入的input數值 0-->終止回圈退出程式 非0繼續回圈---->玩游戲/重新輸入變數值
}
a. 
srand為生成亂數的函式
在這里我們簡單介紹一下srand函式生成亂數的用法
1.首先srand函式的所需的頭檔案為

2.srand的函式用法

srand函式在傳引數時,引數需要的是無符號整型即(unsigned int)
所以如我們的代碼所示我們需要把引數強制轉換為無符號整型即(unsigned int)
3.以時間(time函式)為傳入srand的引數,保證生成的數字足夠隨機
4.呼叫time函式時所需要的頭檔案

5.time函式所需要的引數

可見time函式需要一個指標型別變數,所以我們在time函式內傳進空指標(NULL)即可
b.
呼叫自定義的選單函式(這個是自己設計的,成什么樣式都是可以的)
void menu()//初始化選單 進入界面給玩家看
{
printf("*********************************\n");//自定義選單樣式(隨意)
printf("* 歡迎您來到三子棋游戲 *\n");
printf("* 1.開始游戲 *\n");
printf("* 0.退出游戲 *\n");
printf("*********************************\n");
}
c.為什么使用do while 回圈
do while可以無視條件回圈一次,所以無論用戶輸入什么數值都可以進行一次回圈,再根據用戶輸入的數值去判斷是否去進行第二次的回圈,或者是退出程式,或者輸入的數值不對進行重新的數值輸入
d.switch陳述句的作用
以用戶輸入的數值判別去執行哪一條陳述句
選1開始下棋

選0退出程式

選擇非0/1重新選擇
2.在主函式呼叫游戲函式(game函式)
整體代碼如下(示例):
void game()
{
char board[ROW][COL];//定義一個3*3的棋盤,我們在這里引入宏這樣是為了以后修改棋盤大小,直接在.h修改一個數值即可,不需要在.c檔案中多次修改
InitBoard(board, ROW, COL);//呼叫game.c檔案中的InitBoard函式對棋盤進行初始化,把定義棋盤的二維陣列都設定成空格
DisPlayBoard(board, ROW, COL);//呼叫game.c檔案中的DisPlayBoard函式,把剛剛設計好的棋盤列印出給玩家看
char ret = 0;//初始化完畢 可以開始下棋分為玩家下和電腦下
while (1)//利用回圈去回圈判斷游戲進行進度
{
Playmove(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");
}
}
a.
設定一個3*3的棋盤(3行3列的陣列),我們在這里參考了宏的定義,這樣方便我們后期對程式的改動(四子棋,五子棋的撰寫)直接改宏的數值就可以了
三子棋棋盤
b.
呼叫函式去初始化棋盤,把二維陣列的各元素都置空(賦值成空格)
void InitBoard(char board[ROW][COL], int row, int col)//最基本的二維陣列賦值的方法
{
int i = 0;
int j = 0;
for (j = 0; j < row; j++)
{
for (i = 0; i < col; i++)
{
board[i][j] = ' ';
}
}
}
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)
{
printf("|");
}
}
printf("\n");
//列印分割行
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
1.先看前半段代碼
利用回圈去列印一個二維陣列,列印一個空格列印一個豎線 ' | ' 我們看到的棋盤最后一列是沒有豎線的,所以豎線列印到最后一列的前一列(利用if條件判斷),每列印一行換一次行


2.后半段代碼

列印出來的棋盤樣式
d.棋盤都設定好了,可以開始下棋

我們規定C為繼續下棋,Q為平局
void Playmove(char board[ROW][COL], int row, int col)
{
printf("現在進行請玩家下棋\n");
int x = 0;//定義兩個變數 由用戶輸入 作為棋盤的坐標
int y = 0;
while (1)
{
printf("請您在棋盤中輸入坐標----->");
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 Computermove(char board[ROW][COL], int row, int col)//電腦下棋得我
{
printf("現在進行請計算機下棋\n");
int x = 0;//由電腦生成的隨機坐標
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')//電腦生成隨機坐標對應元素是空格電腦就可以在對應坐標位置下棋
{
board[x][y] = '#';//電腦下棋的標識利用#表示
break;//結束回圈 進行下一輪玩家下棋
}
}
}
1.
這里為什么要由用戶輸入的坐標減去1,因為作為玩家并不知道陣列的下標是從0開始的,所以當玩家輸入1 1坐標時其實應該對應我們二維陣列的 [0][0]下標所對應元素
2.
這里我們用rand去呼叫我們剛剛定義的亂數,但是亂數相當的大,并不滿足我們棋盤的坐標需求,所以我們利用我們生成的亂數去取余行或者列,這樣剩下的余數,一定是小于我們行列坐標的數值,這樣我們的電腦生成的隨機坐標就可以在記錄在棋盤內了
e.雙方都下好棋,我們可以對雙方的輸贏進行判斷
int IsFull(char board[ROW][COL], int row, int col)//判斷是否平局的函式
{
int i = 0;
int j = 0;
for (j = 0; j < row; j++)//訪問二維陣列的各個元素
{
for (i = 0; i < col; i++)
{
if (board[j][i] == ' ')//看看棋盤是否滿了
{
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][0] != ' ')//判斷一行三個是否相等而且一行不能有空格
{
return board[i][0]; //回傳* 玩家贏 回傳#電腦贏 主要看board[0][i]對應的元素
}
}
//判斷一列連出來三個的情況
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];//回傳*玩家贏 回傳#電腦贏 主要看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 (IsFull(board, row, col))
{
return 'Q';
}
return 'C';//都不是繼續游戲
}

f.整體三個檔案的代碼
text.c
#pragma warning(disable : 4996)//VS 2019需要關閉scanf等函式的C4996警告
#include "game.h"//呼叫.h檔案中text.c所需要的頭檔案,宏,函式宣告
void menu()//初始化選單 進入界面給玩家看
{
printf("*********************************\n");//自定義選單樣式(隨意)
printf("* 歡迎您來到三子棋游戲 *\n");
printf("* 1.開始游戲 *\n");
printf("* 0.退出游戲 *\n");
printf("*********************************\n");
}
void game()
{
char board[ROW][COL];//定義一個3*3的棋盤,我們在這里引入宏這樣是為了以后修改棋盤大小,直接在.h修改一個數值即可,不需要在.c檔案中多次修改
InitBoard(board, ROW, COL);//呼叫game.c檔案中的InitBoard函式對棋盤進行初始化,把定義棋盤的二維陣列都設定成空格
DisPlayBoard(board, ROW, COL);//呼叫game.c檔案中的DisPlayBoard函式,把剛剛設計好的棋盤列印出給玩家看
char ret = 0;//初始化完畢 可以開始下棋分為玩家下和電腦下
while (1)//利用回圈去回圈判斷游戲進行進度
{
Playmove(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");
}
}
void main()//入口主函式(程式起點)
{
srand((unsigned int)time(NULL));
int input = 0;//定義由用戶輸入的變數
do
{
menu();//呼叫選單函式,程式運行后,讓玩家看到選單輸入變數的數值
printf("請玩家依據選單選擇\n");//提示語(提示玩家輸入變數)
scanf("%d", &input);//scanf函式捕獲用戶輸入的input變數數值
switch (input)//switch 根據用戶輸入的數值 0/1去執行不同的陳述句
{
case 1://當用戶輸入的是1
game();//呼叫game函式去實作游戲
break;
case 0://當用戶輸入的是0
printf("Exit\n");//列印Exit退出游戲
break;
default://用戶數入的不是 0/1重新回到回圈,做下一次的重新輸入
printf("輸入的資料無法識別\n");//提示用戶輸入的資料有誤
break;
}
} while (input);//根據用戶輸入的input數值 0-->終止回圈退出程式 非0繼續回圈---->玩游戲/重新輸入變數值
}
game.c
#pragma warning(disable : 4996)
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (j = 0; j < row; j++)
{
for (i = 0; i < col; i++)
{
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 Playmove(char board[ROW][COL], int row, int col)
{
printf("現在進行請玩家下棋\n");
int x = 0;//定義兩個變數 由用戶輸入 作為棋盤的坐標
int y = 0;
while (1)
{
printf("請您在棋盤中輸入坐標----->");
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 Computermove(char board[ROW][COL], int row, int col)
{
printf("現在進行請計算機下棋\n");
int x = 0;//由電腦生成的隨機坐標
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')//電腦生成隨機坐標滿足棋盤要求 結束回圈 進行下一輪玩家下棋
{
board[x][y] = '#';
break;
}
}
}
int IsFull(char board[ROW][COL], int row, int col)//判斷是否平局的函式
{
int i = 0;
int j = 0;
for (j = 0; j < row; j++)
{
for (i = 0; i < col; i++)
{
if (board[j][i] == ' ')
{
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][0] != ' ')//判斷一行三個是否相等而且一行不能有空格
{
return board[i][0]; //回傳* 玩家贏 回傳#電腦贏 主要看board[0][i]對應的元素
}
}
//判斷一列連出來三個的情況
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];//回傳*玩家贏 回傳#電腦贏 主要看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 (IsFull(board, row, col))
{
return 'Q';
}
return 'C';//都不是繼續游戲
}
game.h
#pragma once
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.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 Playmove(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);
g.成果展示
1.玩家贏(一行案列)

2.電腦贏(副對角線案列)
3.玩家贏(一列案例)

4.玩家贏(主對角案例)

5.平局案例
總結
三子棋同掃雷游戲,知識點幾乎一致,希望大家對所學的知識進行一個匯總,學會的同時,盡可能自己寫一下,有錯誤或者說得不清楚的地方歡迎下方留言
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292131.html
標籤:其他
上一篇:STC學習:串口通信

