[日常練習] 3. 基於井字棋遊戲的C語言實現!
阿新 • • 發佈:2018-11-10
井字棋算是童年課堂上的與同桌默契配合的一大樂趣...躲避著老師“關切”的目光,在眼皮底下“頂風作案”,將“燈下黑”體現的淋漓盡致!在C語言中,也算是一個小的專案,今天,我們就用C語言來實現它!!!追逐童年的一份小樂趣!
遊戲介紹:
“井字棋”也稱“三子棋”,需要一個3*3的棋盤。假設分為黑、白方,各執黑棋、白棋,雙方各下一次,下棋位置必須在棋盤內並且不能佔著已有棋子,若能將橫3、豎3、斜3任意一種情況都是黑棋/白棋,那麼則黑方/白方勝利。要是當棋盤下滿還不能分出勝負,那麼就是平局。
C語言實現邏輯:
1. 首先,需要一個3*3的棋盤,棋盤使用二維陣列配合字元進行列印即可,採用迴圈結構可以方便我們的操作。
2. 遊戲簡答可分成:玩家、電腦雙方,那麼電腦下棋子與玩家下棋子的棋盤都需要進行列印。這是兩種不同的重複操作,但大致功能相同,那麼可以根據其功能寫出兩種列印函式。
3. 雙方落子是依據在二維陣列之內的,給兩者不同的字元標識即可進行區分。但是落子規則需要進一步討論,玩家所輸入座標必須在滿足二維陣列的要求,不能是負數、不能越界,否則應該重新進行座標輸入。還有一種情況就是,所輸入座標已經有棋子了,這時應該提示玩家重新進行輸入,並且電腦應該直接避免這個情況。
4. 判斷勝負是遊戲很重要的一部分。這一部分也是依據在二維陣列的基礎上的,可以遍歷二維陣列的元素,要是橫、豎、斜之一存在相同的棋子,那麼執該棋子方取得勝利。否則當棋盤填充滿的情況下,仍無勝利方,那麼就是平局了。
經過上面簡單的邏輯分析,為了驗證我們邏輯的正確性,現在給出我們的C語言實現的原始碼及結果!
測試原始碼:
#include <stdio.h> #include "game.h" #include <time.h> #include <stdlib.h> void menu() //列印遊戲選單 { printf("************************************\n"); printf("********《《 1. play 》》*********\n"); printf("********《《 0. exit 》》*********\n"); printf("************************************\n"); } void game() { char board[ROW][COL] = {0}; //以行列作為二維陣列的引數值 char ret = 0; //字元型別ret作為載體,便於二維陣列中所傳字元進行比對 InitBoard(board, ROW, COL); //定義一個ROW*COL的空棋盤 DisplayBoard(board, ROW, COL); //新增字元/特殊字元(宣揚個性),給棋盤加上邊界 while(1) //死迴圈 { PlayerMove(board, ROW, COL); //玩家走,定義函式 ret = IsWin(board, ROW, COL); //判定勝負 if(ret != ' ') //如果此二維陣列內元素未定義,即為空,在執行下面的電腦走 { break; } DisplayBoard(board, ROW, COL);//玩家走後列印棋盤 ComputerMove(board, ROW, COL);//電腦走(一定是空白可賦值,見25--28行) ret = IsWin(board, ROW, COL); //判定勝負 if(ret != ' ') { break; } DisplayBoard(board, ROW, COL);//電腦走後,列印棋盤 } if(ret == '0') // { printf("電腦贏!\n"); } else if(ret == 'X') { printf("玩家贏!\n"); } else if(ret == 'Q') { printf("平局!\n"); } } void test() { 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"); } }while(input); //迴圈結構,輸錯後繼續,不準停! } int main() { test(); return 0; }
遊戲實現原始碼:
#include "game.h"
void InitBoard(char arr[ROW][COL], int row, int col) //函式不需返回值,需要二維陣列、行數、列數作為函式引數
{
int i = 0; //注:在從game.h拷貝函式名的時候需要去除 ";" 否則會提示錯誤:在檔案範圍內找到“{”(是否缺少函式頭?)
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++) //遍歷二維陣列
{
arr[i][j] = ' '; //初始化二維陣列
}
}
}
void DisplayBoard(char arr[ROW][COL],int row, int col) //函式引數與InitBoard相同,功能為列印有邊界的棋盤,即給二維陣列賦值
{
int i = 0;
int j = 0;
for(i=0; i<row; i++) //遍歷二維陣列
{
for(j=0; j<col; j++)
{
printf(" %c ", arr[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 arr[ROW][COL],int row, int col)
{
int x = 0;
int y = 0;
printf("玩家走:\n");
while(1)
{
printf("請輸入座標:");
scanf("%d%d", &x, &y);
if((x>=1 && x<=3)&&((y>=1 && x<=3))) //保證玩家輸入座標正確性
{
if(arr[x-1][y-1] == ' ') //玩家輸入座標與二維陣列下標之間相差1
{
arr[x-1][y-1] = '*'; //如果為空,即未被佔用,則賦值為字元X
break;
}
else
{
printf("座標已被佔用\n"); //被佔用提示
}
}
else //不在if語句限值之內即非法
{
printf("座標非法\n");
}
}
}
void ComputerMove(char arr[ROW][COL],int row, int col) //電腦落子
{
int x = 0;
int y = 0;
printf("電腦走:>\n");
while(1)
{
x=rand() % 3; //得二維陣列下標0 1 2,對3取模即可
y=rand() % 3;
if(arr[x][y] == ' ')
{
arr[x][y] = 'o'; //若為空,對其賦值
break;
}
}
printf("電腦座標:%d %d\n", x+1, y+1);
}
//當程序沒有退出時 會產生錯誤 1>LINK : fatal error LNK1104: 無法開啟檔案“E:\A-bite\A\game\Debug\game.exe”
static int IsFull(char arr[ROW][COL],int row, int col) //不為介面函式,不需要放入game.h,僅在此使用,無法進行test.c中呼叫
{
int i = 0;
int j = 0;
for(i=0; i<row; i++) //遍歷二維陣列
{
for(j=0; j<col; j++)
{
if(arr[i][j] == ' ') //判斷是否仍有空值
return 0; //有空值返回0
}
}
return 1; //無空值返回1
}
char IsWin(char arr[ROW][COL],int row, int col) //判斷勝負
{
int i = 0;
for(i=0; i<row; i++) //判斷行 是否能勝利
{
if(arr[i][0]==arr[i][1] && arr[i][1]==arr[i][2] && arr[i][0]!=' ')
{
return arr[i][0]; //若三子相同,且不能為空,返回元素內值
}
}
for(i=0; i<col; i++) //判斷列 是否能勝利
{
if(arr[0][i]==arr[1][i] && arr[1][i]==arr[2][i] && arr[1][i]!=' ')
{
return arr[1][i];
}
}
if(arr[0][0]==arr[1][1] && arr[1][1]==arr[2][2] && arr[1][1] != ' ') //判斷正對角線能否勝利
{
return arr[1][1];
}
if(arr[0][2]==arr[1][1] && arr[1][1]==arr[2][0] && arr[1][1] != ' ') //判斷反對角線能否勝利
{
return arr[1][1];
}
if(IsFull(arr, row, col)) //判定平局
{
return 'Q';
}
return ' '; //繼續
}
標頭檔案及函式宣告:
#ifndef __GAME_H__
#define __GAME_H__
#include<stdio.h>
#define ROW 3
#define COL 3
void InitBoard(char arr[ROW][COL],int row, int col);
void DisplayBoard(char arr[ROW][COL],int row, int col);
void PlayerMove(char arr[ROW][COL],int row, int col);
void ComputerMove(char arr[ROW][COL],int row, int col);
char IsWin(char arr[ROW][COL],int row, int col);
#endif //__GAME_H__