1. 程式人生 > >詳解!C語言程式設計實現小遊戲“三子棋”

詳解!C語言程式設計實現小遊戲“三子棋”

今天我們來程式設計實現一個充滿童趣的小遊戲“三子棋”
先來說一下三子棋的規則:

三子棋又叫九宮棋、圈圈叉叉、一條龍等。
將正方形對角線連起來,或相對兩邊依次擺上三個雙方棋子,
總之只要將自己的三個棋子走成一條線,
對方就算輸了。

圖示
不用再過多解釋了,相信大家一定都玩過!

那麼,該如何用程式設計的方式實現它呢?
首先,我們建立專案後,要建立三個檔案
在這裡插入圖片描述
分別是標頭檔案game.h,用來宣告庫函式,儲存我們在程式設計中所自定義函式的函式名,以及巨集定義棋盤的寬高。
原始檔game.c檔案用於儲存我們所編寫的遊戲中所要用到的自定義的函式體。
test.c中包含的是整個遊戲程式的大框架和遊戲選單程式。

我們先在test.c檔案中定義選單函式,並在主函式中呼叫

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
void menu()
{
	printf("***********************************\n");
	printf("************   1.play  ************\n");
	printf("************   0.exit  ************\n");
	printf("***********************************\n");
}
int main()
{
	int input = 0;
	printf("歡迎啟動三子棋!\n");
	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;
}

除錯成功後是這樣子的:
在這裡插入圖片描述
接下來就是最重要的game()程式體了
首先要展出棋盤,
我們知道三子棋的棋盤是一個3x3的正方形格子,即九宮格。
在程式執行後可以是這樣子
在這裡插入圖片描述
我們在game.h檔案中定義寬高

#define ROW 3
#define COL 3

接下來再game.c中寫出初始化陣列的程式,在遊戲一開始時將陣列中的所有元素初始為“ ”(空格)

void InitBoard(char board[ROW][COL], int row, int col)
{
	memset(&board[0][0], ' ', row*col*sizeof(board[0][0]));
}

這裡我們使用memset函式,記得加上宣告

#include <string.h>

接著寫出展出棋盤的函式

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]);//這裡是 空格+%c+空格 //
			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");
		}
	}
}

這樣就可以實現上圖的效果,
棋盤的展出與初始化完成

接下來我們定義讓玩家先走,於是寫出玩家走棋的函式
玩家走的棋用’X’來表示

void PlayerMove(char board[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 <= row && y >= 1 && y <= col)//判斷玩家所輸入的座標是否在棋盤內//
		{
			if (board[x - 1][y - 1] == ' ')//判斷所輸入的座標是否已被佔用//
			{
				board[x - 1][y - 1] = 'X';
				break;
			}
			else
			{
				printf("抱歉,座標已經被佔用,請重新輸入!\n");
			}
		}
		else
		{
			printf("輸入的座標有誤,請重新輸入!\n");
		}
	}
}

接著寫出電腦走棋的函式
電腦走的棋用’O’來表示

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] = 'O';
			break;
		}
	}
}

這裡我們用到了rand函式,令電腦在沒佔用的位置隨機走一步棋
需要進行宣告

#include <stdlib.h>

並且需要在主函式下呼叫srand函式
同時宣告

#include <time.h>

最後,需要定義一個函式來判斷輸贏或平局
我們在構成獲勝條件時讓函式的返回值為棋子所用的字元
在函式的末尾我們還需要一個用於判斷棋盤是否被佔滿的函式IsFull(在下方說明),
佔滿時返回’Q’否則返回‘ ’
當返回值為‘ ’時未出現獲勝方,則應繼續遊戲
當返回‘Q’時意味著沒有一方獲勝,而棋盤已被佔滿,即為平局

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];
		}
	}
	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];
	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	return ' ';
}

IsFull函式用於判斷棋盤是否被佔滿,未被佔滿返回值為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;
}

(以上函式均寫在檔案game.c中)

這時我們就可以寫出game函數了
每當完成一步棋後都需要呼叫IsWin函式來進行一次判斷

void game()
{
	char board[ROW][COL] = { 0 };
	char ret = 0;
	InitBoard(board, 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);
		ret = IsWin(board, ROW, COL);
		if (ret != ' ')
			break;
		DisplayBoard(board, ROW, COL);
	}
	if (ret == 'X')
		printf("玩家贏!\n");
	else if (ret == 'O')
		printf("電腦贏!\n");
	else if (ret == 'Q')
		printf("平局\n");
	DisplayBoard(board, ROW, COL);
}

三子棋函式完成!
你是否找回了童趣呢?

完整程式碼:https://github.com/Yubao-wss/Game/tree/master/Sanzi Chess/Sanzi Chess