
前言:今天我們來用C語言寫一個三子棋小游戲,三子棋,是黑白棋的一種,三子棋是一種民間傳統游戲,又叫九宮棋、圈圈叉叉、一條龍、井字棋等,這里我們寫的是玩家與電腦對戰的一個代碼,如果想跟朋友一起玩也可以自己稍作修改噢,
讓我們往下看吧
目錄:
C語言簡單三字棋小游戲:
- 一、想法與構思
- 1.想法
- 2.構思
- 二、代碼與實作
- 1.代碼分塊
- 2.test.c
- 3.game.h
- 4.game.c
- 1.InitBoard(初始化九宮格棋盤)
- 2.DisplayBoard(橫豎劃分)
- 3. PlayerMove(玩家進行游戲)
- 4.ComputerMove(電腦進行操作)
- 5. IsWin(判斷勝負)
- 三、完整代碼
- 1.test.c
- 2.game.h
- 3.game.c
一、想法與構思
1.想法
首先想要做一個游戲就先明白游戲的規則和玩法,三子棋,就是在一個九宮格里面下子,兩個人對戰,每一個人每一輪下一子,當任意一方有橫豎斜其中一種三子連線,即該方獲勝,若九宮格填滿,仍無連線,則為平局,
沒錯,這就是我們想寫出來的游戲,那么接下來就是構思了↓
2.構思
有了想法構思就很容易啦,
首先我們要確定我們代碼中要實作的:
- 在初始狀態下出現一個九宮格,
- 玩家和電腦輪流進行輸入,
- 每一輪可在里面輸入一個字符標記,
- 判斷游戲繼續、平局或誰勝誰負,
完成構思接下來就進入我們的代碼領域了,
二、代碼與實作
1.代碼分塊
為了讓整個代碼更加可觀,我們首先把代碼分為三個板塊:
1.test.c源檔案
測驗游戲和一些細節的補充,
2.game.h頭檔案
存放游戲函式的宣告,
3.game.c源檔案
整個游戲的實作,
2.test.c
首先我們來將代碼的整體框架給寫出來:
//先寫一個選單函式,讓我們選擇是否進入游戲
void menu()
{
printf("***********************************\n");
printf("*********** 1. play *********\n");
printf("*********** 0. exit *********\n");
printf("***********************************\n");
}
void game()//游戲主體的代碼
{
}
int main()//主函式
{
int input = 0;
do
{
menu();//參考上面的選單函式
printf("請選擇>");
scanf("%d", &input);//選擇是否進入游戲
switch (input)
{
case 1://輸入1進入游戲
game();
break;
case 0://輸入0退出游戲
printf("退出游戲\n");
break;
default://輸入其他會提示輸入有誤
printf("輸入有誤\n");
break;
}
} while (input);
return 0;
}
然后我們要補充好game()的部分:
按照構思,我們先要把初始化的棋盤給寫出來,那初始化棋盤如何寫呢,一個九宮格的棋盤可以看作為九個空格和一個井字合起來,而且空格中需要輸入東西,所以我們可以用一個二維陣列了表示,如何橫豎的井字,我們可以用符號" — " 和符號 " | "在二維陣列的縫隙中接入,
那么直接寫?不不不,還記得我們區分板塊嗎,在這里我們只需要命名幾個函式,然后在game.c上寫就可以啦
void game()//三子棋游戲的程序
{
char board[ROW][COL];//創建一個二維陣列作為棋盤
//ROW為行,COL為列
InitBoard(board, ROW, COL);//初始化棋盤 - board的元素都給成空格
//將二維陣列和行列傳進函式
DisplayBoard(board, ROW, COL);//列印橫豎的棋盤
//將二維陣列和行列傳進函式
}
然后接下來就是下棋的部分了,
再看回我們的構思,玩家和電腦輪流下棋,所以我們得寫兩個函式分別描述玩家下棋和電腦下棋,
void game()//三子棋游戲的程序
{
char board[ROW][COL];
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
PlayerMove(board, ROW, COL);//玩家下棋
DisplayBoard(board, ROW, COL);//列印玩家下棋后的棋盤
ComputerMove(board, ROW, COL);//電腦下棋
DisplayBoard(board, ROW, COL);//列印電腦下棋后的棋盤
}
然后我們需要是第三個構思,每一輪! 我們不可能一輪就分出勝負,所以我們要在玩家和電腦下棋之間放一個回圈,同時我們再看第四個構思,當回圈出來那么就是勝負已分了,
所以我們要在game()中添加一個回圈和一個勝負條件還有平局條件:
這里我們可以設定一個判斷勝負函式 IsWin,然后 給 IsWin函式設定回傳值,結果為
- 如果勝負未分,游戲繼續,則回傳值為C(continue)
- 如果玩家贏了,回傳玩家的符號,反之回傳電腦的符號,
- 什么都不回傳就平局,
void game()//三子棋游戲的程序
{
char board[ROW][COL];
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)//設定回圈,當判斷平局或勝負就跳出
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//設定一個判斷勝負函式 IsWin
//在這里設定一個變數ret,接收IsWin回傳的結果
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;//如果不等于C(continue),就是平局或勝負已分
//直接跳出回圈
}
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");
}
}
以上就是我們test.c的代碼,
3.game.h
寫好主函式之后,那么頭檔案game.h中的函式宣告就很容易寫好了,
部分說明直接在代碼中注釋就可以了,
#pragma once //作用:讓引頭檔案只引一次,防止頭檔案被多次包含,
//在這里我們幾個模塊需要的頭檔案的放這里就可以了
//到時候再在另外兩個中直接參考 "game.h"就可以使用game.h中參考的頭檔案了,
#include <stdio.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 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);
4.game.c
重頭戲來了,整個代碼的靈魂,也是最難寫的部分來了,
前面寫了那么多也僅僅是把構思的框架實作了而已,這里才是真正把游戲寫出來的地方,
那我們一個一個來吧:
1.InitBoard(初始化九宮格棋盤)
噢,放錯了,應該是這個:
這里的話,初始化的時候,九宮格中都是空的,但是后續我們還要往里面填進玩家和電腦輸入的符號,所以我們暫且要用空格表示,
代碼:
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] = ' ';
}
}
}
2.DisplayBoard(橫豎劃分)
在這里,我們可以先想像棋盤是什么樣子的:
那我們列印的時候呢(要用 — 和 | ):
我們可以看到先 — 再 | ,而且是三次列印 — 兩次列印 |
所以整體是分為:
- 列印玩家或電腦輸入字符+豎杠分割線
- 橫杠分割線+豎杠分割線
代碼:
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. PlayerMove(玩家進行游戲)
首先我們要提示到玩家進行游戲,然后為了統一和簡化玩家操作,我們直接把玩家想畫的地方改為坐標指示,比如1 1就是畫第一行第一列,
然后我們也要判斷玩家輸入的坐標是否有效,要考慮坐標存不存在,坐標里面是否已經被畫,
代碼:
void PlayerMove(char board[ROW][COL], int row, int col)
{
printf("輪到玩家進行操作:>\n");
int x = 0;
int y = 0;
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");
}
}
}
4.ComputerMove(電腦進行操作)
電腦操作就比玩家簡單多了,直接設定一個符合坐標的隨機值,再判斷這個坐標為空格就可以了,
代碼:
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("輪到電腦進行操作:>\n");
while (1)//死回圈,填進才跳出
{
x = rand() % row;
y = rand() % col;
//這里用到了隨機函式,要記得在補充頭檔案,還有初始化時間戳,
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
5. IsWin(判斷勝負)
判斷勝負的條件也很簡單,我們可以分別寫出來:
- 橫上有三個相同的符號
- 豎上有三個相同的符號
- 對角線有三個相同的符號
代碼:
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[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
}
然后還有平局和繼續游戲這兩個情況還沒有,我們可以寫一個IsFull函式來決定是否結束游戲,:
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[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判斷平局
//如果棋盤滿了回傳1, 不滿回傳0
int ret = IsFull(board, row, col);//呼叫IsFull函式
if (ret == 1)
{
return 'Q';//這就是上面test.c里面一個else的情況,就是平局
}
//繼續游戲
return 'C';//continue
}
到此就把game.c中需要的函式都實作了,
三、完整代碼
完整代碼如下:
1.test.c
#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];
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");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//電腦隨機
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;
}
2.game.h
#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 PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
int IsFull(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
3.game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//將game.h引過來,實際上也把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;
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");
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
printf("輪到玩家進行操作:>\n");
int x = 0;
int y = 0;
while (1)
{
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");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("輪到電腦進行操作:>\n");
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 (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[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
int ret = IsFull(board, row, col);
if (ret == 1)
{
return 'Q';
}
return 'C';
}
這就是三子棋小游戲的C語言寫法啦,小白制作不易,有錯的地方還請xdm指正,互相關注,共同進步,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290967.html
標籤:其他
上一篇:簡單幾步教你學廢三子棋!!!
