天天看點

三子棋——年輕人的第一款小遊戲前言正文總結 

目錄

前言

正文

主函數部分(test.c)

頭檔案部分(game.h)

功能實作函數部分(game.c)

 1.初始化函數

2.列印棋盤函數

3.玩家移動函數

4.電腦移動函數

5.判斷輸赢函數

6.重回game函數

效果展示

總結 

前言

  經過一段時間的學習,分支與循環、數組與函數的相關知識已經足夠支撐我們完成一個小遊戲了,這個小遊戲不需要太多的功能,也不需要太複雜的邏輯,隻需要懂點循環與分支,懂點數組的使用以及函數如何傳參和返值即可。作為草稿紙上常出現的小遊戲,三子棋的邏輯可謂是非常簡單了,隻需要玩家走一步、電腦走一步,并在八種可能獲勝結果中比對就行了,下面讓我們一起來看看三子棋的實作。

  注意:本文為模拟遊戲實作,代碼量兩百左右,共有兩個源檔案+一個頭檔案。

正文

本程式一共就下面三個檔案
三子棋——年輕人的第一款小遊戲前言正文總結 
三子棋——年輕人的第一款小遊戲前言正文總結 

主函數部分(test.c)

 我們直接從主函數開始!
三子棋——年輕人的第一款小遊戲前言正文總結 
 下面看看game(遊戲)函數的設計
三子棋——年輕人的第一款小遊戲前言正文總結 
//三子棋
#include"game.h"
void menu()
{
	printf("**************************\n");
	printf("********  1.Play  ********\n");
	printf("********  0.Exit  ********\n");
	printf("**************************\n");

}
void game()
{
	char board[ROW][COL] = { 0 };//定義
	init_board(board, ROW, COL);//初始化
	display_board(board, ROW, COL);//列印
	//下棋
	char tmp = 0;
	while (1)
	{
		player_move(board, ROW, COL);//玩家走
		display_board(board, ROW, COL);//列印
		tmp=who_win(board, ROW, COL);//判斷
		if (tmp != 'C')
			break;

		computer_move(board, ROW, COL);//電腦走
		display_board(board, ROW, COL);//列印
		tmp=who_win(board, ROW, COL);//判斷
		if (tmp != 'C')
			break;
	}
	if (tmp == '*')
		printf("玩家獲勝\n");
	else if (tmp == '#')
		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;
}
           
 主函數檔案(test.c就介紹完了),下面介紹game.h這個頭檔案

頭檔案部分(game.h)

這個頭檔案是自己建立的,目的就是在主函數源檔案(test.c)和功能實作函數(game.c)中搭起一座溝通的橋梁。
三子棋——年輕人的第一款小遊戲前言正文總結 
#pragma once
#include<stdio.h>
#include<stdlib.h>

#define ROW 3
#define COL 3

void init_board(char board[][COL],int row,int col);//初始化

void display_board(char board[][COL], int row, int col);//列印

void player_move(char board[][COL], int row, int col);//玩家走

void computer_move(char board[][COL], int row, int col);//電腦走

char who_win(char board[][COL], int row, int col);//判斷
           
自定義頭檔案部分代碼量最少,功能也比較簡單,如果說test.c是大腦、控制中心,那麼game.h就相當于神經系統的一部分,是函數間溝通的橋梁,能對函數起主導作用。

功能實作函數部分(game.c)

此部分是程式運作必不可少的部分,沒有它們,程式能跑,但什麼都幹不了,類似于植人。

本部分函數細節較多,是以我會分開逐個講解。 

 1.初始化函數

三子棋——年輕人的第一款小遊戲前言正文總結 
 初始函數主要就是把整個數組周遊一遍,然後将字元 空格 (' ')賦給每個數組即可。
