1. 程式人生 > >【C語言】專案-三子棋

【C語言】專案-三子棋

C語言專案

三子棋

實現思想

  大家都玩過五子棋,也對五子棋的遊戲規則不陌生,今天我們就仿照五子棋做一個三子棋,以函式模組為進行封裝逐步實現,並且實現一個萬能演算法,可以達到n*n的棋盤上玩n子棋(前提是螢幕夠大)。
  實現具體思想很簡單,先做出選單,然後根據玩家選擇執行不同的內容函式,如果選擇遊戲則開始三子棋的遊戲主體函式,執行完成之後重新執行選單,知道玩家選擇退出遊戲!
  三子棋的主體遊戲思想也很簡單,用一個數組表示棋盤,每一個回合開始前先列印棋盤,隨後讓玩家進行座標選擇要落子的地方,此時注意 要判斷玩家輸入是否合法,玩家輸入後將棋盤上的資料進行更改,並判斷是否已經分出勝負,未結束的話是由電腦隨機選擇座標進行落子(在這裡我們暫時先進行簡單的設計,讓電腦隨機落子

),電腦落子完成後也要判斷是否遊戲已經結束,未結束的話重新列印棋盤即可完成一個迴圈。在遊戲中我們應該考慮到遊戲有三中勝負情況,分別是:玩家勝、電腦勝和平局。

實現程式碼