三子棋——年輕人的第一款小遊戲前言正文總結 
void init_board(char board[][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.列印棋盤函數

列印棋盤函數需要思考下:什麼情況列印 | 和 什麼情況列印 --- ,不想清楚這些問題就無法列印出優美的棋盤。
三子棋——年輕人的第一款小遊戲前言正文總結 
void display_board(char board[][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.玩家移動函數

玩家移動就是讓玩家輸入坐标,輸入坐标有三種情況:非法、占用、成功,依次判斷即可,其次要注意不是人人都知道坐标從0開始,是以在使用x、y時要減1,確定坐标不會越界。
三子棋——年輕人的第一款小遊戲前言正文總結 
void player_move(char board[][COL], int row, int col)//玩家走
{
	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");
	}
}
           

4.電腦移動函數

電腦移動不要太多判斷,隻需要給電腦一個随機值,一個判斷條件。

直到電腦落子成功再跳出即可

三子棋——年輕人的第一款小遊戲前言正文總結 
void computer_move(char board[][COL], int row, int col)//電腦走
{
	printf("輪到電腦落子:>");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	printf("電腦已落子\n");
}
           

5.判斷輸赢函數

這個函數出現于玩家或電腦移動之後,目的就是判斷是否已達成勝利條件(共八種),如果達成了,就能跳出game函數中的死循環,結束遊戲。
三子棋——年輕人的第一款小遊戲前言正文總結 
三子棋——年輕人的第一款小遊戲前言正文總結 
 注意:本程式中函數就判斷輸赢函數和判斷和局函數有傳回值,一個是char,一個是int
int place(char board[][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 who_win(char board[][COL], int row, int col)//判斷
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && 
			board[i][1] == board[i][2] && board[i][2] != ' ')
			return board[i][0];
	}//判斷行

	for (j = 0; j < row; j++)
	{
		if (board[0][j] == board[1][j] &&
			board[1][j] == board[2][j] && board[2][j] != ' ')
			return board[0][j];
	}//判斷列

	if (board[0][0] == board[1][1] && 
		board[1][1] == board[2][2] && board[2][2] != ' ')
		return board[0][0];//判斷正斜

	if (board[0][2] == board[1][1] && 
		board[1][1] == board[2][0] && board[2][0] != ' ')
		return board[0][2];//判斷反斜

	if (place(board, ROW, COL) == 1)
		return 'Q';//判斷和局

	return 'C';//預設選項
}
           

6.重回game函數

經過game.c中各函數的一頓操作,最終由判斷輸赢函數攜帶傳回值回到game函數進行判斷
三子棋——年輕人的第一款小遊戲前言正文總結 

效果展示

讓我們直接來看看效果如何:
三子棋——年輕人的第一款小遊戲前言正文總結 
可以看到三種情況都能實作,現在隻需要将代碼進行優化,主要是優化輸赢判斷部分,使其相容性更強,以後在玩五子棋時能沿用這套方案。 
 下面我将展示功能實作函數(game.c)的全部代碼:
#define _CRT_SECURE_NO_WARNINGS 1	
#include"game.h"

void init_board(char board[][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 display_board(char board[][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 player_move(char board[][COL], int row, int col)//玩家走
{
	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 computer_move(char board[][COL], int row, int col)//電腦走
{
	printf("輪到電腦落子:>");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	printf("電腦已落子\n");
}

int place(char board[][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 who_win(char board[][COL], int row, int col)//判斷
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && 
			board[i][1] == board[i][2] && board[i][2] != ' ')
			return board[i][0];
	}//判斷行

	for (j = 0; j < row; j++)
	{
		if (board[0][j] == board[1][j] &&
			board[1][j] == board[2][j] && board[2][j] != ' ')
			return board[0][j];
	}//判斷列

	if (board[0][0] == board[1][1] && 
		board[1][1] == board[2][2] && board[2][2] != ' ')
		return board[0][0];//判斷正斜

	if (board[0][2] == board[1][1] && 
		board[1][1] == board[2][0] && board[2][0] != ' ')
		return board[0][2];//判斷反斜

	if (place(board, ROW, COL) == 1)
		return 'Q';//判斷和局

	return 'C';//預設選項
}
           

總結 

  我們本次三子棋之旅到這就要結束了,說實在的,三子棋這段代碼蘊含邏輯比較簡單,唯一需要注意的就是棋盤列印和電腦随機值,隻有了解透徹了,代碼敲起來才能得心應手!

三子棋——年輕人的第一款小遊戲前言正文總結 

繼續閱讀