/*!
 * \檔名 源.cpp
 * \日期 2018/11/10 13:35
 *
 * \作者 Misaki
 * 聯絡方式  [email protected]
 *
 * 檔案描述: 三子棋
 *
*/
#define _CRT_SECURE_NO_WARNINGS
#define ROW 5//棋盤行
#define COL 5//棋盤列
#define WIN 5//獲勝條件
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
char g_board[ROW][COL];
/*
將棋盤進行初始化
*/
void initBoard()
{
	for (int row = 0; row < ROW; row++)
	{
		for (int col = 0; col < COL; col++)
		{
			g_board[row][col] = ' ';//空位置用' '表示
		}
	}
}
/*
列印選單
*/
int menu()
{
	system("cls");
	int choose = 0;
	printf("1、開始遊戲\n");
	printf("2、遊戲說明\n");
	printf("3、退出\n");
	printf("請選擇:");
	scanf("%d", &choose);
	return choose;
}
/*
列印棋盤
*/
void printBoard()
{
	system("cls");
	for (int col = 0; col < COL; col++)
	{
		printf(" _____");
	}
	printf(" \n");
	for (int row = 0; row < ROW; row++)
	{
		printf("|");
		for (int col = 0; col < COL; col++)
		{
			printf("%6c", '|');
		}
		printf("\n|");
		for (int col = 0; col < COL; col++)
		{
			printf("  %c  |", g_board[row][col]);
		}
		printf("\n|");
		for (int col = 0; col < COL; col++)
		{
			printf("_____|");
		}
		printf("\n");
	}
	printf("\n");
}
/*
玩家回合
*/
void playerMove(int* row, int* col)
{
	printf("玩家回合:\n");
	int rowt = 0, colt = 0, result;
	while (1)
	{
		printf("請輸入座標:(格式:y x)");
		if (result = scanf("%d%d", &rowt, &colt) != 2)
		{
			printf("你輸的是座標麼?重來\n");
			rewind(stdin);
			continue;
		}
		if (rowt < 0 || rowt >= ROW || colt < 0 || colt >= COL)
		{
			printf("輸入座標不合法,請重新輸入!\n");
			rewind(stdin);
			continue;
		}
		if (g_board[rowt][colt] != ' ')
		{
			printf("這個位置已經有子了!\n");
			rewind(stdin);
			continue;
		}
		g_board[rowt][colt] = 'x';
		//將值返回出去
		*row = rowt;
		*col = colt;
		break;
	}
}
void computerMove(int* row, int* col)
{
	int rowt = 0;
	int colt = 0;
	while (1)
	{
		rowt = rand() % (ROW);
		colt = rand() % (COL);
		if (g_board[rowt][colt] == ' ')
		{
			break;
		}
	}
	g_board[rowt][colt] = 'o';
	//將值返回出去
	*row = rowt;
	*col = colt;
}
/*
判斷是否平局
*/
int isdraw()
{
	int num = 0;
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (g_board[i][j] == ' ')
			{
				num++;
			}
		}
	}
	if (num == 0)//平局了,棋盤滿了
	{
		return 1;
	}
	else//還能打
	{
		return 0;
	}
}
/*
判斷是否三子相連
引數:當前下子位置
返回值:誰獲得勝利
*/
char judge(int row, int col)
{
	int num =1;//計數相連棋子個數
	int i = 1;//判斷周圍第i個棋子是否相同
	//從左到右的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((col + i) > (COL - 1) || g_board[row][col] != g_board[row][col + i])
		{
			break;
		}
		num++;
	}
	//從右到左的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((col - i) < 0 || g_board[row][col] != g_board[row][col - i])
		{
			break;
		}
		num++;
	}
	if (num >= WIN)
	{
		return g_board[row][col];
	}
	num = 1;
	//從上到下的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((row + i) > (ROW - 1) || g_board[row][col] != g_board[row + i][col])
		{
			break;
		}
		num++;
	}
	//從下到上的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((row - i) < 0 || g_board[row][col] != g_board[row - i][col])
		{
			break;
		}
		num++;
	}
	if (num >= WIN)
	{
		return g_board[row][col];
	}
	num = 1;
	//從左上到右下的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((row + i) > (ROW - 1) || (col + i) > (COL - 1) || g_board[row][col] != g_board[row + i][col + i])
		{
			break;
		}
		num++;
	}
	//從右下到左上的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((row - i) < 0 || (col - i) < 0 || g_board[row][col] != g_board[row - i][col - i])
		{
			break;
		}
		num++;
	}
	if (num >= WIN)
	{
		return g_board[row][col];
	}
	num = 1;
	//從右上到左下的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((row + i) > (ROW - 1) || (col - i) < 0 || g_board[row][col] != g_board[row + i][col - i])
		{
			break;
		}
		num++;
	}
	//從左下到右上的判斷
	for (i = 1; i < WIN; i++)
	{
		if ((row - i) < 0 || (col + i) > (COL - 1) || g_board[row][col] != g_board[row - i][col + i])
		{
			break;
		}
		num++;
	}
	if (num >= WIN)
	{
		return g_board[row][col];
	}
	if (isdraw())//平局了
	{
		return 'd';
	}
	else
	{
		return ' ';
	}
}
/*
遊戲是否結束
*/
int isOver(int row, int col)
{
	char c = judge(row, col);
	if (c == ' ')
	{
		return 0;
	}
	if (c == 'x')
	{
		printf("恭喜你贏了!\n");
		system("pause");
		return 1;
	}
	if (c == 'o')
	{
		printf("不走運,你輸了!\n");
		system("pause");
		return 1;
	}
	else
	{
		printf("平局!\n");
		system("pause");
		return 1;
	}
}
/*
遊戲主體
*/
void mainGame()
{
	int row = 0;
	int col = 0;
	//初始化棋盤
	initBoard();
	//列印棋盤
	printBoard();
	//迴圈控制遊戲程序
	while (1)
	{
		//玩家開始下
		playerMove(&row, &col);
		//列印棋盤
		printBoard();
		//判定是否遊戲結束
		if (isOver(row, col))
		{
			break;
		}
		//電腦下
		computerMove(&row, &col);
		//列印棋盤
		printBoard();
		printf("計算機回合↑\n");
		//判定是否遊戲結束
		if (isOver(row, col))
		{
			break;
		}
	}
}
void gameExplain()
{
	system("cls");
	printf("五子棋你會玩,三子棋你不會玩?\n");
	printf("什麼你五子棋都不會玩,你不會百度,搜狗,goole啊!\n");
	system("pause");
}
int main()
{
	srand(time(NULL));
	while (1)
	{
		int choose = menu();
		if (choose == 1)
		{
			mainGame();
			continue;
		}
		if (choose == 2)
		{
			gameExplain();
			continue;
		}
		if (choose == 3)
		{
			break;
		}
		else
		{
			printf("別瞎比選!\n");
			rewind(stdin);
			system("pause");
			continue;
		}
	}
	printBoard();
	return 0;
}

  在這裡值得一提的是我用來判斷是否獲勝的演算法,演算法可總結為以落子為中心,向橫縱正斜和反斜四個方向分別計數,以達到統計是否已經連子獲勝的目的。
  歡迎來我的部落格閒逛:https://misakifx.github.io/